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