require_relative 'ast_building' require_relative 'regex_repr' # The purpose of a ASTBuilder is to build piece by piece an AST # (Abstract Syntax Tree) from a sequence of input tokens and # visit events produced by walking over a GFGParsing object. # Uses the Builder GoF pattern. # The Builder pattern creates a complex object # (say, a parse tree) from simpler objects (terminal and non-terminal # nodes) and using a step by step approach. class ASTBuilder < Rley::Parser::ParseTreeBuilder include ASTBuilding Terminal2NodeClass = { }.freeze protected # Overriding method. # Factory method for creating a node object for the given # input token. # @param aTerminal [Terminal] Terminal symbol associated with the token # @param aTokenPosition [Integer] Position of token in the input stream # @param aToken [Token] The input token def new_leaf_node(aProduction, aTerminal, aTokenPosition, aToken) node = Rley::PTree::TerminalNode.new(aToken, aTokenPosition) return node end # Method to override. # Factory method for creating a parent node object. # @param aProduction [Production] Production rule # @param aRange [Range] Range of tokens matched by the rule # @param theTokens [Array] The input tokens # @param theChildren [Array] Children nodes (one per rhs symbol) def new_parent_node(aProduction, aRange, theTokens, theChildren) node = case aProduction.name when 'srl_0' # rule 'srl' => 'quantifier' return_first_child(aRange, theTokens, theChildren) when 'quantifier_0' # rule 'quantifier' => 'ONCE' multiplicity(1, 1) when 'quantifier_1' # rule 'quantifier' => 'TWICE' multiplicity(2, 2) when 'quantifier_2' # rule 'quantifier' => %w[EXACTLY count TIMES] reduce_quantifier_2(aProduction, aRange, theTokens, theChildren) when 'quantifier_3' # rule 'quantifier' => %w[BETWEEN count AND count times_suffix] reduce_quantifier_3(aProduction, aRange, theTokens, theChildren) when 'quantifier_4' # rule 'quantifier' => 'OPTIONAL' multiplicity(0, 1) when 'quantifier_5' # rule 'quantifier' => %w[ONCE OR MORE] multiplicity(1, :more) when 'quantifier_6' # rule 'quantifier' => %w[NEVER OR MORE] multiplicity(0, :more) when 'quantifier_7' # rule 'quantifier' => %w[AT LEAST count TIMES] reduce_quantifier_7(aProduction, aRange, theTokens, theChildren) when 'count_0', 'count_1' return_first_child(aRange, theTokens, theChildren) when 'times_suffix_0', 'times_suffix_1' nil else raise StandardError, "Don't know production #{aProduction.name}" end return node end def multiplicity(lowerBound, upperBound) return SRL::Regex::Multiplicity.new(lowerBound, upperBound, :greedy) end # rule 'quantifier' => %w[EXACTLY count TIMES] def reduce_quantifier_2(aProduction, aRange, theTokens, theChildren) count = theChildren[1].token.lexeme.to_i multiplicity(count, count) end # rule 'quantifier' => %w[BETWEEN count AND count times_suffix] def reduce_quantifier_3(aProduction, aRange, theTokens, theChildren) upper = theChildren[3].token.lexeme.to_i # lower = theChildren[1].token.lexeme.to_i multiplicity(3, upper) end # rule 'quantifier' => %w[AT LEAST count TIMES] def reduce_quantifier_7(aProduction, aRange, theTokens, theChildren) count = theChildren[2].token.lexeme.to_i multiplicity(count, :more) end =begin def reduce_binary_operator(theChildren) operator_node = theChildren[1] operator_node.children << theChildren[0] operator_node.children << theChildren[2] return operator_node end # rule 'simple_expression' => %w[simple_expression add_operator term] def reduce_simple_expression_1(_production, _range, _tokens, theChildren) reduce_binary_operator(theChildren) end # rule 'term' => %w[term mul_operator factor] def reduce_term_1(_production, _range, _tokens, theChildren) reduce_binary_operator(theChildren) end # rule 'factor' => %w[simple_factor POWER simple_factor]] def reduce_factor_1(aProduction, aRange, theTokens, theChildren) result = PowerNode.new(theChildren[1].symbol, aRange) result.children << theChildren[0] result.children << theChildren[2] return result end # rule 'simple_factor' => %[sign scalar] def reduce_simple_factor_0(aProduction, aRange, theTokens, theChildren) first_child = theChildren[0] result = if first_child.kind_of?(CalcNegateNode) -theChildren[1] else theChildren[1] end return result end # rule 'simple_factor' => %w[unary_function in_parenthesis] def reduce_simple_factor_1(aProduction, aRange, theTokens, theChildren) func = CalcUnaryFunction.new(theChildren[0].symbol, aRange.low) func.func_name = theChildren[0].value func.children << theChildren[1] return func end # rule 'simple_factor' => %w[MINUS in_parenthesis] def reduce_simple_factor_2(aProduction, aRange, theTokens, theChildren) negation = CalcNegateNode.new(theChildren[0].symbol, aRange.low) negation.children << theChildren[1] return negation end # rule 'add_operator' => 'PLUS' def reduce_add_operator_0(_production, aRange, _tokens, theChildren) return CalcAddNode.new(theChildren[0].symbol, aRange) end # rule 'add_operator' => 'MINUS' def reduce_add_operator_1(_production, aRange, _tokens, theChildren) return CalcSubtractNode.new(theChildren[0].symbol, aRange) end # rule 'mul_operator' => 'STAR' def reduce_mul_operator_0(_production, aRange, _tokens, theChildren) return CalcMultiplyNode.new(theChildren[0].symbol, aRange) end # rule 'mul_operator' => 'DIVIDE' def reduce_mul_operator_1(_production, aRange, _tokens, theChildren) return CalcDivideNode.new(theChildren[0].symbol, aRange) end =end end # class # End of file