aurum 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,47 @@
1
+ module Aurum
2
+ module MetaLanguage
3
+ class Grammar < Aurum::Grammar
4
+ tokens do
5
+ ignore enum(" \r\n").one_or_more
6
+ _nonterminal 'nonterminal'
7
+ _terminal 'terminal'
8
+ _literal 'literal'
9
+ end
10
+
11
+ syntax_rules do
12
+ bnf bnf, rules
13
+ bnf _
14
+
15
+ rules rule
16
+ rules rules, '|', symbol_list
17
+
18
+ rule _nonterminal, '->', symbol_list
19
+
20
+ symbol_list _
21
+ symbol_list symbol_list, symbol
22
+
23
+ symbol _nonterminal
24
+ symbol _terminal
25
+ symbol _literal
26
+
27
+ =begin
28
+ syntax_rules syntax_rules, syntax_rule {syntax_rules.s_exp = syntax_rules1.s_exp + syntax_rule.s_exp}
29
+ syntax_rules _ {syntax_rules.s_exp = []}
30
+
31
+ # syntax_rule _nonterminal, '->', symbols {syntax_rule.s_exp = [:production, [:nonterminal, _nonterminal.value], symbols.s_exp]}
32
+ syntax_rule _nonterminal, '->', handles {syntax_rule.s_exp = [:production, [:nonterminal, _nonterminal.value], handles.s_exp]}
33
+
34
+ handles handle, '|', handles
35
+ handles _
36
+
37
+ handle handle, symbol {handle.s_exp = handle1.s_exp << symbol.s_exp}
38
+ handle _ {handle.s_exp = []}
39
+
40
+ symbol _nonterminal {symbol.s_exp = [:nonterminal, _nonterminal.value]}
41
+ symbol _terminal {symbol.s_exp = [:terminal, _terminal.value]}
42
+ symbol _literal {symbol.s_exp = [:literal, _literal.value]}
43
+ =end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,95 @@
1
+ module Aurum
2
+ class Grammar
3
+ class SyntaxRules < Struct.new(:precedences, :productions)
4
+ attr_reader :literals
5
+ def initialize
6
+ @precedences, @productions, @terminals, @literals = {}, {}, {}, [].to_set
7
+ @precedences_update = true
8
+ end
9
+
10
+ def add_syntax_rule production
11
+ @precedences_update = true
12
+ nonterminal = production.nonterminal
13
+ production.symbols.each {|s| @terminals[s.name] = s if s.is_terminal && !s.precedence}
14
+ @productions[nonterminal] = [] unless @productions.has_key?(nonterminal)
15
+ return false if @productions[nonterminal].include?(production)
16
+ @productions[nonterminal] << production
17
+ true
18
+ end
19
+
20
+ def add_literal literal
21
+ @literals << literal
22
+ end
23
+
24
+ def add_operator_precedence operator, precedence
25
+ @precedences_update = true
26
+ @precedences[operator] = precedence
27
+ end
28
+
29
+ def productions nonterminal
30
+ @productions[nonterminal]
31
+ end
32
+
33
+ def operator_precedence symbol_name
34
+ @precedences[symbol_name]
35
+ end
36
+
37
+ def assign_operator_precedence_to_symbols
38
+ return unless @precedences_update
39
+ @precedences_update = false
40
+ for name, precedence in @precedences
41
+ symbol = @terminals[name]
42
+ symbol.precedence = precedence if symbol
43
+ end
44
+ end
45
+
46
+ class Precedence < Struct.new(:associativity, :level)
47
+ include Comparable
48
+ Highest, Lowest = Precedence.new(:non_associative, 65535), Precedence.new(:non_associative, -65535)
49
+ def <=> other
50
+ return level <=> other.level unless level == other.level
51
+ return 1 if associativity == :left_associative
52
+ return -1 if associativity == :right_associative
53
+ #TODO non_associative
54
+ end
55
+ end
56
+
57
+ class Symbol < Struct.new(:name, :is_terminal)
58
+ attr_accessor :precedence, :action
59
+ def inspect
60
+ name.split('$literal_').last
61
+ end
62
+ end
63
+
64
+ class Production < Struct.new(:nonterminal, :symbols)
65
+ attr_accessor :name
66
+
67
+ def precedence
68
+ terminals = symbols.find_all {|symbol| symbol.is_terminal && symbol.precedence}
69
+ terminals.size == 1 ? terminals.first.precedence : Precedence::Highest
70
+ end
71
+
72
+ def inspect
73
+ "#{nonterminal.inspect} -> #{symbols.map {|symbol| symbol.inspect}.join(' ')}"
74
+ end
75
+ end
76
+ end
77
+
78
+ def Grammar.terminal name
79
+ SyntaxRules::Symbol.new(name, true)
80
+ end
81
+
82
+ def Grammar.nonterminal name
83
+ SyntaxRules::Symbol.new(name, false)
84
+ end
85
+
86
+ def Grammar.precedence associative, level
87
+ SyntaxRules::Precedence.new(associative, level)
88
+ end
89
+
90
+ def Grammar.production nonterminal, symbols
91
+ SyntaxRules::Production.new(nonterminal, symbols)
92
+ end
93
+ EOF, Epsilon = Grammar.terminal('$eof'), Grammar.terminal('$epsilon')
94
+ end
95
+ end
@@ -0,0 +1,33 @@
1
+ helper_lib = "#{File.dirname(__FILE__)}/../../"
2
+ $:.unshift helper_lib unless $:.include? helper_lib
3
+ #require 'spec_helper'
4
+ #require File.join(File.dirname(__FILE__), '../../engine/parser_matcher')
5
+ =begin
6
+ class TestGrammar < Aurum::Grammar
7
+ end
8
+ class GrammarA < Aurum::Grammar
9
+ productions do
10
+ expression factor, '+', factor
11
+ factor _id
12
+ end
13
+ end
14
+
15
+ describe Aurum::Grammar, 'including other grammar' do
16
+ def be_parsed_as(nonterminal, value=nil)
17
+ ParserMatcher::BeParsedAs.new(TestGrammar.parsing_table(nonterminal), nonterminal, value)
18
+ end
19
+
20
+ it 'should throw an error if included object is not a grammar' do
21
+ lambda {TestGrammar.include_grammar String}.should raise_error(RuntimeError, 'String is not a grammar!')
22
+ end
23
+
24
+ it 'should include grammar into TestGrammar' do
25
+ TestGrammar.include_grammar GrammarA
26
+ [:_id, '+', :_id].should be_parsed_as('expression')
27
+ end
28
+ it 'should change symbol names and include grammar into TestGrammar' do
29
+ TestGrammar.include_grammar GrammarA, :syntax => {:expression => :exp}
30
+ [:_id, '+', :_id].should be_parsed_as('exp')
31
+ end
32
+ end
33
+ =end
@@ -0,0 +1,59 @@
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::Engine::BasicTokenizationCapability do
7
+ before :all do
8
+ Lexer = Aurum::Lexer.new(GrammarForLexerTesting)
9
+ end
10
+
11
+ it 'should return recognized symbol' do
12
+ lexer = Lexer.new('1234')
13
+ lexer.next_symbol.to_a.should == ['_numeric', '1234']
14
+ end
15
+
16
+ it 'should shift to lexical state' do
17
+ lexer = Lexer.new('state_a_begin1234')
18
+ lexer.next_symbol.to_a.should == ['_numeric', 'state_a_begin1234']
19
+ end
20
+
21
+ it 'should return recognized symbol and shift to lexical state' do
22
+ lexer = Lexer.new('state_b_begin1234')
23
+ lexer.next_symbol.to_a.should == ['_state_b_begin', 'state_b_begin']
24
+ lexer.next_symbol.to_a.should == ['_numeric', '1234']
25
+ end
26
+
27
+ it 'should ignore ignored pattern' do
28
+ lexer = Lexer.new('ignore1234')
29
+ lexer.next_symbol.to_a.should == ['_numeric', '1234']
30
+ end
31
+
32
+ it 'should not match pattern greedily' do
33
+ lexer = Lexer.new('state_b_begi1234')
34
+ lexer.next_symbol.to_a.should == ['_state_b_beg', 'state_b_beg']
35
+ end
36
+
37
+ it 'should return EOF if reach the end of input' do
38
+ lexer = Lexer.new('ignore')
39
+ lexer.next_symbol.to_a.should == ['$eof', '']
40
+ end
41
+
42
+ it 'should return UNKNOWN if can not recognize token' do
43
+ lexer = Lexer.new('state_b_')
44
+ lexer.next_symbol.to_a.should == ['$unknown', 'state_b_']
45
+ end
46
+
47
+ it 'should return pushbacked symbol' do
48
+ lexer = Lexer.new('state_b_')
49
+ lexer.pushback('pushback')
50
+ lexer.next_symbol.should == 'pushback'
51
+ end
52
+
53
+ it 'should return current column' do
54
+ lexer = Lexer.new('1234')
55
+ lexer.column.should == 0
56
+ lexer.next_symbol
57
+ lexer.column.should == 4
58
+ end
59
+ end
@@ -0,0 +1,90 @@
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::Engine::BasicParsingCapability, ' LR(0) : simple LR(0) grammar' do
7
+ include ParserMatcher
8
+ before :all do
9
+ @grammar = SimpleLR0Grammar
10
+ end
11
+ it {[:_id].should be_parsed_as('term')}
12
+ it {[:_id, '+', :_id].should be_parsed_as('expression')}
13
+ it {[:_it].should_not be_parsed_as('term')}
14
+ it {[:_id, '+', :_it].should_not be_parsed_as('expression')}
15
+ it 'should not look for eof' do
16
+ [:_id, '+', :_id].should be_parsed_as('term')
17
+ end
18
+ end
19
+
20
+ describe Aurum::Engine::BasicParsingCapability, ' LALR(1) : Grammar 4.19 in Dragon book' do
21
+ include ParserMatcher
22
+ before :all do
23
+ @grammar = Grammar419InDragonBook
24
+ end
25
+ it {[:_id].should be_parsed_as('factor')}
26
+ it {['(', :_id, ')'].should be_parsed_as('factor')}
27
+ it {['(', :_id, '*', :_id, ')'].should be_parsed_as('factor')}
28
+ it {['(', :_id, '+', :_id, ')'].should be_parsed_as('factor')}
29
+ it {[:_id, '*', :_id].should be_parsed_as('term')}
30
+ it {[:_id, '*', '(', :_id, '*', :_id, ')'].should be_parsed_as('term')}
31
+ it {[:_id, '*', '(', :_id, '+', :_id, ')'].should be_parsed_as('term')}
32
+ it {[:_id, '+', :_id].should be_parsed_as('expression')}
33
+ it {[:_id, '*', :_id].should be_parsed_as('expression')}
34
+ it {[:_id, '+', :_id, '*', :_id].should be_parsed_as('expression')}
35
+ it {[:_id, '+', :_id, '+', :_id].should be_parsed_as('expression')}
36
+ it {[:_id, '+', '(', :_id, '*', :_id, ')'].should be_parsed_as('expression')}
37
+ it {[:_id, '+', '(', :_id, '+', :_id, ')'].should be_parsed_as('expression')}
38
+ it {[:_id, '+', :_id].should_not be_parsed_as('term')}
39
+ end
40
+
41
+ describe Aurum::Engine::BasicParsingCapability, ' LALR(1) : Expression Grammar with operator precedences' do
42
+ include ParserMatcher
43
+ before :all do
44
+ @grammar = ExpressionGrammarWithOperatorPrecedence
45
+ end
46
+ it {[:_id, '+', :_id].should be_parsed_as('expression')}
47
+ it {[:_id, '*', :_id].should be_parsed_as('expression')}
48
+ it {[:_id, '+', :_id, '*', :_id].should be_parsed_as('expression')}
49
+ it {[:_id, '+', :_id, '+', :_id].should be_parsed_as('expression')}
50
+ it {[:_id, '+', '(', :_id, '*', :_id, ')'].should be_parsed_as('expression')}
51
+ it {[:_id, '+', '(', :_id, '+', :_id, ')'].should be_parsed_as('expression')}
52
+ end
53
+
54
+ describe Aurum::Engine::SemanticActionExecutable, ' LALR(2) : BNF grammar in Philippe Charles\' thesis' do
55
+ include ParserMatcher
56
+ before :all do
57
+ @grammar = BnfGrammarWithActions
58
+ end
59
+ it {[:_s, '->', :_s, :_s, :_s].should be_parsed_as('bnf', :s_exp => [[:rule, :_s, [:_s, :_s, :_s]]])}
60
+ it {[:_s, '->', :_s, :_s, '->', :_s].should be_parsed_as('bnf', :s_exp => [[:rule, :_s, [:_s]], [:rule, :_s, [:_s]]])}
61
+ it {[:_s, '->', :_s, '->', :_s].should be_parsed_as('bnf', :s_exp => [[:rule, :_s, []], [:rule, :_s, [:_s]]])}
62
+ it {[:_s, '->', :_s, '->'].should be_parsed_as('bnf', :s_exp => [[:rule, :_s, []], [:rule, :_s, []]])}
63
+ end
64
+
65
+ describe Aurum::Engine::BasicParsingCapability, ' LALR(4) : simple LALR(4) grammar' do
66
+ include ParserMatcher
67
+ before :all do
68
+ @grammar = LALR4Grammar
69
+ end
70
+ it {[:_x, :_w, :_x, :_x, :_x, :_x, :_y].should be_parsed_as('s')}
71
+ it {[:_w, :_x, :_x, :_x, :_y, :_z].should be_parsed_as('s')}
72
+ it {[:_w, :_x, :_x, :_x, :_x, :_z].should be_parsed_as('s')}
73
+ end
74
+
75
+ describe Aurum::Engine::SemanticActionExecutable::SemanticContext do
76
+ it 'lexer should be accessible in semantic context' do
77
+ @context = Aurum::Engine::SemanticActionExecutable::SemanticContext.new('lexer', {}, {})
78
+ (@context.instance_eval {@lexer}).should == 'lexer'
79
+ end
80
+
81
+ it 'should access symbols by name' do
82
+ @context = Aurum::Engine::SemanticActionExecutable::SemanticContext.new('lexer', {'symbolA' => 1}, {})
83
+ @context.symbolA.should == 1
84
+ end
85
+
86
+ it 'should access symbols by alias name' do
87
+ @context = Aurum::Engine::SemanticActionExecutable::SemanticContext.new('lexer', {'symbolA' => 1}, {'symbolB' => 'symbolA'})
88
+ @context.symbolB.should == 1
89
+ end
90
+ end
@@ -0,0 +1,30 @@
1
+ helper_dir = File.join(File.dirname(__FILE__), '..')
2
+ $:.unshift(helper_dir) unless $:.include?(helper_dir)
3
+
4
+ require 'spec_helper'
5
+ require 'dangling_else/grammar'
6
+
7
+ describe 'Dangling Else' do
8
+ before :all do
9
+ DanglingElseLexer = Aurum::Lexer.new(Aurum::Examples::DanglingElse)
10
+ DanglingElseParser = Aurum::Parser.new(Aurum::Examples::DanglingElse, :statement)
11
+ end
12
+
13
+ it 'else should be matched to closest if' do
14
+ parse(<<-EOF).should == [:if, [:expr], [:if, [:expr], [:other], [:other]], nil]
15
+ if ( expr )
16
+ if (expr)
17
+ other
18
+ else
19
+ other
20
+ EOF
21
+ end
22
+
23
+ def scanner source
24
+ DanglingElseLexer.new(source)
25
+ end
26
+
27
+ def parse source
28
+ DanglingElseParser.new.parse(DanglingElseLexer.new(source)).s_exp
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ helper_dir = File.join(File.dirname(__FILE__), '..')
2
+ $:.unshift(helper_dir) unless $:.include?(helper_dir)
3
+
4
+ require 'spec_helper'
5
+ require 'expression/grammar'
6
+
7
+ describe 'Expression Grammar' do
8
+ before :all do
9
+ ExpressionLexer = Aurum::Lexer.new(Aurum::Examples::ExpressionGrammar)
10
+ ExpressionParser = Aurum::Parser.new(Aurum::Examples::ExpressionGrammar, :expression)
11
+ end
12
+
13
+ it '1 + 1 should == 2' do
14
+ parse('1 + 1').should == 2
15
+ end
16
+
17
+ it '2 * 3 should == 6' do
18
+ parse('2 * 3').should == 6
19
+ end
20
+
21
+ it '2 + 2 * 3 should == 8' do
22
+ parse('2 + 2 * 3').should == 8
23
+ end
24
+
25
+ it '(2 + 2) * 3 should == 12' do
26
+ parse('(2 + 2) * 3').should == 12
27
+ end
28
+
29
+ it '3 * (2 + 2) should == 12' do
30
+ parse('3 * (2 + 2)').should == 12
31
+ end
32
+
33
+ it '2 * (2 + 2) * 3 should == 24' do
34
+ parse('2 * (2 + 2) * 3').should == 24
35
+ end
36
+
37
+ it '-2 * -4 should == 8' do
38
+ parse('-2 * -4').should == 8
39
+ end
40
+
41
+ it '-2 - - 4 should == 2' do
42
+ parse('-2 - - 4').should == 2
43
+ end
44
+
45
+ def parse source
46
+ ExpressionParser.new.parse(ExpressionLexer.new(source)).value
47
+ end
48
+ end
@@ -0,0 +1,50 @@
1
+ =begin
2
+ helper_dir = "#{File.dirname(__FILE__)}/../"
3
+ $:.unshift helper_dir unless $:.include?(helper_dir)
4
+ require 'spec_helper'
5
+ require 'smalltalk/grammar'
6
+
7
+ describe 'Little Smalltalk' do
8
+ before :all do
9
+ @logger = Aurum::Builder::GraphvizLogger.new
10
+ @parsing_table = Smalltalk::Grammar.parsing_table :program, @logger
11
+ @lexical_table = Smalltalk::Grammar.lexical_table @logger
12
+ end
13
+
14
+ it 'keyword message sending should be parsed correctly' do
15
+ parse(<<-EOF).should == [:program, [], [[:keyword, [:var, "Transcript"], [["show:", [:var, "helloMessage"]]]]]]
16
+ Transcript show: helloMessage.
17
+ EOF
18
+ end
19
+
20
+ it 'binary message sending should be parsed correctly' do
21
+ parse(<<-EOF).should == [:program, [], [[:binary, [:var, "a"], [["+", [:var, "b"]]]]]]
22
+ a + b.
23
+ EOF
24
+ end
25
+
26
+ it 'unary message sending should be parsed correctly' do
27
+ parse(<<-EOF).should == [:program, [], [[:unary, [:var, "car"], ["go"]]]]
28
+ car go.
29
+ EOF
30
+ end
31
+
32
+ it 'unary message sending should have higher precedence then keyword message sending' do
33
+ parse(<<-EOF).should == [:program, [], [[:keyword, [:var, "Rectangle"], [["width:", [:unary, [:var, "aRect"], ["weight"]]], ["height:", [:unary, [:var, "aRect"], ["height"]]]]]]]
34
+ Rectangle width:aRect weight height:aRect height.
35
+ EOF
36
+ end
37
+
38
+ it 'binary message sending should have higher precedence then keyword message sending' do
39
+ parse(<<-EOF).should == [:program, [], [[:keyword, [:var, "Rectangle"], [["width:", [:binary, [:var, "width"], [["+", [:var, "delta"]]]]], ["height:", [:binary, [:var, "height"], [["+", [:var, "delta"]]]]]]]]]
40
+ Rectangle width:width + delta height:height + delta.
41
+ EOF
42
+ end
43
+
44
+ def parse source
45
+ lexer = Aurum::Engine::Lexer.new(@lexical_table, source)
46
+ parser = Aurum::Engine::Parser.new(@parsing_table)
47
+ parser.parse(lexer).s_exp
48
+ end
49
+ end
50
+ =end