aurum 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/Rakefile +29 -0
  2. data/examples/dangling_else/grammar.rb +23 -0
  3. data/examples/expression/grammar.rb +28 -0
  4. data/examples/smalltalk/grammar.rb +151 -0
  5. data/examples/smalltalk/interpreter.rb +70 -0
  6. data/examples/yacc/grammar.rb +72 -0
  7. data/lib/aurum.rb +1 -9
  8. data/lib/aurum/engine.rb +39 -175
  9. data/lib/aurum/engine/parsing_facility.rb +107 -0
  10. data/lib/aurum/engine/tokenization_facility.rb +86 -0
  11. data/lib/aurum/grammar.rb +52 -219
  12. data/lib/aurum/grammar/automata.rb +194 -0
  13. data/lib/aurum/grammar/builder/augmented_grammar.rb +83 -0
  14. data/lib/aurum/grammar/builder/dot_logger.rb +66 -0
  15. data/lib/aurum/grammar/builder/lexical_table_builder.rb +55 -0
  16. data/lib/aurum/grammar/builder/parsing_table_builder.rb +238 -0
  17. data/lib/aurum/grammar/builder/set_of_items.rb +190 -0
  18. data/lib/aurum/grammar/compiled_tables.rb +20 -0
  19. data/lib/aurum/grammar/dsl/lexical_definition.rb +94 -0
  20. data/lib/aurum/grammar/dsl/syntax_definition.rb +79 -0
  21. data/lib/aurum/grammar/lexical_rules.rb +224 -0
  22. data/lib/aurum/grammar/metalang/grammar.rb +47 -0
  23. data/lib/aurum/grammar/syntax_rules.rb +95 -0
  24. data/spec/builder/dsl_definition/aurum_grammar_spec.rb +33 -0
  25. data/spec/engine/lexer_spec.rb +59 -0
  26. data/spec/engine/parser_spec.rb +90 -0
  27. data/spec/examples/dangling_else_example.rb +30 -0
  28. data/spec/examples/expression_example.rb +48 -0
  29. data/spec/examples/smalltalk_example.rb +50 -0
  30. data/spec/examples/yacc_spec.rb +30 -0
  31. data/spec/grammar/builder/lexical_table/automata_spec.rb +55 -0
  32. data/spec/grammar/builder/lexical_table/builder_spec.rb +78 -0
  33. data/spec/grammar/builder/lexical_table/character_set_spec.rb +100 -0
  34. data/spec/grammar/builder/lexical_table/pattern_spec.rb +11 -0
  35. data/spec/grammar/builder/lexical_table/regular_expression.rb +40 -0
  36. data/spec/grammar/builder/parsing_table/augmented_grammar_spec.rb +36 -0
  37. data/spec/grammar/builder/parsing_table/builder_spec.rb +152 -0
  38. data/spec/grammar/builder/parsing_table/digraph_traverser_spec.rb +42 -0
  39. data/spec/grammar/builder/parsing_table/item_spec.rb +51 -0
  40. data/spec/grammar/builder/parsing_table/sources_spec.rb +66 -0
  41. data/spec/grammar/builder/parsing_table/state_spec.rb +82 -0
  42. data/spec/grammar/dsl/character_classes_builder_spec.rb +50 -0
  43. data/spec/grammar/dsl/lexical_rules_builder_spec.rb +181 -0
  44. data/spec/grammar/dsl/precedence_builder_spec.rb +64 -0
  45. data/spec/grammar/dsl/productions_builder_spec.rb +78 -0
  46. data/spec/grammar/metalang/metalang_spec.rb +0 -0
  47. data/spec/grammar/precedence_spec.rb +42 -0
  48. data/spec/grammar/syntax_rules_spec.rb +31 -0
  49. data/spec/parser_matcher.rb +69 -0
  50. data/spec/pattern_matcher.rb +123 -0
  51. data/spec/spec_helper.rb +133 -0
  52. metadata +70 -36
  53. data/example/expression/expression.rb +0 -35
  54. data/example/expression/lisp.rb +0 -26
  55. data/lib/aurum/lexical_table_generator.rb +0 -429
  56. data/lib/aurum/parsing_table_generator.rb +0 -464
  57. data/test/engine/lexer_test.rb +0 -59
  58. data/test/engine/semantic_attributes_test.rb +0 -15
  59. data/test/grammar_definition/character_class_definition_test.rb +0 -28
  60. data/test/grammar_definition/grammar_definition_test.rb +0 -55
  61. data/test/grammar_definition/lexical_definition_test.rb +0 -56
  62. data/test/grammar_definition/operator_precedence_definition_test.rb +0 -35
  63. data/test/grammar_definition/production_definition_test.rb +0 -60
  64. data/test/lexical_table_generator/automata_test.rb +0 -74
  65. data/test/lexical_table_generator/character_set_test.rb +0 -73
  66. data/test/lexical_table_generator/interval_test.rb +0 -36
  67. data/test/lexical_table_generator/pattern_test.rb +0 -115
  68. data/test/lexical_table_generator/subset_determinizer_test.rb +0 -19
  69. data/test/lexical_table_generator/table_generator_test.rb +0 -126
  70. data/test/parsing_table_generator/augmented_grammar_test.rb +0 -45
  71. data/test/parsing_table_generator/lalr_n_computation_test.rb +0 -92
  72. data/test/parsing_table_generator/lr_0_automata_test.rb +0 -94
  73. data/test/parsing_table_generator/lr_item_test.rb +0 -27
  74. data/test/parsing_table_generator/parsing_table_state_test.rb +0 -39
  75. data/test/parsing_table_generator/precedence_table_test.rb +0 -28
  76. data/test/parsing_table_generator/production_test.rb +0 -9
  77. data/test/test_helper.rb +0 -103
@@ -0,0 +1,64 @@
1
+ helper_dir = File.join(File.dirname(__FILE__), '..', '..')
2
+ $:.unshift(helper_dir) unless $:.include?(helper_dir)
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Aurum::Grammar::DSL::PrecedencesBuilder do
7
+ before :each do
8
+ @syntax_rules = Aurum::Grammar::SyntaxRules.new
9
+ @builder = Aurum::Grammar::DSL::PrecedencesBuilder.new(@syntax_rules)
10
+ end
11
+
12
+ it 'string should be declared as literal non-associative operator' do
13
+ @builder.nonassoc '+'
14
+ precedence = @syntax_rules.operator_precedence('$literal_+')
15
+ precedence.should eql?(Aurum::Grammar.precedence(:non_associative, 0))
16
+ end
17
+
18
+ it 'symbol should be declared as terminal non-associative operator' do
19
+ @builder.nonassoc :_id
20
+ precedence = @syntax_rules.operator_precedence('_id')
21
+ precedence.should eql?(Aurum::Grammar.precedence(:non_associative, 0))
22
+ end
23
+
24
+ it 'string should be declared as literal left-associative operator' do
25
+ @builder.left '+'
26
+ precedence = @syntax_rules.operator_precedence('$literal_+')
27
+ precedence.should eql?(Aurum::Grammar.precedence(:left_associative, 0))
28
+ end
29
+
30
+ it 'symbol should be declared as terminal left-associative operator' do
31
+ @builder.left :_id
32
+ precedence = @syntax_rules.operator_precedence('_id')
33
+ precedence.should eql?(Aurum::Grammar.precedence(:left_associative, 0))
34
+ end
35
+
36
+ it 'string should be declared as literal right-associative operator' do
37
+ @builder.right '+'
38
+ precedence = @syntax_rules.operator_precedence('$literal_+')
39
+ precedence.should eql?(Aurum::Grammar.precedence(:right_associative, 0))
40
+ end
41
+
42
+ it 'symbol should be declared as terminal right-associative operator' do
43
+ @builder.right :_id
44
+ precedence = @syntax_rules.operator_precedence('_id')
45
+ precedence.should eql?(Aurum::Grammar.precedence(:right_associative, 0))
46
+ end
47
+
48
+ it 'operators declared in the same time should have same precedence' do
49
+ @builder.nonassoc '+', '-'
50
+ precedence = @syntax_rules.operator_precedence('$literal_+')
51
+ precedence.should eql?(Aurum::Grammar.precedence(:non_associative, 0))
52
+ precedence = @syntax_rules.operator_precedence('$literal_-')
53
+ precedence.should eql?(Aurum::Grammar.precedence(:non_associative, 0))
54
+ end
55
+
56
+ it 'operators declared earlier should have higher precedence' do
57
+ @builder.nonassoc '+'
58
+ @builder.nonassoc '-'
59
+ precedence = @syntax_rules.operator_precedence('$literal_+')
60
+ precedence.should eql?(Aurum::Grammar.precedence(:non_associative, 0))
61
+ precedence = @syntax_rules.operator_precedence('$literal_-')
62
+ precedence.should eql?(Aurum::Grammar.precedence(:non_associative, -1))
63
+ end
64
+ end
@@ -0,0 +1,78 @@
1
+ helper_dir = File.join(File.dirname(__FILE__), '..', '..')
2
+ $:.unshift(helper_dir) unless $:.include?(helper_dir)
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Aurum::Grammar::DSL::ProductionsBuilder do
7
+ before :each do
8
+ @syntax_rules, @actions = Aurum::Grammar::SyntaxRules.new, {}
9
+ @builder = Aurum::Grammar::DSL::ProductionsBuilder.new(@syntax_rules, @actions)
10
+ end
11
+
12
+ it 'should add terminal to terminal list' do
13
+ @builder.instance_eval do
14
+ nonterminal _terminal
15
+ end
16
+ terminals = @syntax_rules.instance_eval {@terminals}
17
+ terminals.size.should == 1
18
+ terminals['_terminal'].should == Aurum::Grammar.terminal('_terminal')
19
+ end
20
+
21
+ it 'should add literal to terminal and literal list' do
22
+ @builder.instance_eval do
23
+ nonterminal '+'
24
+ end
25
+ terminals, literals = @syntax_rules.instance_eval {[@terminals, @literals]}
26
+ terminals.size.should == 1
27
+ terminals['$literal_+'].should == Aurum::Grammar.terminal('$literal_+')
28
+ literals.should == ['+'].to_set
29
+ end
30
+
31
+ it 'should add production to nonterminal' do
32
+ @builder.instance_eval do
33
+ nonterminal _terminal
34
+ end
35
+ productions = @syntax_rules.productions(Aurum::Grammar.nonterminal('nonterminal'))
36
+ productions.map {|prod| prod.inspect}.join(' , ').should == 'nonterminal -> _terminal'
37
+ end
38
+
39
+ it 'should add empty production to nonterminal' do
40
+ @builder.instance_eval do
41
+ nonterminal _
42
+ end
43
+ productions = @syntax_rules.productions(Aurum::Grammar.nonterminal('nonterminal'))
44
+ productions.map {|prod| prod.inspect}.join(' , ').should == 'nonterminal -> '
45
+ end
46
+
47
+ it 'should use object_id as anonymouse production name' do
48
+ @builder.instance_eval do
49
+ nonterminal _terminal
50
+ end
51
+ production = @syntax_rules.productions(Aurum::Grammar.nonterminal('nonterminal')).to_a[0]
52
+ production.name.should == "$production_#{production.object_id}"
53
+ end
54
+
55
+ it 'should use last symbol as production name' do
56
+ @builder.instance_eval do
57
+ nonterminal _terminal, :production_name
58
+ end
59
+ production = @syntax_rules.productions(Aurum::Grammar.nonterminal('nonterminal')).to_a[0]
60
+ production.name.should == 'production_name'
61
+ end
62
+
63
+ it 'should add action to actions table for anonymouse production' do
64
+ @builder.instance_eval do
65
+ nonterminal _terminal { 'action' }
66
+ end
67
+ production = @syntax_rules.productions(Aurum::Grammar.nonterminal('nonterminal')).to_a[0]
68
+ @actions[production.name].should_not be_nil
69
+ end
70
+
71
+ it 'should add action to actions table for named production' do
72
+ @builder.instance_eval do
73
+ nonterminal _terminal, :name do 'action' end
74
+ end
75
+ production = @syntax_rules.productions(Aurum::Grammar.nonterminal('nonterminal')).to_a[0]
76
+ @actions[production.name].should_not be_nil
77
+ end
78
+ end
File without changes
@@ -0,0 +1,42 @@
1
+ helper_dir = File.join(File.dirname(__FILE__), '..')
2
+ $:.unshift(helper_dir) unless $:.include?(helper_dir)
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Aurum::Grammar::SyntaxRules::Precedence do
7
+ it 'precedence2 should greater than precedence2 if operator1 has higher precedence' do
8
+ precedence1 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, 0)
9
+ precedence2 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, -1)
10
+ precedence1.should > precedence2
11
+ end
12
+
13
+ it 'precedence2 should less than precedence1 if precedence1 has higher precedence' do
14
+ precedence1 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, 0)
15
+ precedence2 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, -1)
16
+ precedence2.should < precedence1
17
+ end
18
+
19
+ it 'precedence1 should greater then precedence2 if operators are left-associative and same precedence' do
20
+ precedence1 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, 0)
21
+ precedence2 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, 0)
22
+ precedence2.should > precedence1
23
+ end
24
+
25
+ it 'precedence2 should greater then precedence1 if operators are left-associative and same precedence' do
26
+ precedence1 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, 0)
27
+ precedence2 = Aurum::Grammar::SyntaxRules::Precedence.new(:left_associative, 0)
28
+ precedence1.should > precedence2
29
+ end
30
+
31
+ it 'precedence1 should less then precedence2 if operators are left-associative and same precedence' do
32
+ precedence1 = Aurum::Grammar::SyntaxRules::Precedence.new(:right_associative, 0)
33
+ precedence2 = Aurum::Grammar::SyntaxRules::Precedence.new(:right_associative, 0)
34
+ precedence1.should < precedence2
35
+ end
36
+
37
+ it 'precedence2 should less then precedence1 if operators are left-associative and same precedence' do
38
+ precedence1 = Aurum::Grammar::SyntaxRules::Precedence.new(:right_associative, 0)
39
+ precedence2 = Aurum::Grammar::SyntaxRules::Precedence.new(:right_associative, 0)
40
+ precedence2.should < precedence1
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ helper_dir = File.join(File.dirname(__FILE__), '..')
2
+ $:.unshift(helper_dir) unless $:.include?(helper_dir)
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Aurum::Grammar::SyntaxRules do
7
+ before :all do
8
+ @syntax_rules = Aurum::Grammar::SyntaxRules.new
9
+ @E, @T, @plus = Aurum::Grammar.nonterminal('E'), Aurum::Grammar.nonterminal('T'), Aurum::Grammar.terminal('$literal_+')
10
+ @syntax_rules.add_syntax_rule Aurum::Grammar.production(@E, [@E, @plus, @E])
11
+ @syntax_rules.add_syntax_rule Aurum::Grammar.production(@E, [@T, @plus, @T])
12
+ end
13
+
14
+ it 'should add productions to nonterminal' do
15
+ productions = @syntax_rules.productions(@E).map {|production| production.inspect}.to_set
16
+ productions.should == ['E -> T + T', 'E -> E + E'].to_set
17
+ end
18
+
19
+ it 'should not add duplicated productions' do
20
+ @syntax_rules.add_syntax_rule Aurum::Grammar.production(@E, [@T, @plus, @T])
21
+ productions = @syntax_rules.productions(@E).map {|production| production.inspect}.to_set
22
+ productions.size.should == 2
23
+ end
24
+
25
+ it 'should assign precedence to operator symbol' do
26
+ precedence = Aurum::Grammar.precedence(:left_associative, 1)
27
+ @syntax_rules.add_operator_precedence('$literal_+', precedence)
28
+ @syntax_rules.assign_operator_precedence_to_symbols
29
+ @syntax_rules.instance_eval {@terminals['$literal_+'].precedence}.should == precedence
30
+ end
31
+ end
@@ -0,0 +1,69 @@
1
+ module ParserMatcher
2
+ def token(terminal, value = terminal)
3
+ Aurum::Engine::Token.new(terminal.to_s, value)
4
+ end
5
+
6
+ def literal(terminal, value = terminal)
7
+ Aurum::Engine::Token.new("$literal_#{terminal}", value)
8
+ end
9
+
10
+ def be_parsed_as(nonterminal, value=nil)
11
+ parser_creator = Aurum::Parser.new(@grammar, nonterminal)
12
+ BeParsedAs.new(parser_creator.new, nonterminal, value)
13
+ end
14
+
15
+ class BeParsedAs
16
+ def initialize parser, nonterminal, value
17
+ @parser, @nonterminal, @value = parser, nonterminal, value
18
+ class << @parser
19
+ def error_recovery
20
+ raise 'error_recover'
21
+ end
22
+ end
23
+ end
24
+
25
+ def matches?(source)
26
+ @source = source
27
+ (result = @parser.parse(Lexer.new(source))) rescue return false
28
+ return true unless @value
29
+ @value.all? {|attr, value| result.__send__(attr) == value}
30
+ end
31
+
32
+ def failure_message
33
+ "[#{@source.join(', ')}] can't be parsed as #{@nonterminal}"
34
+ end
35
+
36
+ def negative_failure_message
37
+ "[#{@source.join(', ')}] can be parsed as #{@nonterminal}"
38
+ end
39
+
40
+ def description
41
+ "be parsed as #{@nonterminal} if [#{@source.join(', ')}] given"
42
+ end
43
+ end
44
+
45
+ class Lexer
46
+ def initialize source
47
+ @source = source.map do |token|
48
+ case token
49
+ when String : Aurum::Engine::Token.new("$literal_#{token}", token)
50
+ when Symbol : Aurum::Engine::Token.new(token.to_s, token)
51
+ when Aurum::Engine::Token : token
52
+ end
53
+ end
54
+ end
55
+
56
+ def next_symbol
57
+ symbol = @source.shift()
58
+ symbol ? symbol : Aurum::Engine::Token.new('$eof', '')
59
+ end
60
+
61
+ def pushback symbol
62
+ @source.unshift(symbol)
63
+ end
64
+
65
+ def inspect
66
+ @source.inspect
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,123 @@
1
+ module PatternMatcher
2
+ class BeMatchedBy
3
+ def initialize pattern_string, pattern
4
+ @pattern_string, @pattern = pattern_string, pattern
5
+ end
6
+
7
+ def matches?(lexeme)
8
+ @lexeme = lexeme
9
+ states = closure(@pattern.automata.table, [0])
10
+ lexeme.each_byte {|char| states = move(@pattern.automata.table, states, char)}
11
+ states.include?(@pattern.accept)
12
+ end
13
+
14
+ def failure_message
15
+ "'#@lexeme' is not matched by /#@pattern_string/"
16
+ end
17
+
18
+ def negative_failure_message
19
+ "'#@lexeme' is matched by /#@pattern_string/"
20
+ end
21
+
22
+ def description
23
+ "match '#@lexeme' by /#@pattern_string/"
24
+ end
25
+
26
+ private
27
+ def move automata, states, char
28
+ result = []
29
+ states.each {|state| automata[state].each {|tran| result.concat(closure(automata, [tran.destination])) if tran.character_set.include?(char)} }
30
+ result.uniq
31
+ end
32
+
33
+ def closure automata, states
34
+ closure, unvisited = Set.new(states.dup), states.dup
35
+ while !unvisited.empty?
36
+ automata[unvisited.pop].each do |tran|
37
+ [closure, unvisited].each {|x| x << tran.destination} if tran.character_set == Aurum::Grammar::LexicalRules::Epsilon && !closure.include?(tran.destination)
38
+ end
39
+ end
40
+ closure.to_a
41
+ end
42
+ end
43
+ def be_matched_by pattern_string, pattern
44
+ BeMatchedBy.new(pattern_string, pattern)
45
+ end
46
+ end
47
+
48
+ module DeterminizedPatternMatcher
49
+ class BeMatchedBy
50
+ def initialize pattern_string, pattern
51
+ @pattern_string, = pattern_string
52
+ @automata, @accepts = Aurum::Grammar::LexicalRules::SubsetDeterminizer.new(pattern.automata, [pattern.accept]).determinize
53
+ end
54
+
55
+ def matches?(lexeme)
56
+ @lexeme = lexeme
57
+ state = 0
58
+ lexeme.each_byte {|char| state = move(state, char)} rescue return false
59
+ @accepts.include?(state)
60
+ end
61
+
62
+ def failure_message
63
+ "'#@lexeme' is not matched by /#@pattern_string/"
64
+ end
65
+
66
+ def negative_failure_message
67
+ "'#@lexeme' is matched by /#@pattern_string/"
68
+ end
69
+
70
+ def description
71
+ "match '#@lexeme' by /#@pattern_string/"
72
+ end
73
+
74
+ private
75
+ def move state, char
76
+ @automata.table[state].each {|tran| return tran.destination if tran.character_set.include?(char)}
77
+ raise 'not matched'
78
+ end
79
+ end
80
+ def be_matched_by pattern_string, pattern
81
+ BeMatchedBy.new(pattern_string, pattern)
82
+ end
83
+ end
84
+
85
+ module MinimizedPatternMatcher
86
+ class BeMatchedBy
87
+ def initialize pattern_string, pattern
88
+ @pattern_string, = pattern_string
89
+ automata, accepts = Aurum::Grammar::LexicalRules::SubsetDeterminizer.new(pattern.automata, [pattern.accept]).determinize
90
+ accept_actions = {}
91
+ accepts.keys.each {|state| accept_actions[state] = 'action'}
92
+ @automata, @accepts = Aurum::Grammar::LexicalRules::HopcroftMinimizer.new(automata, accept_actions).minimize
93
+ end
94
+
95
+ def matches?(lexeme)
96
+ @lexeme = lexeme
97
+ state = 0
98
+ lexeme.each_byte {|char| state = move(state, char)} rescue return false
99
+ @accepts.include?(state)
100
+ end
101
+
102
+ def failure_message
103
+ "'#@lexeme' is not matched by /#@pattern_string/"
104
+ end
105
+
106
+ def negative_failure_message
107
+ "'#@lexeme' is matched by /#@pattern_string/"
108
+ end
109
+
110
+ def description
111
+ "match '#@lexeme' by /#@pattern_string/"
112
+ end
113
+
114
+ private
115
+ def move state, char
116
+ @automata.table[state].each {|tran| return tran.destination if tran.character_set.include?(char)}
117
+ raise 'not matched'
118
+ end
119
+ end
120
+ def be_matched_by pattern_string, pattern
121
+ BeMatchedBy.new(pattern_string, pattern)
122
+ end
123
+ end
@@ -0,0 +1,133 @@
1
+ lib_dir = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ examples_dir = File.join(File.dirname(__FILE__), '..', 'examples')
3
+ $:.unshift(lib_dir) unless $:.include?(lib_dir)
4
+ $:.unshift(examples_dir) unless $:.include?(examples_dir)
5
+
6
+ require 'delegate'
7
+ require 'aurum/grammar'
8
+ require 'aurum/engine'
9
+
10
+ require File.join(File.dirname(__FILE__), 'pattern_matcher')
11
+ require File.join(File.dirname(__FILE__), 'parser_matcher')
12
+
13
+ class SimpleLR0Grammar < Aurum::Grammar
14
+ syntax_rules do
15
+ expression term, '+', term
16
+ term _id
17
+ end
18
+ end
19
+
20
+ class Grammar419InDragonBook < Aurum::Grammar
21
+ syntax_rules do
22
+ expression expression, '+', term
23
+ expression term
24
+ term term, '*', factor
25
+ term factor
26
+ factor '(', expression, ')'
27
+ factor _id
28
+ end
29
+ end
30
+
31
+ class ExpressionGrammar < Aurum::Grammar
32
+ syntax_rules do
33
+ expression expression, '+', expression
34
+ expression expression, '*', expression
35
+ expression '(', expression, ')'
36
+ expression _id
37
+ end
38
+ end
39
+
40
+ class ExpressionGrammarWithOperatorPrecedence < Aurum::Grammar
41
+ precedences do
42
+ left '*'
43
+ left '+'
44
+ end
45
+
46
+ productions do
47
+ expression expression, '+', expression
48
+ expression expression, '*', expression
49
+ expression '(', expression, ')'
50
+ expression _id
51
+ end
52
+ end
53
+
54
+ class BnfGrammarInCharlesThesis < Aurum::Grammar
55
+ productions do
56
+ bnf rlist
57
+ rlist rlist, rule
58
+ rlist _
59
+ rule _s, '->', slist
60
+ slist slist, _s
61
+ slist _
62
+ end
63
+ end
64
+
65
+ class Grammar411InDragonBook < Aurum::Grammar
66
+ productions do
67
+ expression term, expression1
68
+ expression1 '+', term, expression1
69
+ expression1 _
70
+ term factor, term1
71
+ term1 '*', factor, term1
72
+ term1 _
73
+ factor '(', expression, ')'
74
+ factor _id
75
+ end
76
+ end
77
+
78
+ class GrammarWithNullableSymbols < Aurum::Grammar
79
+ productions do
80
+ expression term
81
+ expression factor
82
+ term _
83
+ factor _id
84
+ end
85
+ end
86
+
87
+ class LALR4Grammar < Aurum::Grammar
88
+ productions do
89
+ s b, _x, _x, _x, _y, _z
90
+ s c, _x, _x, _x, _x, _z
91
+ s _x, b, _x, _x, _x, _x, _y
92
+ b _w
93
+ c _w
94
+ end
95
+ end
96
+
97
+ class BnfGrammarWithActions < Aurum::Grammar
98
+ productions do
99
+ bnf rlist
100
+ rlist rlist, rule {rlist.s_exp = rlist1.s_exp + [rule.s_exp]}
101
+ rlist _ {rlist.s_exp = []}
102
+ rule _s, '->', slist {rule.s_exp = [:rule, _s.value, slist.s_exp]}
103
+ slist slist, _s {slist.s_exp = slist1.s_exp + [_s.value]}
104
+ slist _ {slist.s_exp = []}
105
+ end
106
+ end
107
+
108
+ class GrammarForLexerTesting < Aurum::Grammar
109
+ tokens do
110
+ _numeric range(?0, ?9).one_or_more
111
+ match 'state_a_begin', :shift_to => :state_a
112
+ match 'state_b_begin', :shift_to => :state_b, :recognize => :_state_b_begin
113
+ match 'state_b_beg', :recognize => :_state_b_beg
114
+ ignore 'ignore'
115
+ within :state_a, :state_b do
116
+ _numeric range(?0, ?9).one_or_more
117
+ end
118
+ end
119
+ end
120
+
121
+ class BNFGrammar < Aurum::Grammar
122
+ productions do
123
+ bnf bnf, rules
124
+ bnf _
125
+ rules rules, '|', symbol_list
126
+ rules rule
127
+ rule _nonterminal, '->', symbol_list
128
+ symbol_list symbol_list, _nonterminal
129
+ symbol_list _
130
+ end
131
+ end
132
+
133
+ $pattern = Aurum::Grammar::LexicalRules::Pattern