Class: ReDuxml::Parser

Inherits:
Object
  • Object
show all
Includes:
Duxml, Lexer
Defined in:
lib/re_duxml/evaluate/parser.rb

Constant Summary

Constants included from Lexer

Lexer::TOKEN_TYPES

Instance Attribute Summary collapse

Attributes included from Lexer

#tokens

Instance Method Summary collapse

Methods included from Lexer

#lex

Constructor Details

#initialize(_logic) ⇒ Parser

Returns a new instance of Parser.

Raises:

  • (Exception)


37
38
39
40
41
42
43
44
45
46
47
# 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

Instance Attribute Details

#aritiesObject

Returns the value of attribute arities.



28
29
30
# File 'lib/re_duxml/evaluate/parser.rb', line 28

def arities
  @arities
end

#inputObject

Returns the value of attribute input.



28
29
30
# File 'lib/re_duxml/evaluate/parser.rb', line 28

def input
  @input
end

#logicObject (readonly)

Returns the value of attribute logic.



27
28
29
# File 'lib/re_duxml/evaluate/parser.rb', line 27

def logic
  @logic
end

#op_stackObject

Returns the value of attribute op_stack.



28
29
30
# File 'lib/re_duxml/evaluate/parser.rb', line 28

def op_stack
  @op_stack
end

#outputObject

Returns the value of attribute output.



28
29
30
# File 'lib/re_duxml/evaluate/parser.rb', line 28

def output
  @output
end

#string_hashObject (readonly)

Returns the value of attribute string_hash.



27
28
29
# File 'lib/re_duxml/evaluate/parser.rb', line 27

def string_hash
  @string_hash
end

Instance Method Details

#parse(expr) ⇒ Object

TODO attribute code to Dentaku



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 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_sObject



33
34
35
# File 'lib/re_duxml/evaluate/parser.rb', line 33

def to_s
  doc.logic.name
end