1header
2{
3	using TokenStreamRewriteEngine 	= antlr.TokenStreamRewriteEngine;
4	using TokenWithIndex 			= antlr.TokenWithIndex;
5}
6
7options
8{
9	language = "CSharp";
10}
11
12class TinyCParser extends Parser;
13
14options
15{
16	//importVocab=TinyC; // use vocab generated by lexer
17}
18
19{
20	TokenStreamRewriteEngine engine;
21
22	public TinyCParser(TokenStreamRewriteEngine lexer) : this(lexer, 1)
23	{
24	  engine = lexer;
25	}
26}
27
28program
29	:	( declaration )* EOF
30	;
31
32declaration
33	:	(globalVariable) => globalVariable
34	|	function
35	;
36
37declarator
38	:	id:ID
39	|	STAR id2:ID
40	;
41
42variable
43	:	type declarator SEMI
44	;
45
46/** Convert "int foo;" into "extern int foo;" */
47globalVariable
48    :   {engine.insertBefore(LT(1), "extern ");}
49        variable
50    ;
51
52/** Convert "int foo() {...}" into "extern int foo();" */
53function
54{
55    int rcurly = 0;
56}
57	:	{engine.insertBefore(LT(1), "extern ");}
58        type id:ID LPAREN
59		(formalParameter (COMMA formalParameter)*)?
60		RPAREN
61        block[true]
62	;
63
64formalParameter
65	:	type declarator
66	;
67
68type:	"int" | "char" | ID ;
69
70block[bool functionLevel]
71	:	a:LCURLY ( statement )* b:RCURLY
72        {
73            if ( functionLevel )
74            {
75                int prevTokenIndex = ((TokenWithIndex) a).getIndex()-1;
76                TokenWithIndex prevToken = engine.getToken(prevTokenIndex);
77                if ( prevToken.Type == RPAREN )
78                {
79                    engine.replace(a, b, ";");
80                }
81                else
82                {
83                    engine.replace(prevToken, b, ";"); // replace whitespace too
84                }
85            }
86        }
87	;
88
89statement
90	:	(variable)=>variable
91	|	expr SEMI
92	|	"if" LPAREN expr RPAREN statement
93		( "else" statement )?
94	|	"while" LPAREN expr RPAREN statement
95	|	block[false]
96	;
97
98expr:	assignExpr
99	;
100
101assignExpr
102	:	aexpr (ASSIGN assignExpr)?
103	;
104
105aexpr
106	:	mexpr (PLUS mexpr)*
107	;
108
109mexpr
110	:	atom (STAR atom)*
111	;
112
113atom:	ID
114	|	INT
115	|	CHAR_LITERAL
116	|	STRING_LITERAL
117	;
118
119
120
121class TinyCLexer extends Lexer;
122
123options
124{
125	k				=	2;
126	charVocabulary 	= 	'\3'..'\377';
127}
128
129WS	:	(' '
130	|	'\t'
131	|	'\n'	{newline();}
132	|	'\r')+
133	;
134
135SL_COMMENT :
136	"//"
137	(~'\n')* '\n'
138	{ $setType(Token.SKIP); newline(); }
139	;
140
141ML_COMMENT
142	:	"/*"
143		(	{ LA(2)!='/' }? '*'
144		|	'\n' { newline(); }
145		|	~('*'|'\n')
146		)*
147		"*/"
148			{ $setType(Token.SKIP); }
149	;
150
151
152LPAREN
153	:	'('
154	;
155
156RPAREN
157	:	')'
158	;
159
160LCURLY:	'{'
161	;
162
163RCURLY:	'}'
164	;
165
166STAR:	'*'
167	;
168
169PLUS:	'+'
170	;
171
172ASSIGN
173	:	'='
174	;
175
176SEMI:	';'
177	;
178
179COMMA
180	:	','
181	;
182
183CHAR_LITERAL
184	:	'\'' (options {greedy=false;}:.)* '\''
185	;
186
187STRING_LITERAL
188	:	'"' (options {greedy=false;}:.)* '"'
189	;
190
191protected
192DIGIT
193	:	'0'..'9'
194	;
195
196INT	:	(DIGIT)+
197	;
198
199ID	:	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
200	;
201
202
203