Class: Kaiseki::Grammar

Inherits:
Object show all
Defined in:
lib/grammar.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ Grammar

Returns a new instance of Grammar.



6
7
8
9
10
11
12
13
14
# File 'lib/grammar.rb', line 6

def initialize &block
  @rules = Hash.new {|hash, key| raise "rule #{key.inspect} undefined" }
  @nodes = Hash.new {|hash, key| raise "node #{key.inspect} undefined" }
  @starting_rule = nil
  @skipping_rule = nil
  @simplify = true
  
  instance_eval &block if block_given?
end

Instance Attribute Details

#nodesObject (readonly)

Returns the value of attribute nodes.



3
4
5
# File 'lib/grammar.rb', line 3

def nodes
  @nodes
end

#rulesObject (readonly)

Returns the value of attribute rules.



3
4
5
# File 'lib/grammar.rb', line 3

def rules
  @rules
end

#simplify(bool = true) ⇒ Object

Returns the value of attribute simplify.



4
5
6
# File 'lib/grammar.rb', line 4

def simplify
  @simplify
end

#skipping_ruleObject

Returns the value of attribute skipping_rule.



4
5
6
# File 'lib/grammar.rb', line 4

def skipping_rule
  @skipping_rule
end

#starting_ruleObject

Returns the value of attribute starting_rule.



4
5
6
# File 'lib/grammar.rb', line 4

def starting_rule
  @starting_rule
end

Instance Method Details

#[](rule) ⇒ Object



16
17
18
# File 'lib/grammar.rb', line 16

def [] rule
  GrammarStub.new @rules[rule], self, rule
end

#action(name, &block) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/grammar.rb', line 70

def action name, &block
  if @rules.key? name
    raise "rule #{name.inspect} already defined"
  else
    @rules[name] = block.to_parseable
  end
end

#node(name, args, options = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
# File 'lib/grammar.rb', line 78

def node name, args, options = {}
  args.must_be Array
  if @nodes.key? name
    raise "node #{name.inspect} already defined"
  else
    parent = options[:class] || Node
    @nodes[name] = parent.subclass args, options
  end
end

#parse(stream, options = {}) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/grammar.rb', line 20

def parse stream, options = {}
  raise 'starting rule undefined' unless @starting_rule
  result = ParseResult.new
  default_options = {
    :grammar => self,
    :result => result,
    :rule => '(main)',
    :skipping => @skipping_rule,
    :simplify => @simplify
  }
  options = default_options.merge options
  begin
    result.results[:main] = @starting_rule.parse stream.to_stream, options
  rescue ParseError => e
    result.errors[:main] = e
  end
  result
end

#rule(name, parseable = nil, &block) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/grammar.rb', line 54

def rule name, parseable = nil, &block
  if @rules.key? name
    raise "rule #{name.inspect} already defined"
  else
    if parseable and block_given?
      raise ArgumentError, "wrong number of arguments; the second argument is mutually exclusive with a block"
    elsif parseable
      @rules[name] = parseable.to_parseable
    elsif block_given?
      @rules[name] = Rule.new(name, self, &block).parseable
    else
      @rules[name] = nil
    end
  end
end

#skipping(parseable) ⇒ Object



44
45
46
47
48
# File 'lib/grammar.rb', line 44

def skipping parseable
  raise "skipping rule already defined" if @skipping_rule
  raise "skipping rule must not be a predicate" if parseable.predicate?
  @skipping_rule = parseable.to_parseable
end

#starting(parseable) ⇒ Object



39
40
41
42
# File 'lib/grammar.rb', line 39

def starting parseable
  raise "starting rule already defined" if @starting_rule
  @starting_rule = parseable.to_parseable
end