1 // Copyright 2014 Tony Wasserka
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the owner nor the names of its contributors may
13 // be used to endorse or promote products derived from this software
14 // without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
29 // Enable this for detailed XML overview of parser results
30 // #define BOOST_SPIRIT_DEBUG
31
32 #include <boost/fusion/include/adapt_struct.hpp>
33 #include <boost/spirit/include/qi.hpp>
34
35 #include "nihstro/parser_assembly.h"
36 #include "nihstro/parser_assembly_private.h"
37
38 #include "nihstro/shader_binary.h"
39 #include "nihstro/shader_bytecode.h"
40
41 namespace spirit = boost::spirit;
42 namespace qi = boost::spirit::qi;
43 namespace ascii = boost::spirit::qi::ascii;
44 namespace phoenix = boost::phoenix;
45
46 using spirit::_1;
47 using spirit::_2;
48 using spirit::_3;
49 using spirit::_4;
50
51 using namespace nihstro;
52
53 // Adapt parser data structures for use with boost::spirit
54
55 /*BOOST_FUSION_ADAPT_STRUCT(
56 IntegerWithSign,
57 (int, sign)
58 (unsigned, value)
59 )
60 */
61 BOOST_FUSION_ADAPT_STRUCT(
62 CompareInstruction,
63 (OpCode, opcode)
64 (std::vector<Expression>, arguments)
65 (std::vector<Instruction::Common::CompareOpType::Op>, ops)
66 )
67
68 template<>
CompareParser(const ParserContext & context)69 CompareParser<ParserIterator>::CompareParser(const ParserContext& context)
70 : CompareParser::base_type(instruction),
71 common(context),
72 opcodes_compare(common.opcodes_compare),
73 expression(common.expression),
74 end_of_statement(common.end_of_statement),
75 diagnostics(common.diagnostics) {
76
77 // TODO: Will this properly match >= ?
78 compare_ops.add
79 ( "==", CompareOp::Equal )
80 ( "!=", CompareOp::NotEqual )
81 ( "<", CompareOp::LessThan )
82 ( "<=", CompareOp::LessEqual )
83 ( ">", CompareOp::GreaterThan )
84 ( ">=", CompareOp::GreaterEqual );
85
86 // Setup rules
87
88 auto comma_rule = qi::lit(',');
89
90 opcode = qi::no_case[qi::lexeme[opcodes_compare >> &ascii::space]];
91 compare_op = qi::lexeme[compare_ops];
92
93 // cmp src1, src2, op1, op2
94 // TODO: Also allow "cmp src1 op1 src2, src1 op2 src2"
95 two_ops = compare_op > comma_rule > compare_op;
96 two_expressions = expression > comma_rule > expression;
97 instr[0] = opcode > two_expressions > comma_rule > two_ops;
98
99 instruction = instr[0] > end_of_statement;
100
101 // Error handling
102 BOOST_SPIRIT_DEBUG_NODE(instr[0]);
103 BOOST_SPIRIT_DEBUG_NODE(instruction);
104
105 qi::on_error<qi::fail>(instruction, error_handler(phoenix::ref(diagnostics), _1, _2, _3, _4));
106 }
107