class ReDuxml::Parser
Attributes
arities[RW]
input[RW]
logic[R]
op_stack[RW]
output[RW]
string_hash[R]
Public Class Methods
new(_logic)
click to toggle source
# File lib/re_duxml/evaluate/parser.rb, line 37 def initialize(_logic) if _logic load _logic @logic = {} doc.logic.Operator.each do |op| op.parent = @logic @logic[op.symbol] = op end end raise Exception if logic.nil? end
Public Instance Methods
parse(expr)
click to toggle source
TODO attribute code to Dentaku
# File lib/re_duxml/evaluate/parser.rb, line 50 def parse(expr) @input = lex(expr) @output = [] @op_stack = [] @arities = [] return nil if input.empty? while(token = input.shift) case token.type when :num, :bool, :string, :param output.push AST::Node.new(token.value) when :operator op_prop = token.value arities << op_prop.arity-1 if op_prop.symbol == '?' if op_prop.right_associative? while op_stack.last && op_prop.precedence < op_stack.last.precedence if !op_stack.last.grouping? consume else break end end else while op_stack.last && op_prop.precedence <= op_stack.last.precedence && !op_stack.last.grouping? consume end end op_stack << op_prop when :function arities << 0 op_stack << token.value when :grouping op_prop = token.value op_str = op_prop.respond_to?(:nodes) ? op_prop.symbol : op_prop.to_s case op_str when '(' if input.any? && input.first.type == :grouping && input.first.value.to_s == '(' input.shift consume(0) else op_stack << op_prop end when ')' while op_stack.any? && op_stack.last.symbol != op_prop.pair.symbol consume(arities.pop || op_stack.last.arity) end lparen = op_stack.pop fail ParseError, "Unbalanced parenthesis" unless lparen && lparen.grouping? if op_stack.last && op_stack.last.position == 'prefix' consume(arities.pop) end when ',' arities[-1] += 1 while op_stack.any? && op_stack.last.symbol != '(' consume end when ':' while op_stack.any? && op_stack.last.symbol != '?' consume(arities.pop) end arities[-1] += 1 op_stack << op_prop else fail ParseError, "Unknown grouping token #{ token.value }" end # case token.value ... when :grouping else fail ParseError, "Not implemented for tokens of type #{ token.type }" end # case token.type end # while (token = input.shift) while op_stack.any? consume end unless output.count == 1 fail ParseError, "Invalid statement" end output.first end
to_s()
click to toggle source
# File lib/re_duxml/evaluate/parser.rb, line 33 def to_s doc.logic.name end
Private Instance Methods
consume(count=2)
click to toggle source
# File lib/re_duxml/evaluate/parser.rb, line 135 def consume(count=2) op_stack.pop if op_stack.last.symbol == ':' operator = op_stack.pop output.push AST::Node.new(operator, get_args(operator.arity || count)) end
get_args(count)
click to toggle source
# File lib/re_duxml/evaluate/parser.rb, line 141 def get_args(count) Array.new(count) { output.pop }.reverse.compact end