1 package gnu.ecmascript; 2 import java.util.Vector ; 3 import gnu.text.SyntaxException; 4 import gnu.mapping.*; 5 import gnu.expr.*; 6 import gnu.lists.Sequence; 7 8 public class Parser 9 { 10 InPort port; 11 Lexer lexer; 12 13 Object previous_token; 14 Object token; 15 16 public static Expression eofExpr = new QuoteExp(Sequence.eofValue); 17 18 public Parser (InPort port) 19 { 20 this.port = port; 21 this.lexer = new Lexer(port); 22 } 23 24 public Expression parseConditionalExpression() 25 throws java.io.IOException , SyntaxException 26 { 27 Expression exp1 = parseBinaryExpression(1); 28 Object result = peekToken(); 29 if (result != Lexer.condToken) 30 return exp1; 31 skipToken(); 32 Expression exp2 = parseAssignmentExpression(); 33 if (getToken() != Lexer.colonToken) 34 return syntaxError("expected ':' in conditional expression"); 35 Expression exp3 = parseAssignmentExpression(); 36 return new IfExp(exp1, exp2, exp3); 37 } 38 39 public Expression parseAssignmentExpression() 40 throws java.io.IOException , SyntaxException 41 { 42 Expression exp1 = parseConditionalExpression(); 43 Object token = peekToken(); 44 if (token == Lexer.equalToken) 45 { 46 skipToken(); 47 Expression exp2 = parseAssignmentExpression(); 48 if (exp1 instanceof ReferenceExp) 49 { 50 SetExp sex = new SetExp(((ReferenceExp) exp1).getName(), exp2); 51 sex.setDefining(true); 52 return sex; 53 } 54 return syntaxError("unmplemented non-symbol ihs in assignment"); 55 } 56 else 57 { 58 if (! (token instanceof Reserved)) 59 return exp1; 60 Reserved op = (Reserved) token; 61 if (!op.isAssignmentOp()) 62 return exp1; 63 skipToken(); 64 Expression exp2 = parseAssignmentExpression(); 65 Expression[] args = { exp1, exp2 }; 66 return new ApplyExp(new QuoteExp(op.proc), args); 67 } 68 } 69 70 public Expression parseExpression() 71 throws java.io.IOException , SyntaxException 72 { 73 Expression[] exps = null; 74 int nExps = 0; 75 for (;;) 76 { 77 Expression exp1 = parseAssignmentExpression(); 78 boolean last = peekToken() != Lexer.commaToken; 79 if (exps == null) 80 { 81 if (last) 82 return exp1; 83 exps = new Expression[2]; 84 } 85 else if (last ? exps.length != nExps + 1 : exps.length <= nExps) 86 { int newsize = last ? nExps + 1 : 2 * exps.length; 88 Expression[] new_exps = new Expression[newsize]; 89 System.arraycopy(exps, 0, new_exps, 0, nExps); 90 exps = new_exps; 91 } 92 exps[nExps++] = exp1; 93 if (last) 94 return new BeginExp(exps); 95 skipToken(); 96 } 97 } 98 99 102 public Object peekTokenOrLine() 103 throws java.io.IOException , SyntaxException 104 { 105 if (token == null) 106 token = lexer.getToken(); 107 return token; 108 } 109 110 113 public Object peekToken() 114 throws java.io.IOException , SyntaxException 115 { 116 if (token == null) 117 token = lexer.getToken(); 118 while (token == Lexer.eolToken) 119 { 120 skipToken(); 121 token = lexer.getToken(); 122 } 123 return token; 124 } 125 126 public Object getToken() 127 throws java.io.IOException , SyntaxException 128 { 129 Object result = peekToken(); 130 skipToken(); 131 return result; 132 } 133 134 public final void skipToken() 135 { 136 if (token != Lexer.eofToken) 137 { 138 previous_token = token; 139 token = null; 140 } 141 } 142 143 144 public void getSemicolon() 145 throws java.io.IOException , SyntaxException 146 { 147 token = peekToken(); 148 if (token == Lexer.semicolonToken) 149 skipToken(); 150 else if (token == Lexer.rbraceToken 151 || token == Lexer.eofToken 152 || previous_token == Lexer.eolToken) 153 ; else 155 syntaxError("missing ';' after expression"); 156 } 157 158 159 public Expression parsePrimaryExpression() 160 throws java.io.IOException , SyntaxException 161 { 162 Object result = getToken(); 163 if (result instanceof QuoteExp) 164 return (QuoteExp) result; 165 if (result instanceof String ) 166 return new ReferenceExp((String ) result); 167 if (result == Lexer.lparenToken) 168 { 169 Expression expr = parseExpression(); 170 Object token = getToken(); 171 if (token != Lexer.rparenToken) 172 return syntaxError("expected ')' - got:"+token); 173 return expr; 174 } 175 return syntaxError("unexpected token: "+result); 176 } 177 178 public Expression makePropertyAccessor (Expression exp, Expression prop) 179 { 180 return null; } 182 183 public final static Expression[] emptyArgs = { }; 184 185 public Expression[] parseArguments() 186 throws java.io.IOException , SyntaxException 187 { 188 skipToken(); 189 Object token = peekToken(); 190 if (token == Lexer.rparenToken) 191 { 192 skipToken(); 193 return emptyArgs; 194 } 195 Vector args = new Vector (10); 196 for (;;) 197 { 198 Expression arg = parseAssignmentExpression(); 199 args.addElement(arg); 200 token = getToken(); 201 if (token == Lexer.rparenToken) 202 break; 203 if (token != Lexer.commaToken) 204 syntaxError("invalid token '"+token+"' in argument list"); 205 } 206 Expression[] exps = new Expression[args.size()]; 207 args.copyInto(exps); 208 return exps; 209 } 210 211 public Expression makeNewExpression(Expression exp, Expression[] args) 212 { 213 if (args == null) 214 args = emptyArgs; 215 exp = null; return new ApplyExp(exp, args); 217 } 218 219 public Expression makeCallExpression(Expression exp, Expression[] args) 220 { 221 return new ApplyExp(exp, args); } 223 224 public String getIdentifier() 225 throws java.io.IOException , SyntaxException 226 { 227 Object token = getToken(); 228 if (token instanceof String ) 229 return (String ) token; 230 syntaxError("missing identifier"); 231 return "??"; 232 } 233 234 public Expression parseLeftHandSideExpression () 235 throws java.io.IOException , SyntaxException 236 { 237 int newCount = 0; 238 while (peekToken() == Lexer.newToken) 239 { 240 newCount++; 241 skipToken(); 242 } 243 Expression exp = parsePrimaryExpression(); 244 for (;;) 245 { 246 Object token = peekToken(); 247 if (token == Lexer.dotToken) 248 { 249 skipToken(); 250 String name = getIdentifier(); 251 exp = makePropertyAccessor(exp, new QuoteExp(name)); 252 } 253 else if (token == Lexer.lbracketToken) 254 { 255 skipToken(); 256 Expression prop = parseExpression(); 257 token = getToken(); 258 if (token != Lexer.rbracketToken) 259 return syntaxError("expected ']' - got:"+token); 260 exp = makePropertyAccessor(exp, prop); 261 } 262 else if (token == Lexer.lparenToken) 263 { 264 Expression[] args = parseArguments(); 265 System.err.println("after parseArgs:"+peekToken()); 266 if (newCount > 0) 267 { 268 exp = makeNewExpression(exp, args); 269 newCount--; 270 } 271 else 272 exp = makeCallExpression(exp, args); 273 } 274 else 275 break; 276 } 277 for (; newCount > 0; newCount--) 278 { 279 exp = makeNewExpression(exp, null); 280 } 281 return exp; 282 } 283 284 public Expression parsePostfixExpression () 285 throws java.io.IOException , SyntaxException 286 { 287 Expression exp = parseLeftHandSideExpression(); 288 Object op = peekTokenOrLine(); 289 if (op != Reserved.opPlusPlus && op != Reserved.opMinusMinus) 290 return exp; 291 skipToken(); 292 Expression[] args = { exp }; 293 return new ApplyExp(new QuoteExp(((Reserved)op).proc), args); 294 } 295 296 297 public Expression parseUnaryExpression () 298 throws java.io.IOException , SyntaxException 299 { 300 return parsePostfixExpression(); 303 } 304 305 public int errors; 306 307 public Expression syntaxError(String message) 308 { 309 errors++; 311 OutPort err = OutPort.errDefault(); 312 String current_filename = port.getName(); 313 int current_line = port.getLineNumber()+1; 314 int current_column = port.getColumnNumber()+1; 315 if (current_line > 0) 316 { 317 if (current_filename != null) 318 err.print (current_filename); 319 err.print (':'); 320 err.print (current_line); 321 if (current_column > 1) 322 { 323 err.print (':'); 324 err.print (current_column); 325 } 326 err.print (": "); 327 } 328 err.println (message); 329 return new ErrorExp (message); 330 } 331 332 public Expression parseBinaryExpression(int prio) 333 throws java.io.IOException , SyntaxException 334 { 335 Expression exp1 = parseUnaryExpression(); 336 for (;;) 337 { 338 token = peekToken(); 339 if (! (token instanceof Reserved)) 340 return exp1; 341 Reserved op = (Reserved) token; 342 if (op.prio < prio) 343 return exp1; 344 getToken(); 345 Expression exp2 = parseBinaryExpression(op.prio+1); 346 Expression[] args = { exp1, exp2 }; 347 exp1 = new ApplyExp(new QuoteExp(op.proc), args); 348 } 349 } 350 351 static Expression emptyStatement = new QuoteExp(Values.empty); 352 353 public Expression parseIfStatement() 354 throws java.io.IOException , SyntaxException 355 { 356 skipToken(); 357 Object token = getToken(); 358 if (token != Lexer.lparenToken) 359 return syntaxError("expected '(' - got:"+token); 360 Expression test_part = parseExpression(); 361 token = getToken(); 362 if (token != Lexer.rparenToken) 363 return syntaxError("expected ')' - got:"+token); 364 Expression then_part = parseStatement(); 365 token = peekToken(); 366 Expression else_part; 367 if (token == Lexer.elseToken) 368 { 369 skipToken(); 370 else_part = parseStatement(); 371 } 372 else 373 else_part = null; 374 return new IfExp(test_part, then_part, else_part); 375 } 376 377 public Expression buildLoop (Expression init, Expression test, 378 Expression incr, Expression body) 379 { 380 if (init != null) 381 { 382 Expression[] pair = new Expression[2]; 383 pair[0] = init; 384 pair[1] = buildLoop (null, test, incr, body); 385 return new BeginExp(pair); 386 } 387 throw new Error ("not implemented - buildLoop"); 388 } 389 390 public Expression parseWhileStatement() 391 throws java.io.IOException , SyntaxException 392 { 393 skipToken(); Object token = getToken(); 395 if (token != Lexer.lparenToken) 396 return syntaxError("expected '(' - got:"+token); 397 Expression test_part = parseExpression(); 398 token = getToken(); 399 if (token != Lexer.rparenToken) 400 return syntaxError("expected ')' - got:"+token); 401 Expression body = parseStatement(); 402 return buildLoop (null, test_part, null, body); 403 } 404 405 public Expression parseFunctionDefinition() 406 throws java.io.IOException , SyntaxException 407 { 408 skipToken(); 409 String name = getIdentifier(); 410 Object token = getToken(); 411 if (token != Lexer.lparenToken) 412 return syntaxError("expected '(' - got:"+token); 413 Vector args = new Vector (10); 414 if (peekToken() == Lexer.rparenToken) 415 { 416 skipToken(); 417 } 418 else 419 { 420 for (;;) 421 { 422 String arg = getIdentifier(); 423 args.addElement(arg); 424 token = getToken(); 425 if (token == Lexer.rparenToken) 426 break; 427 if (token != Lexer.commaToken) 428 syntaxError("invalid token '"+token+"' in argument list"); 429 } 430 } 431 Expression body = parseBlock(); 432 LambdaExp lexp = new LambdaExp(body); 433 lexp.setName(name); 434 SetExp sexp = new SetExp(name, lexp); 435 sexp.setDefining(true); 436 return sexp; 437 } 438 439 public Expression parseBlock() 440 throws java.io.IOException , SyntaxException 441 { 442 Expression[] exps = null; 443 if (getToken() != Lexer.lbraceToken) 444 return syntaxError("extened '{'"); 445 int nExps = 0; 446 for (;;) 447 { 448 token = peekToken(); 449 boolean last; 450 if (token == Lexer.rbraceToken) 451 { 452 skipToken(); 453 if (exps == null) 454 return emptyStatement; 455 last = true; 456 } 457 else 458 last = false; 459 if (exps == null) 460 exps = new Expression[2]; 461 else if (last ? exps.length !=nExps : exps.length <= nExps) 462 { int newsize = last ? nExps : 2 * exps.length; 464 Expression[] new_exps = new Expression[newsize]; 465 System.arraycopy(exps, 0, new_exps, 0, nExps); 466 exps = new_exps; 467 } 468 if (last) 469 return new BeginExp(exps); 470 exps[nExps++] = parseStatement(); 471 } 472 } 473 474 public Expression parseStatement() 475 throws java.io.IOException , SyntaxException 476 { 477 Object token = peekToken(); 478 if (token instanceof Reserved) 479 { 480 switch (((Reserved) token).prio) 481 { 482 case Reserved.IF_TOKEN: return parseIfStatement(); 483 case Reserved.WHILE_TOKEN: return parseWhileStatement(); 484 case Reserved.FUNCTION_TOKEN: return parseFunctionDefinition(); 485 } 486 } 487 if (token == Lexer.eofToken) 488 return eofExpr; 489 if (token == Lexer.semicolonToken) 490 { 491 skipToken(); 492 return emptyStatement; 493 } 494 if (token == Lexer.lbraceToken) 495 return parseBlock(); 496 497 Expression exp = parseExpression(); 498 getSemicolon(); 499 return exp; 500 } 501 502 public static void main (String [] args) 503 { 504 Language language = new kawa.standard.Scheme(); 506 InPort inp = InPort.inDefault (); 507 if (inp instanceof TtyInPort) 508 { 509 Object prompter = new Prompter(); 510 ((TtyInPort)inp).setPrompter((Procedure) prompter); 511 } 512 513 Parser parser = new Parser(inp); 514 OutPort out = OutPort.outDefault(); 515 for (;;) 516 { 517 try 518 { 519 530 Expression expr = parser.parseStatement(); 531 if (expr == eofExpr) 532 break; 533 out.print("[Expression: "); 534 expr.print(out); 535 out.println("]"); 536 Object result = expr.eval(Environment.user()); 537 out.print("result: "); 538 out.print(result); 539 out.println(); 540 } 541 catch (Throwable ex) 542 { 543 System.err.println("caught exception:"+ex); 544 ex.printStackTrace(System.err); 545 return; 546 } 547 } 548 } 549 } 550 | Popular Tags |