1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#!/usr/bin/ruby 2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# encoding: utf-8 3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverrequire 'antlr3/test/functional' 5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass TestAutoAST < ANTLR3::Test::Functional 7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def parse( grammar, rule, input, expect_errors = false ) 9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @grammar = inline_grammar( grammar ) 10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver compile_and_load @grammar 11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module = self.class.const_get( @grammar.name ) 12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Lexer.send( :include, ANTLR3::Test::CollectErrors ) 14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Lexer.send( :include, ANTLR3::Test::CaptureOutput ) 15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Parser.send( :include, ANTLR3::Test::CollectErrors ) 16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Parser.send( :include, ANTLR3::Test::CaptureOutput ) 17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver lexer = grammar_module::Lexer.new( input ) 19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver parser = grammar_module::Parser.new( lexer ) 20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver r = parser.send( rule ) 22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver parser.reported_errors.should be_empty unless expect_errors 23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = '' 24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver unless r.nil? 26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result += r.result if r.respond_to?( :result ) 27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result += r.tree.inspect if r.tree 28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return( expect_errors ? [ result, parser.reported_errors ] : result ) 30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver def tree_parse( grammar, tree_grammar, rule, tree_rule, input ) 33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @grammar = inline_grammar( grammar ) 34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @tree_grammar = inline_grammar( tree_grammar ) 35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver compile_and_load @grammar 36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver compile_and_load @tree_grammar 37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module = self.class.const_get( @grammar.name ) 39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tree_grammar_module = self.class.const_get( @tree_grammar.name ) 40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Lexer.send( :include, ANTLR3::Test::CollectErrors ) 42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Lexer.send( :include, ANTLR3::Test::CaptureOutput ) 43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Parser.send( :include, ANTLR3::Test::CollectErrors ) 44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar_module::Parser.send( :include, ANTLR3::Test::CaptureOutput ) 45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tree_grammar_module::TreeParser.send( :include, ANTLR3::Test::CollectErrors ) 46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tree_grammar_module::TreeParser.send( :include, ANTLR3::Test::CaptureOutput ) 47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver lexer = grammar_module::Lexer.new( input ) 49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver parser = grammar.module::Parser.new( lexer ) 50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver r = parser.send( rule ) 51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver nodes = ANTLR3::CommonTreeNodeStream( r.tree ) 52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver nodes.token_stream = parser.input 53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver walker = tree_grammar_module::TreeParser.new( nodes ) 54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver r = walker.send( tree_rule ) 55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return( r ? r.tree.inspect : '' ) 57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example 'flat token list' do 61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'abc 34' ) 62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TokenList; 63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID INT ; 65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;}; 68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'abc 34' 70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example 'token list in a single-alternative subrule' do 73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'abc 34' ) 74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TokenListInSingleAltBlock; 75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : (ID INT) ; 77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'abc 34' 82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "simple root at the outer level via the `^' operator" do 85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'abc 34' ) 86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar SimpleRootAtOuterLevel; 87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID^ INT ; 89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(abc 34)' 94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "outer-level root changing token order from the `^' operator" do 97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '34 abc' ) 98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar SimpleRootAtOuterLevelReverse; 99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : INT ID^ ; 101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(abc 34)' 106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "leaving out tokens using the `!' operator" do 109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'abc 34 dag 4532' ) 110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar Bang; 111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID INT! ID! INT ; 113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'abc 4532' 119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "tokens in `(...)?' optional subrule" do 122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a 1 b' ) 123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar OptionalThenRoot; 124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ( ID INT )? ID^ ; 126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(b a 1)' 131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "labeled literal-string root token" do 134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'void foo;' ) 135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar LabeledStringRoot; 136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : v='void'^ ID ';' ; 138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(void foo ;)' 143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example 'rule with token wildcard' do 146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'void foo;' ) 147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar Wildcard; 148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : v='void'^ . ';' ; 150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(void foo ;)' 155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "token wildcard as root via the `^' operator" do 158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'void foo;' ) 159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar WildcardRoot; 160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : v='void' .^ ';' ; 162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(foo void ;)' 167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "labeled token wildcard as root via the `^' operator" do 170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'void foo;' ) 171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar WildcardRootWithLabel; 172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : v='void' x=.^ ';' ; 174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(foo void ;)' 179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "token wildcard as root (with list label)" do 183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'void foo;' ) 184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar WildcardRootWithListLabel; 185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : v='void' x=.^ ';' ; 187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(foo void ;)' 193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "trashed token wildcard" do 196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'void foo;' ) 197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar WildcardBangWithListLabel; 198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : v='void' x=.! ';' ; 200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'void ;' 206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "multiple occurences of the `^' operator in a list of tokens" do 209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a 34 c' ) 210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RootRoot; 211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID^ INT^ ID ; 213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(34 a c)' 219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "another case of multiple occurences of the `^' operator" do 222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a 34 c' ) 223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RootRoot2; 224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID INT^ ID^ ; 226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(c (34 a))' 232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "root-hoist using `^' from within a (...)+ block" do 235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a 34 * b 9 * c' ) 236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RootThenRootInLoop; 237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID^ (INT '*'^ ID)+ ; 239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(* (* (a 34) b 9) c)' 245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "nested subrules without any AST ops resulting in a flat list" do 248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'void a b;' ) 249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NestedSubrule; 250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : 'void' (({ 252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver #do nothing 253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } ID|INT) ID | 'null' ) ';' ; 254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'void a b ;' 260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "invoking another rule without any AST ops, resulting in a flat list" do 263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'int a' ) 264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar InvokeRule; 265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : type ID ; 267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver type : { 268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # do nothing 269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }'int' | 'float' ; 270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'int a' 276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting the results of another rule as root using the `^' operator" do 279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'int a' ) 280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar InvokeRuleAsRoot; 281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : type^ ID ; 283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver type : { 284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # do nothing 285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }'int' | 'float' ; 286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(int a)' 292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting another rule's true as root using the `^' operator (with a label)" do 295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'int a' ) 296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar InvokeRuleAsRootWithLabel; 297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : x=type^ ID ; 299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver type : { 300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # do nothing 301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }'int' | 'float' ; 302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(int a)' 308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting another rule's result tree as root using the `^' operator (with a list += label)" do 311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'int a' ) 312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar InvokeRuleAsRootWithListLabel; 313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : x+=type^ ID ; 315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver type : { 316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # do nothing 317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }'int' | 'float' ; 318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(int a)' 324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "root-hoist via `^' within a (...)* loop resulting in a deeply-nested tree" do 327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a+b+c+d' ) 328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RuleRootInLoop; 329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID ('+'^ ID)* ; 331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(+ (+ (+ a b) c) d)' 337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting another rule's result tree as root from within a (...)* loop resulting in a deeply nested tree" do 340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a+b+c-d' ) 341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RuleInvocationRuleRootInLoop; 342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID (op^ ID)* ; 344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver op : { 345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver # do nothing 346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }'+' | '-' ; 347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(- (+ (+ a b) c) d)' 353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "using tail recursion to build deeply-nested expression trees" do 356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :s, '3 exp 4 exp 5' ) 357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TailRecursion; 358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver s : a ; 360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : atom ('exp'^ a)? ; 361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver atom : INT ; 362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(exp 3 (exp 4 5))' 368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "simple token node from a token type set" do 371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'abc' ) 372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TokenSet; 373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby; output=AST;} 374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID|INT ; 375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'abc' 380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting a token-type set token as root with `^'" do 383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '+abc' ) 384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar SetRoot; 385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ('+' | '-')^ ID ; 387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(+ abc)' 393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting a token-type set token as root with `^' (with a label)" do 396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '+abc' ) 397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar SetRootWithLabel; 398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : (x=('+' | '-'))^ ID ; 400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '+ abc' 406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting a token-type set token as root from within a (...)* loop" do 409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a+b-c' ) 410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar SetAsRuleRootInLoop; 411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID (('+'|'-')^ ID)* ; 413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(- (+ a b) c)' 419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "an `~' inverted token-type set element" do 422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '34+2' ) 423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NotSet; 424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ~ID '+' INT ; 426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '34 + 2' 432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "a `~' inverted token-type set in a rule (with a label)" do 435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '34+2' ) 436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NotSetWithLabel; 437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : x=~ID '+' INT ; 439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '34 + 2' 445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "a `~' inverted token-type set element in a rule (with a list += label)" do 448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '34+2' ) 449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NotSetWithListLabel; 450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : x=~ID '+' INT ; 452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '34 + 2' 458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "a `~' inverted token-type set element hoisted to root via `^'" do 461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '34 55' ) 462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NotSetRoot; 463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ~'+'^ INT ; 465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(34 55)' 471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting a `~' inverted token-type set to root using `^' (with label)" do 474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '34 55' ) 475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NotSetRootWithLabel; 476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : x=~'+'^ INT ; 478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(34 55)' 483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting a `~' inverted token-type set to root using `^' (with list += label)" do 486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '34 55' ) 487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NotSetRootWithListLabel; 488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : x+=~'+'^ INT ; 490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(34 55)' 495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "hoisting a `~' inverted token-type set to root from within a (...)* loop" do 498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, '3+4+5' ) 499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NotSetRuleRootInLoop; 500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : INT (~INT^ INT)* ; 502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver blort : '+' ; 503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(+ (+ 3 4) 5)' 509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "multiple tokens with the same label in a rule" do 512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a b' ) 513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TokenLabelReuse; 514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a returns [result] : id=ID id=ID { 516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver $result = "2nd id=\%s," \% $id.text 517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } ; 518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '2nd id=b,a b' 524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "multiple tokens with the same label in a rule (with a `^' root hoist)" do 527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a b' ) 528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TokenLabelReuse2; 529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a returns [result]: id=ID id=ID^ {$result = "2nd id=#{$id.text},"} ; 531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '2nd id=b,(b a)' 537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "extra token in a simple declaration" do 540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :decl, 'int 34 x=1;', true ) 541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar ExtraTokenInSimpleDecl; 542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver decl : type^ ID '='! INT ';'! ; 544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver type : 'int' | 'float' ; 545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 1:4 extraneous input \"34\" expecting ID" ] 551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(int x 1)' 552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "missing ID in a simple declaration" do 555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :decl, 'int =1;', true ) 556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar MissingIDInSimpleDecl; 557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokens {EXPR;} 559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver decl : type^ ID '='! INT ';'! ; 560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver type : 'int' | 'float' ; 561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 1:4 missing ID at \"=\"" ] 566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(int <missing ID> 1)' 567324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 568324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 569324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "missing token of a token-type set in a simple declaration" do 570324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :decl, 'x=1;', true ) 571324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar MissingSetInSimpleDecl; 572324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 573324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokens {EXPR;} 574324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver decl : type^ ID '='! INT ';'! ; 575324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver type : 'int' | 'float' ; 576324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 577324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 578324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 579324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 580324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 581324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 1:0 mismatched input \"x\" expecting set nil" ] 582324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '(<error: x> x 1)' 583324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 584324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 585324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "missing INT token simulated with a `<missing INT>' error node" do 586324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :a, 'abc', true ) 587324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar MissingTokenGivesErrorNode; 588324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 589324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID INT ; // follow is EOF 590324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 591324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 592324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 593324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 594324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 595324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 0:-1 missing INT at \"<EOF>\"" ] 596324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'abc <missing INT>' 597324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 598324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 599324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "missing token from invoked rule results in error node with a resync attribute" do 600324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :a, 'abc', true ) 601324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar MissingTokenGivesErrorNodeInInvokedRule; 602324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 603324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : b ; 604324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b : ID INT ; // follow should see EOF 605324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 606324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 607324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 608324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 609324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 610324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 0:-1 mismatched input \"<EOF>\" expecting INT" ] 611324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '<mismatched token: <EOF>, resync = abc>' 612324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 613324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 614324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "extraneous ID token displays error and is ignored in AST output" do 615324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :a, 'abc ick 34', true ) 616324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar ExtraTokenGivesErrorNode; 617324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 618324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : b c ; 619324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b : ID ; 620324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver c : INT ; 621324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 622324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 623324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 624324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 625324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 626324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 1:4 extraneous input \"ick\" expecting INT" ] 627324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'abc 34' 628324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 629324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 630324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "missing ID token simulated with a `<missing ID>' error node" do 631324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :a, '34', true ) 632324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar MissingFirstTokenGivesErrorNode; 633324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 634324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : ID INT ; 635324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 636324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 637324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 638324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 639324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 640324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 1:0 missing ID at \"34\"" ] 641324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '<missing ID> 34' 642324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 643324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 644324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "another case where a missing ID token is simulated with a `<missing ID>' error node" do 645324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :a, '34', true ) 646324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar MissingFirstTokenGivesErrorNode2; 647324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 648324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : b c ; 649324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b : ID ; 650324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver c : INT ; 651324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 652324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 653324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 654324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 655324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 656324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 1:0 missing ID at \"34\"" ] 657324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '<missing ID> 34' 658324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 659324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 660324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "no viable alternative for rule is represented as a single `<unexpected: ...>' error node" do 661324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result, errors = parse( <<-'END', :a, '*', true ) 662324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar NoViableAltGivesErrorNode; 663324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 664324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : b | c ; 665324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b : ID ; 666324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver c : INT ; 667324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 668324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver S : '*' ; 669324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 670324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 671324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 672324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver errors.should == [ "line 1:0 no viable alternative at input \"*\"" ] 673324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == "<unexpected: 0 S[\"*\"] @ line 1 col 0 (0..0), resync = *>" 674324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 675324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 676324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "token with a `+=' list label hoisted to root with `^'" do 677324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a' ) 678324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TokenListLabelRuleRoot; 679324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 680324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : id+=ID^ ; 681324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 682324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 683324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 684324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 685324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 686324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'a' 687324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 688324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 689324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "token with a list `+=' label trashed with `!'" do 690324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a' ) 691324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar TokenListLabelBang; 692324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 693324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : id+=ID! ; 694324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 695324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 696324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 697324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 698324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 699324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '' 700324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 701324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 702324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "using list `+=' labels to collect trees of invoked rules" do 703324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a b' ) 704324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RuleListLabel; 705324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 706324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a returns [result]: x+=b x+=b { 707324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver t = $x[1] 708324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver $result = "2nd x=#{t.inspect}," 709324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver }; 710324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b : ID; 711324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 712324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 713324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 714324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 715324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 716324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '2nd x=b,a b' 717324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 718324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 719324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "using a list `+=' label to collect the trees of invoked rules within a (...)+ block" do 720324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a b' ) 721324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RuleListLabelRuleRoot; 722324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 723324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a returns [result] : ( x+=b^ )+ { 724324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver $result = "x=\%s," \% $x[1].inspect 725324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } ; 726324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b : ID; 727324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 728324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 729324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 730324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 731324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 732324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'x=(b a),(b a)' 733324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 734324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 735324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "trashing the tree of an invoked rule with `!' while collecting the tree with a list `+=' label" do 736324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a b' ) 737324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar RuleListLabelBang; 738324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 739324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a returns [result] : x+=b! x+=b { 740324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver $result = "1st x=#{$x[0].inspect}," 741324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } ; 742324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b : ID; 743324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 744324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 745324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 746324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 747324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 748324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == '1st x=a,b' 749324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 750324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 751324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "a whole bunch of different elements" do 752324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'a b b c c d' ) 753324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar ComplicatedMelange; 754324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 755324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a : A b=B b=B c+=C c+=C D {s = $D.text} ; 756324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver A : 'a' ; 757324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver B : 'b' ; 758324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver C : 'c' ; 759324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver D : 'd' ; 760324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 761324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 762324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'a b b c c d' 763324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 764324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 765324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "rule return values in addition to AST output" do 766324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :a, 'abc 34' ) 767324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar ReturnValueWithAST; 768324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options {language=Ruby;output=AST;} 769324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver a returns [result] : ID b { $result = $b.i.to_s + "\n" } ; 770324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver b returns [i] : INT {$i=$INT.text.to_i}; 771324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z'+ ; 772324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9'+; 773324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS : (' '|'\n') {$channel=HIDDEN;} ; 774324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 775324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 776324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == "34\nabc 34" 777324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 778324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 779324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver example "a (...)+ loop containing a token-type set" do 780324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result = parse( <<-'END', :r, 'abc 34 d' ) 781324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver grammar SetLoop; 782324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver options { language=Ruby;output=AST; } 783324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver r : (INT|ID)+ ; 784324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ID : 'a'..'z' + ; 785324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver INT : '0'..'9' +; 786324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver WS: (' ' | '\n' | '\t')+ {$channel = HIDDEN;}; 787324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 788324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver END 789324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver result.should == 'abc 34 d' 790324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver end 791324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 792324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend 793