Class: Ast::BNF

Inherits:
Object
  • Object
show all
Defined in:
lib/ast_ast/bnf.rb

Overview

Allows you to describe the tree using BNF style syntax.

In normal BNF you would write something like:

<LETTER> ::= a|b|c|d|...|X|Y|Z
<WORD>   ::= <WORD><LETTER>|<LETTER>
<QUOTE>  ::= ' 
<STRING> ::= <QUOTE><WORD><QUOTE>

With Ast::BNF, assuming you have the correct tokens, it would become:

define "Word",  ["Word", :letter], :letter
define "String",  [:quote, "Word", :quote]

Defined Under Namespace

Classes: Definition

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, &block) ⇒ BNF

Returns a new instance of BNF.



127
128
129
# File 'lib/ast_ast/bnf.rb', line 127

def initialize(name, &block)
  @block = block
end

Instance Attribute Details

#defsObject

Returns the value of attribute defs.



23
24
25
# File 'lib/ast_ast/bnf.rb', line 23

def defs
  @defs
end

#tokensObject

Returns the value of attribute tokens.



23
24
25
# File 'lib/ast_ast/bnf.rb', line 23

def tokens
  @tokens
end

Instance Method Details

#define(name, *args) ⇒ Object



167
168
169
170
# File 'lib/ast_ast/bnf.rb', line 167

def define(name, *args)
  @defs ||= []
  @defs << Definition.new(name, args, self)
end

#to_tree(tokens) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/ast_ast/bnf.rb', line 131

def to_tree(tokens)
  self.instance_eval(&@block)
  
  # get matrix of defs in order by order
  defs_orders = @defs.collect {|i| [i.order, i]}
  ordered_defs = []
  defs_orders.each do |i|
    ordered_defs[i[0]] ||= []
    ordered_defs[i[0]] << i[1]
  end
    
  result = []
  ordered_defs.each do |order|
    
    order.each do |definition|
      c = tokens.scan
      
      definition.rules.each do |rule|
        list = tokens.peek(rule.size)
        
        res = []
        rule.zip(list) do |(a, b)|
          next if b.nil?
          if a == b.type
            res << b.value
          end
        end
        next if res.size != rule.size
        p [definition.name, res.join('')]
      end
    end
  end

  tokens
end