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/common.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/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
/**
62
* Implementation of transform_attribute from std::vector<InputSwizzlerMask::Component> to InputSwizzlerMask.
63
* This eases swizzle mask parsing a lot.
64
*/
65
namespace boost { namespace spirit { namespace traits {
66
template<>
67
struct transform_attribute<InputSwizzlerMask, std::vector<InputSwizzlerMask::Component>, qi::domain>
68
{
69
using Exposed = InputSwizzlerMask;
70
71
using type = std::vector<InputSwizzlerMask::Component>;
72
73
static void post(Exposed& val, const type& attr) {
74
val.num_components = (int)attr.size();
75
for (size_t i = 0; i < attr.size(); ++i)
76
val.components[i] = attr[i];
77
}
78
79
static type pre(Exposed& val) {
80
type vec;
81
for (int i = 0; i < val.num_components; ++i)
82
vec.push_back(val.components[i]);
83
return vec;
84
}
85
86
static void fail(Exposed&) { }
87
};
88
}}} // namespaces
89
90
template<>
91
CommonRules<ParserIterator>::CommonRules(const ParserContext& context) {
92
// Setup symbol table
93
opcodes_trivial.add
94
( "nop", OpCode::Id::NOP )
95
( "end", OpCode::Id::END )
96
( "emit", OpCode::Id::EMIT )
97
( "else", OpCode::Id::ELSE )
98
( "endif", OpCode::Id::ENDIF )
99
( "endloop", OpCode::Id::ENDLOOP );
100
101
opcodes_float[0].add
102
( "mova", OpCode::Id::MOVA );
103
104
opcodes_float[1].add
105
( "exp", OpCode::Id::EX2 )
106
( "log", OpCode::Id::LG2 )
107
( "lit", OpCode::Id::LIT )
108
( "flr", OpCode::Id::FLR )
109
( "rcp", OpCode::Id::RCP )
110
( "rsq", OpCode::Id::RSQ )
111
( "mov", OpCode::Id::MOV );
112
opcodes_float[2].add
113
( "add", OpCode::Id::ADD )
114
( "dp3", OpCode::Id::DP3 )
115
( "dp4", OpCode::Id::DP4 )
116
( "dph", OpCode::Id::DPH )
117
( "dst", OpCode::Id::DST )
118
( "mul", OpCode::Id::MUL )
119
( "sge", OpCode::Id::SGE )
120
( "slt", OpCode::Id::SLT )
121
( "max", OpCode::Id::MAX )
122
( "min", OpCode::Id::MIN );
123
opcodes_float[3].add
124
( "mad", OpCode::Id::MAD );
125
126
opcodes_compare.add
127
( "cmp", OpCode::Id::CMP );
128
129
opcodes_flowcontrol[0].add
130
( "break", OpCode::Id::BREAK )
131
( "breakc", OpCode::Id::BREAKC )
132
( "if", OpCode::Id::GEN_IF )
133
( "loop", OpCode::Id::LOOP );
134
opcodes_flowcontrol[1].add
135
( "jmp", OpCode::Id::GEN_JMP )
136
( "call", OpCode::Id::GEN_CALL );
137
138
opcodes_setemit.add
139
( "setemitraw", OpCode::Id::SETEMIT );
140
141
signs.add( "+", +1)
142
( "-", -1);
143
144
// TODO: Add rgba/stq masks
145
swizzlers.add
146
( "x", InputSwizzlerMask::x )
147
( "y", InputSwizzlerMask::y )
148
( "z", InputSwizzlerMask::z )
149
( "w", InputSwizzlerMask::w );
150
151
// TODO: Make sure this is followed by a space or *some* separator
152
// TODO: Use qi::repeat(1,4)(swizzlers) instead of Kleene [failed to work when I tried, so make this work!]
153
// TODO: Use qi::lexeme[swizzlers] [crashed when I tried, so make this work!]
154
swizzle_mask = qi::attr_cast<InputSwizzlerMask, std::vector<InputSwizzlerMask::Component>>(*swizzlers);
155
156
identifier = qi::lexeme[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z0-9_")];
157
peek_identifier = &identifier;
158
159
uint_after_sign = qi::uint_; // TODO: NOT dot (or alphanum) after this to prevent floats..., TODO: overflows?
160
sign_with_uint = signs > uint_after_sign;
161
index_expression_first_term = (qi::attr(+1) >> qi::uint_) | (peek_identifier > identifier);
162
index_expression_following_terms = ((qi::lit('+') >> peek_identifier) > identifier) | sign_with_uint;
163
index_expression = (-index_expression_first_term) // the first element has an optional sign
164
>> (*index_expression_following_terms); // following elements have a mandatory sign
165
166
expression = ((-signs) > peek_identifier > identifier) >> (-(qi::lit('[') > index_expression > qi::lit(']'))) >> *(qi::lit('.') > swizzle_mask);
167
168
end_of_statement = qi::omit[qi::eol | qi::eoi];
169
170
// Error handling
171
// BOOST_SPIRIT_DEBUG_NODE(identifier);
172
// BOOST_SPIRIT_DEBUG_NODE(uint_after_sign);
173
// BOOST_SPIRIT_DEBUG_NODE(index_expression);
174
// BOOST_SPIRIT_DEBUG_NODE(peek_identifier);
175
// BOOST_SPIRIT_DEBUG_NODE(expression);
176
// BOOST_SPIRIT_DEBUG_NODE(swizzle_mask);
177
// BOOST_SPIRIT_DEBUG_NODE(end_of_statement);
178
179
diagnostics.Add(swizzle_mask.name(), "Expected swizzle mask after period");
180
diagnostics.Add(peek_identifier.name(), "Expected identifier");
181
diagnostics.Add(uint_after_sign.name(), "Expected integer number after sign");
182
diagnostics.Add(index_expression.name(), "Expected index expression between '[' and ']'");
183
diagnostics.Add(expression.name(), "Expected expression of a known identifier");
184
diagnostics.Add(end_of_statement.name(), "Expected end of statement");
185
}
186
187