KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > kawa > lang > SyntaxRules


1 package kawa.lang;
2 import gnu.mapping.*;
3 import gnu.expr.*;
4 import gnu.lists.*;
5 import java.io.*;
6 import gnu.text.*;
7
8 public class SyntaxRules extends Procedure1 implements Printable, Externalizable
9 {
10   /** The list of literal identifiers.
11    * The 0'th element is name of the macro being defined;
12    * the rest are as specied in the syntax-rules form. */

13   Object JavaDoc[] literal_identifiers;
14
15   SyntaxRule[] rules;
16
17   /* The largest (num_variables+template_identifier.length) for any rule. */
18   int maxVars = 0;
19
20   public SyntaxRules ()
21   {
22   }
23
24   /** The compiler generates calls to this constructor. */
25   public SyntaxRules (Object JavaDoc[] literal_identifiers, SyntaxRule[] rules,
26               int maxVars)
27   {
28     this.literal_identifiers = literal_identifiers;
29     this.rules = rules;
30     this.maxVars = maxVars;
31   }
32
33   public SyntaxRules (Object JavaDoc[] literal_identifiers, Object JavaDoc srules,
34               Translator tr)
35   {
36     this.literal_identifiers = literal_identifiers;
37     int rules_count = Translator.listLength(srules);
38     if (rules_count < 0)
39       {
40     rules_count = 0;
41     tr.syntaxError ("missing or invalid syntax-rules");
42       }
43     this.rules = new SyntaxRule [rules_count];
44     Pair rules_pair;
45     // SyntaxForm, if any, wrapping rest of rules list.
46
SyntaxForm rules_syntax = null;
47     for (int i = 0; i < rules_count; i++, srules = rules_pair.cdr)
48       {
49     while (srules instanceof SyntaxForm)
50       {
51         rules_syntax = (SyntaxForm) srules;
52         srules = rules_syntax.form;
53       }
54     rules_pair = (Pair) srules;
55
56     // SyntaxForm, if any, wrapping the current rule.
57
SyntaxForm rule_syntax = rules_syntax;
58     Object JavaDoc syntax_rule = rules_pair.car;
59     while (syntax_rule instanceof SyntaxForm)
60       {
61         rule_syntax = (SyntaxForm) syntax_rule;
62         syntax_rule = rule_syntax.form;
63       }
64     if (! (syntax_rule instanceof Pair))
65       {
66         tr.syntaxError ("missing pattern in " + i + "'th syntax rule");
67         return;
68       }
69     // SyntaxForm, if any, wrapping the current rule's pattern.
70
SyntaxForm pattern_syntax = rule_syntax;
71     Pair syntax_rule_pair = (Pair) syntax_rule;
72     Object JavaDoc pattern = syntax_rule_pair.car;
73
74     String JavaDoc save_filename = tr.getFileName();
75     int save_line = tr.getLineNumber();
76     int save_column = tr.getColumnNumber();
77
78     try
79       {
80         // SyntaxForm, if any, wrapping the current rule's template.
81
SyntaxForm template_syntax = rule_syntax;
82         tr.setLine(syntax_rule_pair);
83         syntax_rule = syntax_rule_pair.cdr;
84         while (syntax_rule instanceof SyntaxForm)
85           {
86         template_syntax = (SyntaxForm) syntax_rule;
87         syntax_rule = template_syntax.form;
88           }
89         if (! (syntax_rule instanceof Pair))
90           {
91         tr.syntaxError ("missing template in " + i + "'th syntax rule");
92         return;
93           }
94         syntax_rule_pair = (Pair) syntax_rule;
95         if (syntax_rule_pair.cdr != LList.Empty)
96           {
97         tr.syntaxError ("junk after "+i+"'th syntax rule");
98         return;
99           }
100         Object JavaDoc template = syntax_rule_pair.car;
101
102         PatternScope patternScope = PatternScope.push(tr);
103         tr.push(patternScope);
104
105         while (pattern instanceof SyntaxForm)
106           {
107         pattern_syntax = (SyntaxForm) pattern;
108         pattern = pattern_syntax.form;
109           }
110
111         StringBuffer JavaDoc programbuf = new StringBuffer JavaDoc();
112
113         // In R5RS syntax-rules, the initial name is neither a
114
// pattern variable or a literal identifier, so ingore it.
115
if (pattern instanceof Pair)
116           {
117         // ?? FIXME
118
literal_identifiers[0] = ((Pair)pattern).car;
119
120         Pair p = (Pair) pattern;
121         programbuf.append((char) ((1 << 3) | SyntaxPattern.MATCH_PAIR));
122         programbuf.append((char) SyntaxPattern.MATCH_IGNORE);
123         pattern = p.cdr;
124           }
125         else
126           {
127         // Identifier macro? FIXME
128
tr.syntaxError ("pattern does not start with name");
129         return;
130           }
131         SyntaxPattern spattern = new SyntaxPattern(programbuf, pattern,
132                          pattern_syntax, literal_identifiers, tr);
133
134         this.rules[i] = new SyntaxRule(spattern,
135                        template, template_syntax, tr);
136
137         PatternScope.pop(tr);
138         tr.pop();
139       }
140     finally
141       {
142         tr.setLine(save_filename, save_line, save_column);
143       }
144       }
145
146     // Calculate maxVars:
147
for (int i = this.rules.length; --i >= 0; )
148       {
149     int size = this.rules[i].patternNesting.length();
150     if (size > maxVars)
151       maxVars = size;
152       }
153   }
154
155   /* --- Recursively translate a pattern in a syntax-rule to a Pattern object.
156    * @param pattern the the pattern to translate
157    * @param literal_identifiers the literals of the syntax-rule
158    * @param nesting the depth of ... we are inside
159    * @param tr the current Translator
160    * @return the translated Pattern
161    */

162
163   public Object JavaDoc apply1 (Object JavaDoc arg)
164   {
165     if (arg instanceof SyntaxForm)
166       {
167     SyntaxForm sf = (SyntaxForm) arg;
168     Translator tr = (Translator) Compilation.getCurrent();
169     ScopeExp save_scope = tr.currentScope();
170     tr.setCurrentScope(sf.scope);
171     try
172       {
173         return expand(sf, tr);
174       }
175     finally
176       {
177         tr.setCurrentScope(save_scope);
178       }
179       }
180     else
181       return expand(arg, (Translator) Compilation.getCurrent());
182   }
183
184   /* DEBUGGING:
185   private void printElement (Object el, StringBuffer sb)
186   {
187     if (el instanceof Object[])
188       {
189     Object[] arr = (Object[]) el;
190     sb.append('{');
191     for (int i = 0; i < arr.length; i++)
192       {
193         if (i != 0)
194           sb.append(", ");
195         printElement(arr[i], sb);
196       }
197     sb.append('}');
198       }
199     else
200       sb.append(el);
201   }
202   END DEBUGGING */

203
204   public Object JavaDoc expand (Object JavaDoc obj, Translator tr)
205   {
206     Object JavaDoc[] vars = new Object JavaDoc[maxVars];
207     Macro macro = (Macro) tr.getCurrentSyntax();
208     /* DEBUGGING:
209     System.err.println("match "+macro+" args:"+obj+" maxVars:"+maxVars);
210     System.err.flush();
211     */

212     for (int i = 0; i < rules.length; i++)
213       {
214     SyntaxRule rule = rules[i];
215     if (rule==null)
216       return new ErrorExp("error defining "+macro);
217     // check that literals have correct binding - FIXME!!
218
Pattern pattern = rule.pattern;
219     boolean matched = pattern.match (obj, vars, 0);
220     if (matched)
221       {
222         if (true) // DEBUGGING
223
{
224         /*
225         OutPort err = OutPort.errDefault();
226         StringBuffer sb = new StringBuffer();
227         sb.append("{Expand "+macro + " rule#" + i
228               +" - matched variables: ");
229         for (int j = 0; j < rule.pattern.varCount; j++)
230           {
231             if (j > 0) sb.append("; ");
232             sb.append(j); sb.append(": ");
233             printElement(vars[j], sb);
234           }
235         sb.append('}');
236         err.println(sb);
237         err.flush();
238         */

239           }
240
241         if (true)
242           {
243         /* DEBUGGING:
244         OutPort err = OutPort.errDefault();
245         err.print("Expanding "); err.println(literal_identifiers[0]);
246         rule.print_template_program(null, err);
247         err.flush();
248         */

249           }
250         Object JavaDoc expansion = rule.execute(vars, tr, TemplateScope.make(tr));
251
252         if (false) // DEBUGGING:
253
{
254         OutPort err = OutPort.errDefault();
255         err.print("{Expansion of ");
256         err.print(macro);
257         err.println(":");
258         err.startLogicalBlock(" ", "}", 2);
259         kawa.standard.Scheme.writeFormat.writeObject(expansion, err);
260         err.endLogicalBlock("}");
261         err.println();
262         err.flush();
263           }
264         return expansion;
265       }
266       }
267     /* DEBUGGING:
268     System.err.println("no matching syntax-rule for "
269                + literal_identifiers[0]);
270     System.err.flush();
271     */

272     return tr.syntaxError ("no matching syntax-rule for "
273                + literal_identifiers[0]);
274   }
275
276   public void print (Consumer out)
277   {
278     out.write("#<macro ");
279     ReportFormat.print(literal_identifiers[0], out);
280     out.write('>');
281   }
282
283   /**
284    * @serialData Write literal_identifiers followed by rules,
285    * using writeObject.
286    */

287   public void writeExternal(ObjectOutput out) throws IOException
288   {
289     out.writeObject(literal_identifiers);
290     out.writeObject(rules);
291     out.writeInt(maxVars);
292   }
293
294   public void readExternal(ObjectInput in)
295     throws IOException, ClassNotFoundException JavaDoc
296   {
297     literal_identifiers = (Object JavaDoc[]) in.readObject();
298     rules = (SyntaxRule[]) in.readObject();
299     maxVars = in.readInt();
300   }
301 }
302
Popular Tags