1#!/usr/bin/ruby 2# encoding: utf-8 3 4require 'antlr3/test/functional' 5 6class TestLLStarParser < ANTLR3::Test::Functional 7 inline_grammar( <<-'END' ) 8 grammar LLStar; 9 10 options { language = Ruby; } 11 @header { require 'stringio' } 12 @init { @output = StringIO.new() } 13 @members { 14 def output 15 @output.string 16 end 17 } 18 19 program 20 : declaration+ 21 ; 22 23 /** In this rule, the functionHeader left prefix on the last two 24 * alternatives is not LL(k) for a fixed k. However, it is 25 * LL(*). The LL(*) algorithm simply scans ahead until it sees 26 * either the ';' or the '{' of the block and then it picks 27 * the appropriate alternative. Lookhead can be arbitrarily 28 * long in theory, but is <=10 in most cases. Works great. 29 * Use ANTLRWorks to see the look use (step by Location) 30 * and look for blue tokens in the input window pane. :) 31 */ 32 declaration 33 : variable 34 | functionHeader ';' 35 { @output.puts( $functionHeader.name + " is a declaration") } 36 | functionHeader block 37 { @output.puts( $functionHeader.name + " is a definition") } 38 ; 39 40 variable 41 : type declarator ';' 42 ; 43 44 declarator 45 : ID 46 ; 47 48 functionHeader returns [name] 49 : type ID '(' ( formalParameter ( ',' formalParameter )* )? ')' 50 {$name = $ID.text} 51 ; 52 53 formalParameter 54 : type declarator 55 ; 56 57 type 58 : 'int' 59 | 'char' 60 | 'void' 61 | ID 62 ; 63 64 block 65 : '{' 66 variable* 67 stat* 68 '}' 69 ; 70 71 stat: forStat 72 | expr ';' 73 | block 74 | assignStat ';' 75 | ';' 76 ; 77 78 forStat 79 : 'for' '(' assignStat ';' expr ';' assignStat ')' block 80 ; 81 82 assignStat 83 : ID '=' expr 84 ; 85 86 expr: condExpr 87 ; 88 89 condExpr 90 : aexpr ( ('==' | '<') aexpr )? 91 ; 92 93 aexpr 94 : atom ( '+' atom )* 95 ; 96 97 atom 98 : ID 99 | INT 100 | '(' expr ')' 101 ; 102 103 ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* 104 ; 105 106 INT : ('0'..'9')+ 107 ; 108 109 WS : ( ' ' 110 | '\t' 111 | '\r' 112 | '\n' 113 )+ 114 {$channel=HIDDEN} 115 ; 116 END 117 118 119 example "parsing with a LL(*) grammar" do 120 lexer = LLStar::Lexer.new( <<-'END'.fixed_indent( 0 ) ) 121 char c; 122 int x; 123 124 void bar(int x); 125 126 int foo(int y, char d) { 127 int i; 128 for (i=0; i<3; i=i+1) { 129 x=3; 130 y=5; 131 } 132 } 133 END 134 parser = LLStar::Parser.new lexer 135 136 parser.program 137 parser.output.should == <<-'END'.fixed_indent( 0 ) 138 bar is a declaration 139 foo is a definition 140 END 141 end 142 143end 144