Differences From Artifact [31eeea68e341add3]:
- File
polemy/parse.d
- 2010-11-07 16:31:52 - part of checkin [633e700889] on branch trunk - If-expression implemented. Factorial now works. (user: kinaba) [annotate]
To Artifact [752d9af2ecdd593b]:
- File
polemy/parse.d
- 2010-11-08 08:45:51 - part of checkin [8d297342aa] on branch trunk - Replaced Token.Kind with bool quoted (user: kinaba) [annotate]
4 * 4 *
5 * Parser for Polemy programming language 5 * Parser for Polemy programming language
6 */ 6 */
7 module polemy.parse; 7 module polemy.parse;
8 import polemy._common; 8 import polemy._common;
9 import polemy.lex; 9 import polemy.lex;
10 import polemy.ast; 10 import polemy.ast;
11 import std.bigint; <
12 11
13 /// Parsing Failure 12 /// Parsing Failure
14 13
15 class ParserException : Exception 14 class ParserException : Exception
16 { 15 {
17 private: 16 private:
18 this(string msg) { super(msg); } 17 this(string msg) { super(msg); }
................................................................................................................................................................................
62 } 61 }
63 return p; 62 return p;
64 } 63 }
65 64
66 Program parseStatements() 65 Program parseStatements()
67 { 66 {
68 Program p; 67 Program p;
69 while( !lex.empty && (lex.front.kind!=Token.Kind.identifier || l | 68 while( !lex.empty && (lex.front.quoted || lex.front.str!="}") )
70 p ~= parseStatement(); 69 p ~= parseStatement();
71 return p; 70 return p;
72 } 71 }
73 72
74 Statement parseStatement() 73 Statement parseStatement()
75 { 74 {
76 auto saved = lex.save; 75 auto saved = lex.save;
77 scope(failure) lex = saved; 76 scope(failure) lex = saved;
78 77
79 if( lex.empty ) 78 if( lex.empty )
80 throw new ParserException("EOF during parsing a statemen 79 throw new ParserException("EOF during parsing a statemen
81 auto pos = lex.front.pos; 80 auto pos = lex.front.pos;
82 81
83 if( lex.front.kind==Token.Kind.identifier && lex.front.str=="var | 82 if( !lex.front.quoted && lex.front.str=="var" )
84 { 83 {
85 // "var" Var "=" Expression ";" 84 // "var" Var "=" Expression ";"
86 lex.popFront; 85 lex.popFront;
87 string var = lex.front.str; 86 string var = lex.front.str;
88 lex.popFront; 87 lex.popFront;
89 eat("=", "for variable declaration"); 88 eat("=", "for variable declaration");
90 auto parsed = new DeclStatement(pos, var, parseExpressio 89 auto parsed = new DeclStatement(pos, var, parseExpressio
................................................................................................................................................................................
177 176
178 Expression parseBaseBaseExpression() 177 Expression parseBaseBaseExpression()
179 { 178 {
180 if( lex.empty ) 179 if( lex.empty )
181 throw new ParserException("EOF during parsing an express 180 throw new ParserException("EOF during parsing an express
182 auto pos = lex.front.pos; 181 auto pos = lex.front.pos;
183 182
184 if( lex.front.kind == Token.Kind.number ) | 183 if( lex.front.quoted )
> 184 {
> 185 scope(exit) lex.popFront;
> 186 return new StrLiteralExpression(pos, lex.front.str);
> 187 }
> 188 if( isNumber(lex.front.str) ) // is_number
185 { 189 {
186 scope(exit) lex.popFront; 190 scope(exit) lex.popFront;
187 return new IntLiteralExpression(pos, BigInt(cast(string) 191 return new IntLiteralExpression(pos, BigInt(cast(string)
188 } 192 }
189 if( lex.front.kind == Token.Kind.stringLiteral ) <
190 { <
191 scope(exit) lex.popFront; <
192 return new StrLiteralExpression(pos, lex.front.str); <
193 } <
194 if( tryEat("(") ) 193 if( tryEat("(") )
195 { 194 {
196 auto e = parseE(); 195 auto e = parseE();
197 eat(")", "after parenthesized expression"); 196 eat(")", "after parenthesized expression");
198 return e; 197 return e;
199 } 198 }
200 if( tryEat("if") ) 199 if( tryEat("if") )
................................................................................................................................................................................
227 string[] params; 226 string[] params;
228 while(!tryEat(")")) 227 while(!tryEat(")"))
229 { 228 {
230 if( lex.empty ) { 229 if( lex.empty ) {
231 auto e = ParserException.create(lex,"Une 230 auto e = ParserException.create(lex,"Une
232 throw e; 231 throw e;
233 } 232 }
234 if( lex.front.kind != Token.Kind.identifier ) { | 233 if( lex.front.quoted ) {
235 auto e = ParserException.create(lex,"Ide 234 auto e = ParserException.create(lex,"Ide
236 throw e; 235 throw e;
237 } 236 }
238 params ~= lex.front.str; 237 params ~= lex.front.str;
239 lex.popFront; 238 lex.popFront;
240 if( !tryEat(",") ) { 239 if( !tryEat(",") ) {
241 eat(")", "after function parameters"); 240 eat(")", "after function parameters");
................................................................................................................................................................................
268 ~(lex.empty ? "EOF" : lex.front.str)~"' occured" 267 ~(lex.empty ? "EOF" : lex.front.str)~"' occured"
269 throw e; 268 throw e;
270 } 269 }
271 } 270 }
272 271
273 bool tryEat(string kwd) 272 bool tryEat(string kwd)
274 { 273 {
275 if( lex.empty || lex.front.kind!=Token.Kind.identifier || lex.fr | 274 if( lex.empty || lex.front.quoted || lex.front.str!=kwd )
276 return false; 275 return false;
277 lex.popFront; 276 lex.popFront;
278 return true; 277 return true;
279 } 278 }
> 279
> 280 bool isNumber(string s)
> 281 {
> 282 return find!(`a<'0'||'9'<a`)(s).empty;
> 283 }
280 } 284 }
281 285
282 unittest 286 unittest
283 { 287 {
284 auto p = parserFromString(` 288 auto p = parserFromString(`
285 var x = 100; 289 var x = 100;
286 var y = 200; 290 var y = 200;
................................................................................................................................................................................
339 new IntLiteralExpression(null, BigInt(1)), 343 new IntLiteralExpression(null, BigInt(1)),
340 new FuncallExpression(null, 344 new FuncallExpression(null,
341 new FunLiteralExpression(null, ["abc"], [ 345 new FunLiteralExpression(null, ["abc"], [
342 ]), 346 ]),
343 new IntLiteralExpression(null, BigInt(4)) 347 new IntLiteralExpression(null, BigInt(4))
344 )))); 348 ))));
345 } 349 }
> 350
> 351 /*
346 unittest 352 unittest
347 { 353 {
348 auto p = parserFromString(`var x = 1; var f = fun(){x=x+1;}; f(); f(); x 354 auto p = parserFromString(`var x = 1; var f = fun(){x=x+1;}; f(); f(); x
349 Program prog = p.parseProgram(); 355 Program prog = p.parseProgram();
350 } 356 }
351 357
352 unittest 358 unittest
................................................................................................................................................................................
357 new VarExpression(null, "if"), 363 new VarExpression(null, "if"),
358 new FuncallExpression(null, new VarExpression(null,"<"), new Var 364 new FuncallExpression(null, new VarExpression(null,"<"), new Var
359 new IntLiteralExpression(null, BigInt(2))), 365 new IntLiteralExpression(null, BigInt(2))),
360 new FunLiteralExpression(null, [], [new ExprStatement(null, new 366 new FunLiteralExpression(null, [], [new ExprStatement(null, new
361 new FunLiteralExpression(null, [], [new ExprStatement(null, new 367 new FunLiteralExpression(null, [], [new ExprStatement(null, new
362 ))); 368 )));
363 } 369 }
> 370 */