1grammar t018llstar;
2
3options {
4    language = Python3;
5}
6
7@header {
8from io import StringIO
9}
10
11@init {
12self.output = StringIO()
13}
14
15program
16    :   declaration+
17    ;
18
19/** In this rule, the functionHeader left prefix on the last two
20 *  alternatives is not LL(k) for a fixed k.  However, it is
21 *  LL(*).  The LL(*) algorithm simply scans ahead until it sees
22 *  either the ';' or the '{' of the block and then it picks
23 *  the appropriate alternative.  Lookhead can be arbitrarily
24 *  long in theory, but is <=10 in most cases.  Works great.
25 *  Use ANTLRWorks to see the lookahead use (step by Location)
26 *  and look for blue tokens in the input window pane. :)
27 */
28declaration
29    :   variable
30    |   functionHeader ';'
31	{self.output.write($functionHeader.name+" is a declaration\n")}
32    |   functionHeader block
33	{self.output.write($functionHeader.name+" is a definition\n")}
34    ;
35
36variable
37    :   type declarator ';'
38    ;
39
40declarator
41    :   ID
42    ;
43
44functionHeader returns [name]
45    :   type ID '(' ( formalParameter ( ',' formalParameter )* )? ')'
46	{$name = $ID.text}
47    ;
48
49formalParameter
50    :   type declarator
51    ;
52
53type
54    :   'int'
55    |   'char'
56    |   'void'
57    |   ID
58    ;
59
60block
61    :   '{'
62            variable*
63            stat*
64        '}'
65    ;
66
67stat: forStat
68    | expr ';'
69    | block
70    | assignStat ';'
71    | ';'
72    ;
73
74forStat
75    :   'for' '(' assignStat ';' expr ';' assignStat ')' block
76    ;
77
78assignStat
79    :   ID '=' expr
80    ;
81
82expr:   condExpr
83    ;
84
85condExpr
86    :   aexpr ( ('==' | '<') aexpr )?
87    ;
88
89aexpr
90    :   atom ( '+' atom )*
91    ;
92
93atom
94    : ID
95    | INT
96    | '(' expr ')'
97    ;
98
99ID  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
100    ;
101
102INT :	('0'..'9')+
103    ;
104
105WS  :   (   ' '
106        |   '\t'
107        |   '\r'
108        |   '\n'
109        )+
110        {$channel=HIDDEN}
111    ;
112