KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > ecmascript > Parser


1 package gnu.ecmascript;
2 import java.util.Vector JavaDoc;
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 JavaDoc previous_token;
14   Object JavaDoc 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 JavaDoc, SyntaxException
26   {
27     Expression exp1 = parseBinaryExpression(1);
28     Object JavaDoc 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 JavaDoc, SyntaxException
41   {
42     Expression exp1 = parseConditionalExpression();
43     Object JavaDoc 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 JavaDoc, 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       { // need to resize
87
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   /** Return the next token from the lexer.
100    * A LineTerminator is considered a token.
101    */

102   public Object JavaDoc peekTokenOrLine()
103     throws java.io.IOException JavaDoc, SyntaxException
104   {
105     if (token == null)
106       token = lexer.getToken();
107     return token;
108   }
109
110   /** Return the next non-whitespace token from the lexer.
111    * LineTerminators are skipped until a non-eolToken is found.
112    */

113   public Object JavaDoc peekToken()
114     throws java.io.IOException JavaDoc, 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 JavaDoc getToken()
127     throws java.io.IOException JavaDoc, SyntaxException
128   {
129     Object JavaDoc 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   /** Skip an explicit or implicit semicolon. */
144   public void getSemicolon()
145     throws java.io.IOException JavaDoc, 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     ; // implicit ("inserted") semicolon
154
else
155       syntaxError("missing ';' after expression");
156   }
157
158
159   public Expression parsePrimaryExpression()
160     throws java.io.IOException JavaDoc, SyntaxException
161   {
162     Object JavaDoc result = getToken();
163     if (result instanceof QuoteExp)
164       return (QuoteExp) result;
165     if (result instanceof String JavaDoc)
166       return new ReferenceExp((String JavaDoc) result);
167     if (result == Lexer.lparenToken)
168       {
169     Expression expr = parseExpression();
170     Object JavaDoc 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; // FIXME
181
}
182
183   public final static Expression[] emptyArgs = { };
184
185   public Expression[] parseArguments()
186     throws java.io.IOException JavaDoc, SyntaxException
187   {
188     skipToken();
189     Object JavaDoc token = peekToken();
190     if (token == Lexer.rparenToken)
191       {
192     skipToken();
193     return emptyArgs;
194       }
195     Vector JavaDoc args = new Vector JavaDoc(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; // FIXME
216
return new ApplyExp(exp, args);
217   }
218
219   public Expression makeCallExpression(Expression exp, Expression[] args)
220   {
221     return new ApplyExp(exp, args); // FIXME
222
}
223
224   public String JavaDoc getIdentifier()
225     throws java.io.IOException JavaDoc, SyntaxException
226   {
227     Object JavaDoc token = getToken();
228     if (token instanceof String JavaDoc)
229       return (String JavaDoc) token;
230     syntaxError("missing identifier");
231     return "??";
232   }
233
234   public Expression parseLeftHandSideExpression ()
235     throws java.io.IOException JavaDoc, 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 JavaDoc token = peekToken();
247     if (token == Lexer.dotToken)
248       {
249         skipToken();
250         String JavaDoc 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 JavaDoc, SyntaxException
286   {
287     Expression exp = parseLeftHandSideExpression();
288     Object JavaDoc 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 JavaDoc, SyntaxException
299   {
300     //Object op = peekTokenOrLine();
301
// FIXME
302
return parsePostfixExpression();
303   }
304
305   public int errors;
306
307   public Expression syntaxError(String JavaDoc message)
308   {
309     // same as Translator.syntaxError. FIXME
310
errors++;
311     OutPort err = OutPort.errDefault();
312     String JavaDoc 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 JavaDoc, 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 JavaDoc, SyntaxException
355   {
356     skipToken();
357     Object JavaDoc 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 JavaDoc("not implemented - buildLoop");
388   }
389
390   public Expression parseWhileStatement()
391     throws java.io.IOException JavaDoc, SyntaxException
392   {
393     skipToken(); // Skip 'while'.
394
Object JavaDoc 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 JavaDoc, SyntaxException
407  {
408     skipToken();
409     String JavaDoc name = getIdentifier();
410     Object JavaDoc token = getToken();
411     if (token != Lexer.lparenToken)
412       return syntaxError("expected '(' - got:"+token);
413     Vector JavaDoc args = new Vector JavaDoc(10);
414     if (peekToken() == Lexer.rparenToken)
415       {
416     skipToken();
417       }
418     else
419       {
420     for (;;)
421       {
422         String JavaDoc 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 JavaDoc, 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       { // need to resize
463
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 JavaDoc, SyntaxException
476   {
477     Object JavaDoc 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 JavaDoc[] args)
503   {
504     Language language = new kawa.standard.Scheme(); // FIXME
505

506     InPort inp = InPort.inDefault ();
507     if (inp instanceof TtyInPort)
508       {
509     Object JavaDoc 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         /*
520         Object token = parser.peekToken();
521         if (token == Lexer.eofToken)
522           break;
523         if (token == Lexer.eolToken)
524           {
525         parser.getToken();
526         continue;
527           }
528         Expression expr = parser.parseExpression();
529         */

530         Expression expr = parser.parseStatement();
531         if (expr == eofExpr)
532           break;
533         out.print("[Expression: ");
534         expr.print(out);
535         out.println("]");
536         Object JavaDoc result = expr.eval(Environment.user());
537         out.print("result: ");
538         out.print(result);
539         out.println();
540       }
541     catch (Throwable JavaDoc ex)
542       {
543         System.err.println("caught exception:"+ex);
544         ex.printStackTrace(System.err);
545         return;
546       }
547       }
548   }
549 }
550
Popular Tags