KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > exprcomp


1 // Primitive runtime code generation of expressions. This is a jas
2
// implementation of the example in Aho Sethi Ullman.
3
//
4
// You pass to it statements of the form
5
// a = 1*2 + 3*5;
6
// Only integer operations are allowed, and variables
7
// are magically created by using them in the LHS of a statement.
8
//
9
// You can print out the value of expressions with the println keyword:
10
// println(a + 10);
11
//
12
// It compiles this into a bytearray, and then loads it as
13
// a new class.
14
//
15
// Unfortunately, this trick cannot be used in an applet --- security
16
// restrictions prevent ClassLoaders from being placed on the
17
// stack. So much for writing regexp compilers that can do codegen instead of
18
// state tables.
19
//
20
// The grammar is simple, so code generation is part of the parsing
21
// step. Operator precedence is directly handled by the grammar.
22
//
23
// Grammar + production rules:
24
//
25
// start -> list EOF
26
// list -> id = expr ; { emit(istore, id.index); } list
27
// | println expr ; { emit(<println sequence>); } list
28
// | lambda
29
// expr -> term moreterms
30
// moreterms -> + term { emit(iadd) } moreterms
31
// | - term { emit(isub) } moreterms
32
// | lambda
33
// term -> factor morefactors
34
// morefactors -> * factor { emit(imul) } morefactors
35
// | / factor { emit(idiv) } morefactors
36
// | lambda
37
// factor -> ( expr )
38
// | number { emit(iconst, number.value) }
39
// | id { emit(iload, id.index); }
40

41 import java.util.*;
42 import java.io.*;
43 import jas.*;
44
45 public class exprcomp implements RuntimeConstants
46 {
47   StreamTokenizer inp;
48   CodeAttr myCode;
49   short cur_stack_height;
50   short max_stack_height;
51   short max_vars;
52   Hashtable vars;
53
54   public exprcomp(StreamTokenizer inp)
55     throws jasError
56   {
57     inp.eolIsSignificant(false);
58     this.inp = inp;
59     myCode = new CodeAttr();
60                                 // Add initializations
61
myCode.addInsn(new Insn(opc_aload_0));
62     myCode.addInsn(new Insn(opc_invokenonvirtual,
63                             new MethodCP("java/lang/Object",
64                                          "<init>", "()V")));
65     cur_stack_height = max_stack_height = 1;
66     vars = new Hashtable();
67     max_vars = 1;
68   }
69   public void write(DataOutputStream out)
70     throws IOException, jasError
71   {
72     ClassEnv clazz = new ClassEnv();
73     myCode.setStackSize(max_stack_height);
74     myCode.setVarSize(max_vars);
75                                 // add initializer to class
76
clazz.addMethod
77       ((short) ACC_PUBLIC, "<init>", "()V", myCode, null);
78     clazz.setClassAccess((short) ACC_PUBLIC);
79     clazz.setClass(new ClassCP("results"));
80     clazz.setSuperClass(new ClassCP("java/lang/Object"));
81     clazz.write(out);
82   }
83
84   public void parse()
85     throws IOException, parseError, jasError
86   {
87     inp.nextToken();
88     while(inp.ttype != inp.TT_EOF)
89       {
90         if (inp.ttype != inp.TT_WORD)
91           {
92             throw new parseError("Expected an id at line " + inp.lineno());
93           }
94         if (inp.sval.equals("println"))
95           {
96             match(inp.TT_WORD);
97             expr();
98             match(';');
99             emit(new Insn(opc_getstatic,
100                           new FieldCP("java/lang/System",
101                                       "out", "Ljava/io/PrintStream;")));
102             emit(new Insn(opc_swap));
103             emit(new Insn(opc_invokevirtual,
104                           new MethodCP("java/io/PrintStream",
105                                        "println", "(I)V")));
106           }
107         else
108           { // search, maybe add into var list
109
Integer JavaDoc idx;
110             if ((idx = (Integer JavaDoc) vars.get(inp.sval)) == null)
111               {
112                 idx = new Integer JavaDoc(max_vars++);
113                 vars.put(inp.sval.intern(), idx);
114               }
115             match(inp.TT_WORD); match('='); expr(); match(';');
116             emit(new Insn(opc_istore, idx.intValue()));
117           }
118       }
119     emit(new Insn(opc_return));
120   }
121
122   void expr()
123     throws IOException, parseError, jasError
124   {
125     term();
126     while (true)
127       {
128         switch(inp.ttype)
129           {
130           case '+':
131             match('+'); term(); emit(new Insn(opc_iadd)); break;
132           case '-':
133             match('-'); term(); emit(new Insn(opc_isub)); break;
134           default: return;
135           }
136         cur_stack_height--;
137       }
138   }
139
140   void term()
141     throws IOException, parseError, jasError
142   {
143     factor();
144     while (true)
145       {
146         switch(inp.ttype)
147           {
148           case '*': match('*'); factor(); emit(new Insn(opc_imul)); break;
149           case '/': match('/'); factor(); emit(new Insn(opc_idiv)); break;
150           default: return;
151           }
152         cur_stack_height --;
153       }
154   }
155   void factor()
156     throws IOException, parseError, jasError
157   {
158     switch(inp.ttype)
159       {
160       case '(': match('('); expr(); match(')'); break;
161       case inp.TT_NUMBER:
162         int val = (int)(inp.nval);
163         emit(new Insn(opc_bipush, (short)val));
164         match(inp.TT_NUMBER);
165         break;
166       case inp.TT_WORD:
167         Integer JavaDoc idx;
168         if ((idx = (Integer JavaDoc) vars.get(inp.sval)) == null)
169           {
170             throw new parseError
171               ("Unknown variable " + inp.sval + " at line " + inp.lineno());
172           }
173         emit(new Insn(opc_iload, idx.intValue()));
174         match(inp.TT_WORD);
175         break;
176       default:
177         throw new parseError("Syntax error at line " + inp.lineno());
178       }
179     cur_stack_height++;
180     if (max_stack_height < cur_stack_height)
181       max_stack_height = cur_stack_height;
182   }
183   void match(int val)
184     throws IOException, parseError
185   {
186     if (inp.ttype != val)
187       { throw new parseError
188           ("line " + inp.lineno() + ": expected " + val + " but got " + inp); }
189     inp.nextToken();
190   }
191
192   void emit(Insn insn)
193   {
194     myCode.addInsn(insn);
195   }
196
197   public static void main(String JavaDoc argv[])
198     throws Exception JavaDoc
199   {
200     exprcomp compiler =
201       new exprcomp(new StreamTokenizer(new FileInputStream(argv[0])));
202     compiler.parse();
203     ByteArrayOutputStream data = new ByteArrayOutputStream();
204     compiler.write(new DataOutputStream(data));
205     dynaloader dl = new dynaloader(data.toByteArray());
206     dl.exec();
207   }
208 }
209
210 class dynaloader extends ClassLoader JavaDoc
211 {
212   Hashtable cache;
213   Class JavaDoc ex;
214
215   dynaloader(byte[] data)
216     throws ClassFormatError JavaDoc
217   {
218     cache = new Hashtable();
219     ex = defineClass(data, 0, data.length);
220     cache.put("results", ex);
221     resolveClass(ex);
222   }
223
224   void exec() throws Exception JavaDoc { ex.newInstance(); }
225   public synchronized Class JavaDoc loadClass(String JavaDoc name, boolean resolve)
226     throws ClassNotFoundException JavaDoc
227   {
228     Class JavaDoc c = (Class JavaDoc) cache.get(name);
229     if (c == null)
230       {
231         c = findSystemClass(name);
232         cache.put(name, c);
233       }
234     if (resolve) resolveClass(c);
235     return c;
236   }
237 }
238
239
240 class parseError extends Exception JavaDoc
241 { parseError(String JavaDoc s) { super(s); } }
242
Popular Tags