Path: blob/a-new-beginning/SharedDependencies/Sources/nihstro/parser_assembly/common.cpp
2 views
// Copyright 2014 Tony Wasserka1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright7// notice, this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright9// notice, this list of conditions and the following disclaimer in the10// documentation and/or other materials provided with the distribution.11// * Neither the name of the owner nor the names of its contributors may12// be used to endorse or promote products derived from this software13// without specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.262728// Enable this for detailed XML overview of parser results29// #define BOOST_SPIRIT_DEBUG3031#include <boost/fusion/include/adapt_struct.hpp>32#include <boost/spirit/include/qi.hpp>3334#include "nihstro/parser_assembly.h"35#include "nihstro/parser_assembly_private.h"3637#include "nihstro/shader_binary.h"38#include "nihstro/shader_bytecode.h"3940namespace spirit = boost::spirit;41namespace qi = boost::spirit::qi;42namespace ascii = boost::spirit::qi::ascii;43namespace phoenix = boost::phoenix;4445using spirit::_1;46using spirit::_2;47using spirit::_3;48using spirit::_4;4950using namespace nihstro;5152// Adapt parser data structures for use with boost::spirit5354BOOST_FUSION_ADAPT_STRUCT(55IntegerWithSign,56(int, sign)57(unsigned, value)58)5960/**61* Implementation of transform_attribute from std::vector<InputSwizzlerMask::Component> to InputSwizzlerMask.62* This eases swizzle mask parsing a lot.63*/64namespace boost { namespace spirit { namespace traits {65template<>66struct transform_attribute<InputSwizzlerMask, std::vector<InputSwizzlerMask::Component>, qi::domain>67{68using Exposed = InputSwizzlerMask;6970using type = std::vector<InputSwizzlerMask::Component>;7172static void post(Exposed& val, const type& attr) {73val.num_components = (int)attr.size();74for (size_t i = 0; i < attr.size(); ++i)75val.components[i] = attr[i];76}7778static type pre(Exposed& val) {79type vec;80for (int i = 0; i < val.num_components; ++i)81vec.push_back(val.components[i]);82return vec;83}8485static void fail(Exposed&) { }86};87}}} // namespaces8889template<>90CommonRules<ParserIterator>::CommonRules(const ParserContext& context) {91// Setup symbol table92opcodes_trivial.add93( "nop", OpCode::Id::NOP )94( "end", OpCode::Id::END )95( "emit", OpCode::Id::EMIT )96( "else", OpCode::Id::ELSE )97( "endif", OpCode::Id::ENDIF )98( "endloop", OpCode::Id::ENDLOOP );99100opcodes_float[0].add101( "mova", OpCode::Id::MOVA );102103opcodes_float[1].add104( "exp", OpCode::Id::EX2 )105( "log", OpCode::Id::LG2 )106( "lit", OpCode::Id::LIT )107( "flr", OpCode::Id::FLR )108( "rcp", OpCode::Id::RCP )109( "rsq", OpCode::Id::RSQ )110( "mov", OpCode::Id::MOV );111opcodes_float[2].add112( "add", OpCode::Id::ADD )113( "dp3", OpCode::Id::DP3 )114( "dp4", OpCode::Id::DP4 )115( "dph", OpCode::Id::DPH )116( "dst", OpCode::Id::DST )117( "mul", OpCode::Id::MUL )118( "sge", OpCode::Id::SGE )119( "slt", OpCode::Id::SLT )120( "max", OpCode::Id::MAX )121( "min", OpCode::Id::MIN );122opcodes_float[3].add123( "mad", OpCode::Id::MAD );124125opcodes_compare.add126( "cmp", OpCode::Id::CMP );127128opcodes_flowcontrol[0].add129( "break", OpCode::Id::BREAK )130( "breakc", OpCode::Id::BREAKC )131( "if", OpCode::Id::GEN_IF )132( "loop", OpCode::Id::LOOP );133opcodes_flowcontrol[1].add134( "jmp", OpCode::Id::GEN_JMP )135( "call", OpCode::Id::GEN_CALL );136137opcodes_setemit.add138( "setemitraw", OpCode::Id::SETEMIT );139140signs.add( "+", +1)141( "-", -1);142143// TODO: Add rgba/stq masks144swizzlers.add145( "x", InputSwizzlerMask::x )146( "y", InputSwizzlerMask::y )147( "z", InputSwizzlerMask::z )148( "w", InputSwizzlerMask::w );149150// TODO: Make sure this is followed by a space or *some* separator151// TODO: Use qi::repeat(1,4)(swizzlers) instead of Kleene [failed to work when I tried, so make this work!]152// TODO: Use qi::lexeme[swizzlers] [crashed when I tried, so make this work!]153swizzle_mask = qi::attr_cast<InputSwizzlerMask, std::vector<InputSwizzlerMask::Component>>(*swizzlers);154155identifier = qi::lexeme[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z0-9_")];156peek_identifier = &identifier;157158uint_after_sign = qi::uint_; // TODO: NOT dot (or alphanum) after this to prevent floats..., TODO: overflows?159sign_with_uint = signs > uint_after_sign;160index_expression_first_term = (qi::attr(+1) >> qi::uint_) | (peek_identifier > identifier);161index_expression_following_terms = ((qi::lit('+') >> peek_identifier) > identifier) | sign_with_uint;162index_expression = (-index_expression_first_term) // the first element has an optional sign163>> (*index_expression_following_terms); // following elements have a mandatory sign164165expression = ((-signs) > peek_identifier > identifier) >> (-(qi::lit('[') > index_expression > qi::lit(']'))) >> *(qi::lit('.') > swizzle_mask);166167end_of_statement = qi::omit[qi::eol | qi::eoi];168169// Error handling170// BOOST_SPIRIT_DEBUG_NODE(identifier);171// BOOST_SPIRIT_DEBUG_NODE(uint_after_sign);172// BOOST_SPIRIT_DEBUG_NODE(index_expression);173// BOOST_SPIRIT_DEBUG_NODE(peek_identifier);174// BOOST_SPIRIT_DEBUG_NODE(expression);175// BOOST_SPIRIT_DEBUG_NODE(swizzle_mask);176// BOOST_SPIRIT_DEBUG_NODE(end_of_statement);177178diagnostics.Add(swizzle_mask.name(), "Expected swizzle mask after period");179diagnostics.Add(peek_identifier.name(), "Expected identifier");180diagnostics.Add(uint_after_sign.name(), "Expected integer number after sign");181diagnostics.Add(index_expression.name(), "Expected index expression between '[' and ']'");182diagnostics.Add(expression.name(), "Expected expression of a known identifier");183diagnostics.Add(end_of_statement.name(), "Expected end of statement");184}185186187