Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/nihstro/parser_assembly/flowcontrol.cpp
2 views
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/fusion/include/swap.hpp>
34
#include <boost/phoenix/core/reference.hpp>
35
#include <boost/spirit/include/qi.hpp>
36
37
#include "nihstro/parser_assembly.h"
38
#include "nihstro/parser_assembly_private.h"
39
40
#include "nihstro/shader_binary.h"
41
#include "nihstro/shader_bytecode.h"
42
43
namespace spirit = boost::spirit;
44
namespace qi = boost::spirit::qi;
45
namespace ascii = boost::spirit::qi::ascii;
46
namespace phoenix = boost::phoenix;
47
48
using spirit::_1;
49
using spirit::_2;
50
using spirit::_3;
51
using spirit::_4;
52
53
using namespace nihstro;
54
55
// Adapt parser data structures for use with boost::spirit
56
57
BOOST_FUSION_ADAPT_STRUCT(
58
ConditionInput,
59
(bool, invert)
60
(Identifier, identifier)
61
(boost::optional<InputSwizzlerMask>, swizzler_mask)
62
)
63
64
BOOST_FUSION_ADAPT_STRUCT(
65
Condition,
66
(ConditionInput, input1)
67
(Instruction::FlowControlType::Op, op)
68
(ConditionInput, input2)
69
)
70
71
BOOST_FUSION_ADAPT_STRUCT(
72
FlowControlInstruction,
73
(OpCode, opcode)
74
(std::string, target_label)
75
(boost::optional<std::string>, return_label)
76
(boost::optional<Condition>, condition)
77
)
78
79
// Manually define a swap() overload for qi::hold to work.
80
namespace boost {
81
namespace spirit {
82
void swap(nihstro::Condition& a, nihstro::Condition& b) {
83
boost::fusion::swap(a, b);
84
}
85
}
86
}
87
88
template<>
89
FlowControlParser<ParserIterator>::FlowControlParser(const ParserContext& context)
90
: FlowControlParser::base_type(flow_control_instruction),
91
common(context),
92
opcodes_flowcontrol(common.opcodes_flowcontrol),
93
expression(common.expression),
94
identifier(common.identifier),
95
swizzle_mask(common.swizzle_mask),
96
end_of_statement(common.end_of_statement),
97
diagnostics(common.diagnostics) {
98
99
condition_ops.add
100
( "&&", ConditionOp::And )
101
( "||", ConditionOp::Or );
102
103
// Setup rules
104
105
auto blank_rule = qi::omit[ascii::blank];
106
auto label_rule = identifier.alias();
107
108
opcode[0] = qi::lexeme[qi::no_case[opcodes_flowcontrol[0]] >> &ascii::space];
109
opcode[1] = qi::lexeme[qi::no_case[opcodes_flowcontrol[1]] >> &ascii::space];
110
111
condition_op = qi::lexeme[condition_ops];
112
113
negation = qi::matches[qi::lit("!")];
114
115
condition_input = negation >> identifier >> -(qi::lit('.') > swizzle_mask);
116
117
// May be a condition involving the conditional codes, or a reference to a uniform
118
// TODO: Make sure we use qi::hold wherever necessary
119
condition = qi::hold[condition_input >> condition_op >> condition_input]
120
| (condition_input >> qi::attr(ConditionOp::JustX) >> qi::attr(ConditionInput{}));
121
122
// if condition
123
instr[0] = opcode[0]
124
>> qi::attr("__dummy") // Dummy label (set indirectly using else,endif, or endloop pseudo-instructions)
125
>> qi::attr(boost::optional<std::string>()) // Dummy return label
126
>> condition;
127
128
// call target_label until return_label if condition
129
instr[1] = opcode[1]
130
>> label_rule
131
>> -(qi::no_skip[(blank_rule >> qi::lit("until")) > blank_rule] >> label_rule)
132
>> -(qi::no_skip[(blank_rule >> qi::lit("if")) > blank_rule] >> condition);
133
134
flow_control_instruction %= (instr[0] | instr[1]) > end_of_statement;
135
136
// Error handling
137
// BOOST_SPIRIT_DEBUG_NODE(opcode[0]);
138
// BOOST_SPIRIT_DEBUG_NODE(opcode[1]);
139
// BOOST_SPIRIT_DEBUG_NODE(negation);
140
// BOOST_SPIRIT_DEBUG_NODE(condition_op);
141
// BOOST_SPIRIT_DEBUG_NODE(condition_input);
142
// BOOST_SPIRIT_DEBUG_NODE(condition);
143
144
// BOOST_SPIRIT_DEBUG_NODE(instr[0]);
145
// BOOST_SPIRIT_DEBUG_NODE(instr[1]);
146
// BOOST_SPIRIT_DEBUG_NODE(flow_control_instruction);
147
148
// qi::on_error<qi::fail>(flow_control_instruction, error_handler(phoenix::ref(diagnostics), _1, _2, _3, _4));
149
}
150
151