001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2007 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.parser;
020:
021: import java.util.ArrayList;
022: import java.util.HashSet;
023: import java.util.IdentityHashMap;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.Set;
028:
029: import xtc.Constants;
030:
031: import xtc.tree.Node;
032: import xtc.tree.Visitor;
033:
034: import xtc.type.AST;
035: import xtc.type.ErrorT;
036: import xtc.type.TupleT;
037: import xtc.type.Type;
038: import xtc.type.VariantT;
039: import xtc.type.Wildcard;
040:
041: import xtc.util.Runtime;
042:
043: /**
044: * Visitor to infer a grammar's variants.
045: *
046: * <p />This visitor assumes that the entire grammar is contained in a
047: * single module. It also assumes that the grammar's real root has
048: * been annotated and that directly left-recursive productions have
049: * <em>not</em> been transformed into equivalent right-iterations.
050: *
051: * @author Robert Grimm
052: * @version $Revision: 1.31 $
053: */
054: public class VariantSorter extends Visitor {
055:
056: /** The debugging level. */
057: private static final int DEBUG = 0;
058:
059: // =========================================================================
060:
061: /**
062: * Visitor to register all generic node names with the type
063: * operations class.
064: */
065: public class Registrar extends Visitor {
066:
067: /** The list of elements. */
068: protected List<Element> elements;
069:
070: /** Create a new registrar. */
071: public Registrar() {
072: elements = new ArrayList<Element>();
073: }
074:
075: /** Visit the specified grammar. */
076: public void visit(Module m) {
077: // Initialize the per-grammar state.
078: analyzer.register(this );
079: analyzer.init(m);
080:
081: elements.clear();
082:
083: // Iterate over generic productions.
084: for (Production p : m.productions) {
085: if (AST.isGenericNode(p.type))
086: analyzer.process(p);
087: }
088: }
089:
090: /** Visit the specified full production. */
091: public void visit(FullProduction p) {
092: dispatch(p.choice);
093: }
094:
095: /** Visit the specified ordered choice. */
096: public void visit(OrderedChoice c) {
097: for (Sequence alt : c.alternatives)
098: dispatch(alt);
099: }
100:
101: /** Visit the specified sequence. */
102: public void visit(Sequence s) {
103: // Remember the current number of elements.
104: final int base = elements.size();
105:
106: // Add this sequence's elements to the list of elements.
107: for (Iterator<Element> iter = s.elements.iterator(); iter
108: .hasNext();) {
109: final Element e = iter.next();
110:
111: if ((!iter.hasNext()) && (e instanceof OrderedChoice)) {
112: dispatch(e);
113: } else {
114: elements.add(e);
115: }
116: }
117:
118: // Actually process the elements.
119: if (!s.hasTrailingChoice()) {
120: NodeMarker mark = null;
121:
122: for (Element e : elements) {
123: if (e instanceof NodeMarker)
124: mark = (NodeMarker) e;
125: }
126:
127: final String name = (null == mark) ? analyzer.current().name.name
128: : mark.name;
129: ast.toTuple(name); // Called for side-effect, i.e., tuple creation.
130: }
131:
132: // Remove any elements added by this method invocation.
133: if (0 == base) {
134: elements.clear();
135: } else {
136: elements.subList(base, elements.size()).clear();
137: }
138: }
139:
140: }
141:
142: // =========================================================================
143:
144: /** Visitor to determine a generic production's variant type. */
145: public class Typer extends Visitor {
146:
147: /** The current production. */
148: protected FullProduction production;
149:
150: /** The list of elements. */
151: protected List<Element> elements;
152:
153: /** The list of node names. */
154: protected List<String> names;
155:
156: /** The type. */
157: protected Type type;
158:
159: /** Create a new typer. */
160: public Typer() {
161: elements = new ArrayList<Element>();
162: names = new ArrayList<String>();
163: }
164:
165: /** Visit the specified full production. */
166: public Type visit(FullProduction p) {
167: // Reset the traversal state.
168: production = p;
169: elements.clear();
170: names.clear();
171:
172: // Process the choice.
173: dispatch(p.choice);
174:
175: // Determine the type.
176:
177: // (1) If the production does not create any generic nodes, we
178: // signal an error.
179: if (0 == names.size())
180: return ErrorT.TYPE;
181:
182: // (2) If the production creates generic nodes that already have
183: // tuples belonging to the same variant, we return that variant.
184: VariantT variant = null;
185: boolean isValid = false;
186:
187: for (String name : names) {
188: if (ast.hasTuple(name)) {
189: final List<VariantT> variants = ast.toVariants(ast
190: .toTuple(name));
191:
192: if (1 == variants.size()) {
193: if (null == variant) {
194: variant = variants.get(0);
195: isValid = true;
196: continue;
197: } else if (variant == variants.get(0)) {
198: continue;
199: }
200: }
201: }
202:
203: isValid = false;
204: break;
205: }
206:
207: if (isValid)
208: return variant;
209:
210: // (3) If the production creates a generic node with the same
211: // name as another generic production and that production
212: // already has a variant type, we return the variant.
213: if (1 == names.size()) {
214: final String name = names.get(0);
215: final FullProduction p2 = analyzer
216: .lookup(new NonTerminal(name));
217:
218: if (null != p2 && AST.isGenericNode(p2.type)
219: && AST.isStaticNode(p2.type)) {
220: return p2.type;
221: }
222: }
223:
224: // (4) Return a new variant named after this production.
225: return ast.toVariant(p.qName.name, false);
226: }
227:
228: /** Visit the specified ordered choice. */
229: public void visit(OrderedChoice c) {
230: for (Sequence alt : c.alternatives)
231: dispatch(alt);
232: }
233:
234: /** Visit the specified sequence. */
235: public void visit(Sequence s) {
236: // Remember the current number of elements.
237: final int base = elements.size();
238:
239: // Add this sequence's elements to the list of elements.
240: for (Iterator<Element> iter = s.elements.iterator(); iter
241: .hasNext();) {
242: final Element e = iter.next();
243:
244: if (!iter.hasNext() && (e instanceof OrderedChoice)) {
245: dispatch(e);
246: } else {
247: elements.add(e);
248: }
249: }
250:
251: // Actually process the elements.
252: if (!s.hasTrailingChoice()) {
253: boolean pass = false;
254: NodeMarker mark = null;
255:
256: loop: for (Element e : elements) {
257: switch (e.tag()) {
258: case BINDING: {
259: Binding b = (Binding) e;
260: if (CodeGenerator.VALUE.equals(b.name))
261: pass = true;
262: }
263: break loop;
264:
265: case NODE_MARKER:
266: mark = (NodeMarker) e;
267: break;
268: }
269: }
270:
271: if (!pass) {
272: final String name = (null == mark) ? production.name.name
273: : mark.name;
274: if (!names.contains(name))
275: names.add(name);
276: }
277: }
278:
279: // Remove any elements added by this method invocation.
280: if (0 == base) {
281: elements.clear();
282: } else {
283: elements.subList(base, elements.size()).clear();
284: }
285: }
286:
287: }
288:
289: // =========================================================================
290:
291: /** The runtime. */
292: protected final Runtime runtime;
293:
294: /** The analyzer. */
295: protected final Analyzer analyzer;
296:
297: /** The type operations. */
298: protected final AST ast;
299:
300: /** The set of AST nodes resulting in an error. */
301: protected Map<Node, Node> malformed;
302:
303: /** The flag for whether the current mode is push or pull. */
304: protected boolean isPushMode;
305:
306: /** The productions to be processed in push mode. */
307: protected List<Production> productions;
308:
309: /** The flag for whether productions have changed in push mode. */
310: protected boolean hasChanged;
311:
312: /**
313: * The current types. In push mode, the list contains exactly one
314: * variant type, which is being pushed through productions. In pull
315: * mode, the list contains the types of all alternatives, which may
316: * be variant types, type parameters, and error types and which are
317: * unified in {@link #visit(FullProduction)}.
318: */
319: protected List<Type> types;
320:
321: /** The current production. */
322: protected FullProduction production;
323:
324: /**
325: * The flag for whether the current production is generic. We need
326: * to track this information in an explicit flag, because this
327: * visitor processes choices and sequences that will be lifted into
328: * their own productions.
329: */
330: protected boolean isGeneric;
331:
332: /** The list of elements representing the current alternative. */
333: protected List<Element> elements;
334:
335: /**
336: * Create a new variant sorter.
337: *
338: * @param runtime The runtime.
339: * @param analyzer The analyzer utility.
340: * @param ast The type operations.
341: */
342: public VariantSorter(Runtime runtime, Analyzer analyzer, AST ast) {
343: this .runtime = runtime;
344: this .analyzer = analyzer;
345: this .ast = ast;
346: malformed = new IdentityHashMap<Node, Node>();
347: productions = new ArrayList<Production>();
348: types = new ArrayList<Type>();
349: elements = new ArrayList<Element>();
350: }
351:
352: /**
353: * Merge the two variants. This method merges the second variant
354: * into the first variant, which must be polymorphic. If the second
355: * variant also is polymorphic, it simply adds the second variant's
356: * tuples to the first variant. Otherwise, it tries to create a new
357: * tuple with the second variant's original name and then adds that
358: * tuple to the first variant.
359: *
360: * @param v1 The first variant.
361: * @param v2 The second variant.
362: * @param p The production for error reporting.
363: * @return The first variant or the error type in case of errors.
364: */
365: protected Type merge(VariantT v1, VariantT v2, Production p) {
366: assert v1.isPolymorphic();
367:
368: if (ast.unify(v1, v2, true).isError()) {
369: runtime.error(
370: "production's alternatives have distinct variants",
371: p);
372: runtime.errConsole().loc(p).pln(
373: ": error: but include same generic node");
374: runtime.errConsole().loc(p).p(": error: 1st type is '");
375: ast.print(v1, runtime.errConsole(), false, true, null);
376: runtime.errConsole().pln("'");
377: runtime.errConsole().loc(p).p(": error: 2nd type is '");
378: ast.print(v2, runtime.errConsole(), false, true, null);
379: runtime.errConsole().pln("'").flush();
380:
381: return ErrorT.TYPE;
382: }
383:
384: Type result = v1;
385: if (v2.isPolymorphic()) {
386: for (TupleT tuple : v2.getTuples())
387: ast.add(tuple, v1);
388: } else {
389: ast.add(ast.toTuple(v2), v1);
390: }
391:
392: return result;
393: }
394:
395: /**
396: * Set the specified production's type to the specified type. This
397: * method preserves the original type's generic attribute, unless
398: * the specified type is the error type.
399: *
400: * @param p The production.
401: * @param t The type.
402: */
403: protected void setType(Production p, Type t) {
404: if (t.isError()) {
405: p.type = t;
406: } else if (AST.isGenericNode(p.type)) {
407: p.type = t.annotate().attribute(Constants.ATT_GENERIC);
408: } else {
409: p.type = t;
410: }
411:
412: if (2 <= DEBUG) {
413: runtime.console().p(p.qName.name).p(" : ");
414: ast.print(p.type, runtime.console(), false, true, null);
415: runtime.console().pln().flush();
416: }
417: }
418:
419: /**
420: * Push and pull any variant types.
421: *
422: * @param m The grammar.
423: */
424: protected void pushPull(Module m) {
425: boolean first = true;
426:
427: do {
428: // Push.
429: isPushMode = true;
430: hasChanged = first;
431: if (first)
432: first = false;
433: while (!productions.isEmpty()) {
434: Production p = productions.remove(0);
435: types.clear();
436: types.add(p.type.resolve());
437: analyzer.process(p);
438: }
439:
440: // Pull.
441: if (hasChanged) {
442: isPushMode = false;
443: hasChanged = false;
444: for (Production p : m.productions) {
445: if (AST.isDynamicNode(p.type)) {
446: analyzer.process(p);
447: }
448: }
449: }
450: } while (!productions.isEmpty());
451: }
452:
453: /** Visit the specified grammar. */
454: public void visit(Module m) {
455: // Register the names for generic nodes first.
456: new Registrar().dispatch(m);
457:
458: // Initialize the per-grammar state.
459: analyzer.register(this );
460: analyzer.init(m);
461:
462: malformed.clear();
463: productions.clear();
464: elements.clear();
465:
466: // Start with the grammar's root.
467: if (!m.hasProperty(Properties.ROOT)) {
468: runtime.error("grammar without distinct root", m);
469: return;
470: } else {
471: Production p = analyzer.lookup((NonTerminal) m
472: .getProperty(Properties.ROOT));
473:
474: if (!AST.isNode(p.type)) {
475: runtime
476: .error(
477: "grammar's root production does not return a node",
478: p);
479: return;
480: }
481:
482: p.attributes.remove(Constants.ATT_VARIANT);
483: setType(p, ast.toVariant(p.qName.name, false));
484: productions.add(p);
485: }
486:
487: // Then process all productions explicitly marked as variant.
488: for (Production p : m.productions) {
489: if (p.hasAttribute(Constants.ATT_VARIANT)) {
490: setType(p, ast.toVariant(p.qName.name, false));
491: productions.add(p);
492: }
493: }
494:
495: // Push/pull the grammar's variants.
496: pushPull(m);
497:
498: // Process any remaining generic productions.
499: final Typer typer = new Typer();
500:
501: for (Production p : m.productions) {
502: if (AST.isDynamicNode(p.type) && AST.isGenericNode(p.type)) {
503: Type t = (Type) typer.dispatch(p);
504:
505: if (!t.isError()) {
506: setType(p, t);
507: productions.add(p);
508: }
509: }
510: }
511: pushPull(m);
512:
513: // Process any remaining non-generic productions.
514: for (Production p : m.productions) {
515: if (AST.isDynamicNode(p.type)) {
516: analyzer.notWorkingOnAny();
517: if (!analyzer.consumesInput(p.qName)) {
518: p.type = AST.NULL_NODE;
519: } else {
520: runtime.error("unable to determine static type", p);
521: }
522: }
523: }
524:
525: // Print the results of the variant inference in debugging mode.
526: if (1 <= DEBUG) {
527: if (2 <= DEBUG)
528: runtime.console().pln();
529:
530: // Print all variant types.
531: Set<String> printed = new HashSet<String>();
532:
533: for (Production p : m.productions) {
534: if (AST.isStaticNode(p.type)) {
535: VariantT variant = p.type.resolve().toVariant();
536:
537: if (!printed.contains(variant.getName())) {
538: printed.add(variant.getName());
539: ast.print(variant, runtime.console(), true,
540: true, null);
541: runtime.console().pln();
542: }
543: }
544: }
545:
546: // Print all productions that do not have a statically typed
547: // node.
548: for (Production p : m.productions) {
549: if (p.type.isError()) {
550: runtime.console().p(p.qName.name).pln(" : *error*");
551: } else if (AST.isDynamicNode(p.type)) {
552: runtime.console().p(p.qName.name).pln(
553: " : *undetermined*");
554: }
555: }
556: runtime.console().flush();
557: }
558: }
559:
560: /** Visit the specified production. */
561: public void visit(FullProduction p) {
562: if (2 <= DEBUG) {
563: if (isPushMode) {
564: runtime.console().p("push ");
565: } else {
566: runtime.console().p("pull ");
567: }
568: runtime.console().pln(p.qName.name).flush();
569: }
570:
571: // Set up the traversal state.
572: production = p;
573: isGeneric = AST.isGenericNode(p.type);
574:
575: // Update the production's type in push mode.
576: if (isPushMode) {
577: if (AST.isDynamicNode(p.type)) {
578: hasChanged = true; // We need another pull pass.
579: setType(p, types.get(0));
580: }
581: } else {
582: types.clear(); // We have not yet seen any alternatives.
583: }
584:
585: // Remember that we are working on the production.
586: analyzer.workingOn(p.qName);
587:
588: // Preprocess directly left-recursive generic productions.
589: if (isGeneric && DirectLeftRecurser.isTransformable(p)) {
590: for (Sequence s : p.choice.alternatives) {
591: if (!DirectLeftRecurser.isRecursive(s, p)) {
592: Binding b = analyzer.bind(s.elements);
593: if (null != b)
594: b.name = CodeGenerator.VALUE;
595: }
596: }
597: }
598:
599: // Actually process the production's choice.
600: dispatch(p.choice);
601:
602: // Update the production's type in pull mode by unifying the
603: // alternatives' types.
604: if (!isPushMode) {
605: Type result = Wildcard.TYPE;
606: boolean seenWild = false; // Flag for having seen a wildcard.
607: boolean seenPoly = false; // Flag for having seen a polymorphic variant.
608:
609: loop: for (Type t : types) {
610: switch (t.tag()) {
611: case ERROR:
612: result = ErrorT.TYPE;
613: break loop;
614:
615: case WILDCARD:
616: seenWild = true;
617: if (seenPoly) {
618: runtime
619: .error(
620: "production requires polymorphic variant",
621: p);
622: runtime
623: .errConsole()
624: .loc(p)
625: .pln(
626: ": error: but has alternatives without static type")
627: .flush();
628: result = ErrorT.TYPE;
629: break loop;
630: }
631: break;
632:
633: case VARIANT:
634: if (seenPoly) {
635: result = merge(result.toVariant(), t
636: .toVariant(), p);
637: if (result.isError())
638: break loop;
639:
640: } else if (result.isWildcard()) {
641: result = t;
642:
643: } else if (!result.equals(t)) {
644: if (isGeneric) {
645: runtime.error("variant '"
646: + result.toVariant().getName()
647: + "' " + "overlaps with '"
648: + t.toVariant().getName() + "'", p);
649: result = ErrorT.TYPE;
650: break loop;
651:
652: } else if (seenWild) {
653: runtime
654: .error(
655: "production requires polymorphic variant",
656: p);
657: runtime
658: .errConsole()
659: .loc(p)
660: .pln(
661: ": error: but has alternatives without static type")
662: .flush();
663: result = ErrorT.TYPE;
664: break loop;
665:
666: } else {
667: VariantT v = result.toVariant();
668: result = merge(ast.toVariant(p.qName.name,
669: true), v, p);
670: if (result.isError())
671: break loop;
672: result = merge(result.toVariant(), t
673: .toVariant(), p);
674: if (result.isError())
675: break loop;
676: seenPoly = true;
677: }
678: }
679: break;
680:
681: default:
682: throw new AssertionError("Unrecognized type " + t);
683: }
684: }
685:
686: // If we have a meaningful result, update the production's type.
687: if (!result.isWildcard()) {
688: setType(p, result);
689:
690: final Type r = result.resolve();
691: if (r.isVariant() && !r.toVariant().isPolymorphic()) {
692: // Push the production's variant type.
693: productions.add(p);
694: }
695: }
696: }
697: }
698:
699: /** Visit the specified choice. */
700: public void visit(OrderedChoice c) {
701: // Process the alternatives.
702: for (Sequence alt : c.alternatives)
703: dispatch(alt);
704: }
705:
706: /** Visit the specified sequence. */
707: public void visit(Sequence s) {
708: // Remember the current number of elements.
709: final int base = elements.size();
710:
711: // Add this sequence's elements to the list of elements.
712: for (Iterator<Element> iter = s.elements.iterator(); iter
713: .hasNext();) {
714: final Element e = iter.next();
715:
716: if ((!iter.hasNext()) && (e instanceof OrderedChoice)) {
717: dispatch(e);
718: } else {
719: elements.add(e);
720: }
721: }
722:
723: // Actually process the elements.
724: if (!s.hasTrailingChoice()) {
725: if (isGeneric) {
726: // The production is generic. If the alternative passes the
727: // value through, determine the last such element. Otherwise,
728: // determine the last node marker (if any).
729: Element pass = null;
730: NodeMarker mark = null;
731:
732: for (Element e : elements) {
733: switch (e.tag()) {
734: case BINDING: {
735: Binding b = (Binding) e;
736: if (CodeGenerator.VALUE.equals(b.name))
737: pass = b.element;
738: }
739: break;
740:
741: case NODE_MARKER:
742: mark = (NodeMarker) e;
743: break;
744: }
745: }
746:
747: if (null != pass) {
748: // Recurse on the passed through element.
749: recurse(pass);
750:
751: } else if (isPushMode) {
752: // Process the constructor name.
753: final String name = (null == mark) ? production.name.name
754: : mark.name;
755: final boolean hasTuple = ast.hasTuple(name);
756: final TupleT tuple = ast.toTuple(name);
757: final List<VariantT> variants = ast
758: .toVariants(tuple);
759:
760: if (!hasTuple || 0 == variants.size()) {
761: ast.add(tuple, types.get(0).toVariant());
762: } else if (!variants.contains(types.get(0))) {
763: runtime.error("tuple '" + name
764: + "' should appear in variant '"
765: + types.get(0).toVariant().getName()
766: + "'", production);
767: runtime.errConsole().loc(production).p(
768: ": error: but already ").p(
769: "appears in variant '").p(
770: variants.get(0).getName()).pln("'")
771: .flush();
772: variants.add(types.get(0).toVariant());
773: }
774: }
775:
776: } else {
777: // The production passes the value through.
778: Element value = analyzer.getValue(elements, true);
779:
780: if (null != value) {
781: recurse(value);
782: }
783: }
784: }
785:
786: // Remove any elements added by this method invocation.
787: if (0 == base) {
788: elements.clear();
789: } else {
790: elements.subList(base, elements.size()).clear();
791: }
792: }
793:
794: /**
795: * Recurse on the specified element. If the element is an
796: * optionally bound nonterminal, this method processes the
797: * corresponding production. If the element is an optionally bound
798: * sequence or choice, this method processes the sequence or choice.
799: * Otherwise, it reports an error condition and returns.
800: *
801: * @param e The element.
802: */
803: protected void recurse(Element e) {
804: // Strip any bindings and options.
805: e = Analyzer.strip(e);
806:
807: while (true) {
808: final Element start = e;
809: if (e instanceof Binding)
810: e = Analyzer.strip(((Binding) e).element);
811: if (e instanceof Option)
812: e = Analyzer.strip(((Option) e).element);
813: if (start == e)
814: break;
815: }
816:
817: // Save the traversal state.
818: List<Type> savedTypes = types;
819: FullProduction savedProduction = production;
820: boolean savedIsGeneric = isGeneric;
821: List<Element> savedElements = elements;
822:
823: // Determine the AST node to recurse on.
824: switch (e.tag()) {
825: case NONTERMINAL: {
826: // Get the production.
827: FullProduction p = analyzer.lookup((NonTerminal) e);
828:
829: // Avoid infinite recursions.
830: if (analyzer.isBeingWorkedOn(p.qName)) {
831: if (!isPushMode)
832: types.add(Wildcard.TYPE);
833: return;
834: }
835:
836: // Check for previous errors and existing variants.
837: if (p.type.isError()) {
838: if (!isPushMode)
839: types.add(ErrorT.TYPE);
840: return;
841:
842: } else if (AST.isStaticNode(p.type)) {
843: if (isPushMode) {
844: // Make sure the variants are consistent.
845: if (!types.get(0).equals(p.type.resolve())) {
846: if (!malformed.containsKey(p)) {
847: runtime.error("variant '"
848: + types.get(0).toVariant()
849: .getName()
850: + "' overlaps with '"
851: + p.type.resolve().toVariant()
852: .getName() + "'", p);
853: malformed.put(p, p);
854: }
855: return;
856: }
857: }
858: if (!isPushMode)
859: types.add(p.type.resolve());
860: return;
861: }
862:
863: // The production must not be void. Neither should it have a
864: // string or token value.
865: assert !AST.isVoid(p.type);
866:
867: if (AST.isString(p.type)) {
868: if (!malformed.containsKey(p)) {
869: runtime
870: .error(
871: "variant type for production with string value",
872: p);
873: malformed.put(p, p);
874: }
875: if (!isPushMode)
876: types.add(ErrorT.TYPE);
877: return;
878:
879: } else if (AST.isToken(p.type)) {
880: if (!malformed.containsKey(p)) {
881: runtime
882: .error(
883: "variant type for production with token value",
884: p);
885: malformed.put(p, p);
886: }
887: if (!isPushMode)
888: types.add(ErrorT.TYPE);
889: return;
890: }
891:
892: // Actually recurse.
893: if (!isPushMode)
894: types = new ArrayList<Type>();
895: elements = new ArrayList<Element>();
896: dispatch(p);
897: if ((!isPushMode) && (!AST.isDynamicNode(p.type))) {
898: // Remember the result.
899: savedTypes.add(p.type.resolve());
900: }
901: }
902: break;
903:
904: case SEQUENCE:
905: case CHOICE:
906: // Since the element will be lifted, its production cannot be
907: // generic.
908: isGeneric = false;
909: elements = new ArrayList<Element>();
910: dispatch(e);
911: break;
912:
913: case NULL:
914: // A null literal can assume any type.
915: if (!isPushMode)
916: types.add(Wildcard.TYPE);
917: return;
918:
919: default:
920: if (!malformed.containsKey(e)) {
921: runtime.error("variant type for invalid element", e);
922: malformed.put(e, e);
923: }
924: if (!isPushMode)
925: types.add(ErrorT.TYPE);
926: return;
927: }
928:
929: // Restore the traversal state.
930: types = savedTypes;
931: production = savedProduction;
932: isGeneric = savedIsGeneric;
933: elements = savedElements;
934: }
935:
936: }
|