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.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/phoenix/core/reference.hpp>
34
#include <boost/spirit/include/qi.hpp>
35
36
#include "nihstro/parser_assembly.h"
37
#include "nihstro/parser_assembly_private.h"
38
39
#include "nihstro/shader_binary.h"
40
#include "nihstro/shader_bytecode.h"
41
42
namespace spirit = boost::spirit;
43
namespace qi = boost::spirit::qi;
44
namespace ascii = boost::spirit::qi::ascii;
45
namespace phoenix = boost::phoenix;
46
47
using spirit::_1;
48
using spirit::_2;
49
using spirit::_3;
50
using spirit::_4;
51
52
using namespace nihstro;
53
54
// Adapt parser data structures for use with boost::spirit
55
56
BOOST_FUSION_ADAPT_STRUCT(
57
SetEmitInstruction::Flags,
58
(boost::optional<bool>, primitive_flag)
59
(boost::optional<bool>, invert_flag)
60
)
61
62
BOOST_FUSION_ADAPT_STRUCT(
63
SetEmitInstruction,
64
(OpCode, opcode)
65
(unsigned, vertex_id)
66
(SetEmitInstruction::Flags, flags)
67
)
68
69
phoenix::function<ErrorHandler> error_handler;
70
71
template<typename Iterator, bool require_end_of_line>
72
TrivialOpParser<Iterator, require_end_of_line>::TrivialOpParser(const ParserContext& context)
73
: TrivialOpParser::base_type(trivial_instruction),
74
common(context),
75
opcodes_trivial(common.opcodes_trivial),
76
opcodes_compare(common.opcodes_compare),
77
opcodes_float(common.opcodes_float),
78
opcodes_flowcontrol(common.opcodes_flowcontrol),
79
end_of_statement(common.end_of_statement),
80
diagnostics(common.diagnostics) {
81
82
// Setup rules
83
if (require_end_of_line) {
84
opcode = qi::no_case[qi::lexeme[opcodes_trivial >> &ascii::space]];
85
trivial_instruction = opcode > end_of_statement;
86
} else {
87
opcode = qi::no_case[qi::lexeme[opcodes_trivial | opcodes_compare | opcodes_float[0]
88
| opcodes_float[1] | opcodes_float[2] | opcodes_float[3]
89
| opcodes_flowcontrol[0] | opcodes_flowcontrol[1] >> &ascii::space]];
90
trivial_instruction = opcode;
91
}
92
93
// Error handling
94
BOOST_SPIRIT_DEBUG_NODE(opcode);
95
BOOST_SPIRIT_DEBUG_NODE(trivial_instruction);
96
97
qi::on_error<qi::fail>(trivial_instruction, error_handler(phoenix::ref(diagnostics), _1, _2, _3, _4));
98
}
99
100
template<typename Iterator>
101
SetEmitParser<Iterator>::SetEmitParser(const ParserContext& context)
102
: SetEmitParser::base_type(setemit_instruction),
103
common(context),
104
opcodes_setemit(common.opcodes_setemit),
105
end_of_statement(common.end_of_statement),
106
diagnostics(common.diagnostics) {
107
108
// Setup rules
109
110
auto comma_rule = qi::lit(',');
111
112
opcode = qi::lexeme[qi::no_case[opcodes_setemit] >> &ascii::space];
113
114
vertex_id = qi::uint_;
115
prim_flag = qi::lit("prim") >> &(!ascii::alnum) >> qi::attr(true);
116
inv_flag = qi::lit("inv") >> &(!ascii::alnum) >> qi::attr(true);
117
flags = ((comma_rule >> prim_flag) ^ (comma_rule >> inv_flag));
118
119
setemit_instruction = ((opcode >> vertex_id) >> (flags | qi::attr(SetEmitInstruction::Flags{}))) > end_of_statement;
120
121
// Error handling
122
BOOST_SPIRIT_DEBUG_NODE(opcode);
123
BOOST_SPIRIT_DEBUG_NODE(vertex_id);
124
BOOST_SPIRIT_DEBUG_NODE(prim_flag);
125
BOOST_SPIRIT_DEBUG_NODE(inv_flag);
126
BOOST_SPIRIT_DEBUG_NODE(flags);
127
BOOST_SPIRIT_DEBUG_NODE(setemit_instruction);
128
129
qi::on_error<qi::fail>(setemit_instruction, error_handler(phoenix::ref(diagnostics), _1, _2, _3, _4));
130
}
131
132
template<typename Iterator>
133
LabelParser<Iterator>::LabelParser(const ParserContext& context)
134
: LabelParser::base_type(label), common(context),
135
end_of_statement(common.end_of_statement),
136
identifier(common.identifier),
137
diagnostics(common.diagnostics) {
138
139
label = identifier >> qi::lit(':') > end_of_statement;
140
141
BOOST_SPIRIT_DEBUG_NODE(label);
142
143
qi::on_error<qi::fail>(label, error_handler(phoenix::ref(diagnostics), _1, _2, _3, _4));
144
}
145
template struct LabelParser<ParserIterator>;
146
147
148
struct Parser::ParserImpl {
149
using Iterator = SourceTreeIterator;
150
151
ParserImpl(const ParserContext& context) : label(context), plain_instruction(context),
152
simple_instruction(context), instruction(context),
153
compare(context), flow_control(context),
154
setemit(context), declaration(context) {
155
}
156
157
unsigned Skip(Iterator& begin, Iterator end) {
158
unsigned lines_skipped = 0;
159
do {
160
parse(begin, end, skipper);
161
lines_skipped++;
162
} while (boost::spirit::qi::parse(begin, end, boost::spirit::qi::eol));
163
164
return --lines_skipped;
165
}
166
167
void SkipSingleLine(Iterator& begin, Iterator end) {
168
qi::parse(begin, end, *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi));
169
}
170
171
bool ParseLabel(Iterator& begin, Iterator end, StatementLabel* content) {
172
assert(content != nullptr);
173
174
return phrase_parse(begin, end, label, skipper, *content);
175
}
176
177
bool ParseOpCode(Iterator& begin, Iterator end, OpCode* content) {
178
assert(content != nullptr);
179
180
return phrase_parse(begin, end, plain_instruction, skipper, *content);
181
}
182
183
bool ParseSimpleInstruction(Iterator& begin, Iterator end, OpCode* content) {
184
assert(content != nullptr);
185
186
return phrase_parse(begin, end, simple_instruction, skipper, *content);
187
}
188
189
bool ParseFloatOp(Iterator& begin, Iterator end, FloatOpInstruction* content) {
190
assert(content != nullptr);
191
192
return phrase_parse(begin, end, instruction, skipper, *content);
193
}
194
195
bool ParseCompare(Iterator& begin, Iterator end, CompareInstruction* content) {
196
assert(content != nullptr);
197
198
return phrase_parse(begin, end, compare, skipper, *content);
199
}
200
201
bool ParseFlowControl(Iterator& begin, Iterator end, FlowControlInstruction* content) {
202
assert(content != nullptr);
203
204
return phrase_parse(begin, end, flow_control, skipper, *content);
205
}
206
207
bool ParseSetEmit(Iterator& begin, Iterator end, SetEmitInstruction* content) {
208
assert(content != nullptr);
209
210
return phrase_parse(begin, end, setemit, skipper, *content);
211
}
212
213
bool ParseDeclaration(Iterator& begin, Iterator end, StatementDeclaration* content) {
214
assert(content != nullptr);
215
216
return phrase_parse(begin, end, declaration, skipper, *content);
217
}
218
219
private:
220
AssemblySkipper<Iterator> skipper;
221
222
LabelParser<Iterator> label;
223
TrivialOpParser<Iterator, false> plain_instruction;
224
TrivialOpParser<Iterator, true> simple_instruction;
225
FloatOpParser<Iterator> instruction;
226
CompareParser<Iterator> compare;
227
FlowControlParser<Iterator> flow_control;
228
SetEmitParser<Iterator> setemit;
229
DeclarationParser<Iterator> declaration;
230
};
231
232
233
234
Parser::Parser(const ParserContext& context) : impl(new ParserImpl(context)) {
235
};
236
237
Parser::~Parser() {
238
}
239
240
unsigned Parser::Skip(Iterator& begin, Iterator end) {
241
return impl->Skip(begin, end);
242
}
243
244
void Parser::SkipSingleLine(Iterator& begin, Iterator end) {
245
impl->SkipSingleLine(begin, end);
246
}
247
248
bool Parser::ParseLabel(Iterator& begin, Iterator end, StatementLabel* label) {
249
return impl->ParseLabel(begin, end, label);
250
}
251
252
bool Parser::ParseOpCode(Iterator& begin, Iterator end, OpCode* opcode) {
253
return impl->ParseOpCode(begin, end, opcode);
254
}
255
256
bool Parser::ParseSimpleInstruction(Iterator& begin, Iterator end, OpCode* opcode) {
257
return impl->ParseSimpleInstruction(begin, end, opcode);
258
}
259
260
bool Parser::ParseFloatOp(Iterator& begin, Iterator end, FloatOpInstruction* instruction) {
261
return impl->ParseFloatOp(begin, end, instruction);
262
}
263
264
bool Parser::ParseCompare(Iterator& begin, Iterator end, CompareInstruction* content) {
265
return impl->ParseCompare(begin, end, content);
266
}
267
268
bool Parser::ParseFlowControl(Iterator& begin, Iterator end, FlowControlInstruction* content) {
269
return impl->ParseFlowControl(begin, end, content);
270
}
271
272
bool Parser::ParseSetEmit(Iterator& begin, Iterator end, SetEmitInstruction* content) {
273
return impl->ParseSetEmit(begin, end, content);
274
}
275
276
bool Parser::ParseDeclaration(Iterator& begin, Iterator end, StatementDeclaration* declaration) {
277
return impl->ParseDeclaration(begin, end, declaration);
278
}
279
280