Path: blob/a-new-beginning/SharedDependencies/Sources/nihstro/parser_assembly/flowcontrol.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/fusion/include/swap.hpp>33#include <boost/phoenix/core/reference.hpp>34#include <boost/spirit/include/qi.hpp>3536#include "nihstro/parser_assembly.h"37#include "nihstro/parser_assembly_private.h"3839#include "nihstro/shader_binary.h"40#include "nihstro/shader_bytecode.h"4142namespace spirit = boost::spirit;43namespace qi = boost::spirit::qi;44namespace ascii = boost::spirit::qi::ascii;45namespace phoenix = boost::phoenix;4647using spirit::_1;48using spirit::_2;49using spirit::_3;50using spirit::_4;5152using namespace nihstro;5354// Adapt parser data structures for use with boost::spirit5556BOOST_FUSION_ADAPT_STRUCT(57ConditionInput,58(bool, invert)59(Identifier, identifier)60(boost::optional<InputSwizzlerMask>, swizzler_mask)61)6263BOOST_FUSION_ADAPT_STRUCT(64Condition,65(ConditionInput, input1)66(Instruction::FlowControlType::Op, op)67(ConditionInput, input2)68)6970BOOST_FUSION_ADAPT_STRUCT(71FlowControlInstruction,72(OpCode, opcode)73(std::string, target_label)74(boost::optional<std::string>, return_label)75(boost::optional<Condition>, condition)76)7778// Manually define a swap() overload for qi::hold to work.79namespace boost {80namespace spirit {81void swap(nihstro::Condition& a, nihstro::Condition& b) {82boost::fusion::swap(a, b);83}84}85}8687template<>88FlowControlParser<ParserIterator>::FlowControlParser(const ParserContext& context)89: FlowControlParser::base_type(flow_control_instruction),90common(context),91opcodes_flowcontrol(common.opcodes_flowcontrol),92expression(common.expression),93identifier(common.identifier),94swizzle_mask(common.swizzle_mask),95end_of_statement(common.end_of_statement),96diagnostics(common.diagnostics) {9798condition_ops.add99( "&&", ConditionOp::And )100( "||", ConditionOp::Or );101102// Setup rules103104auto blank_rule = qi::omit[ascii::blank];105auto label_rule = identifier.alias();106107opcode[0] = qi::lexeme[qi::no_case[opcodes_flowcontrol[0]] >> &ascii::space];108opcode[1] = qi::lexeme[qi::no_case[opcodes_flowcontrol[1]] >> &ascii::space];109110condition_op = qi::lexeme[condition_ops];111112negation = qi::matches[qi::lit("!")];113114condition_input = negation >> identifier >> -(qi::lit('.') > swizzle_mask);115116// May be a condition involving the conditional codes, or a reference to a uniform117// TODO: Make sure we use qi::hold wherever necessary118condition = qi::hold[condition_input >> condition_op >> condition_input]119| (condition_input >> qi::attr(ConditionOp::JustX) >> qi::attr(ConditionInput{}));120121// if condition122instr[0] = opcode[0]123>> qi::attr("__dummy") // Dummy label (set indirectly using else,endif, or endloop pseudo-instructions)124>> qi::attr(boost::optional<std::string>()) // Dummy return label125>> condition;126127// call target_label until return_label if condition128instr[1] = opcode[1]129>> label_rule130>> -(qi::no_skip[(blank_rule >> qi::lit("until")) > blank_rule] >> label_rule)131>> -(qi::no_skip[(blank_rule >> qi::lit("if")) > blank_rule] >> condition);132133flow_control_instruction %= (instr[0] | instr[1]) > end_of_statement;134135// Error handling136// BOOST_SPIRIT_DEBUG_NODE(opcode[0]);137// BOOST_SPIRIT_DEBUG_NODE(opcode[1]);138// BOOST_SPIRIT_DEBUG_NODE(negation);139// BOOST_SPIRIT_DEBUG_NODE(condition_op);140// BOOST_SPIRIT_DEBUG_NODE(condition_input);141// BOOST_SPIRIT_DEBUG_NODE(condition);142143// BOOST_SPIRIT_DEBUG_NODE(instr[0]);144// BOOST_SPIRIT_DEBUG_NODE(instr[1]);145// BOOST_SPIRIT_DEBUG_NODE(flow_control_instruction);146147// qi::on_error<qi::fail>(flow_control_instruction, error_handler(phoenix::ref(diagnostics), _1, _2, _3, _4));148}149150151