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