diff --git a/org.metaborg.sdf2table/src/main/java/org/metaborg/sdf2table/io/NormGrammarReader.java b/org.metaborg.sdf2table/src/main/java/org/metaborg/sdf2table/io/NormGrammarReader.java index 50f0606f5..53ae97c56 100644 --- a/org.metaborg.sdf2table/src/main/java/org/metaborg/sdf2table/io/NormGrammarReader.java +++ b/org.metaborg.sdf2table/src/main/java/org/metaborg/sdf2table/io/NormGrammarReader.java @@ -3,50 +3,14 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.metaborg.parsetable.characterclasses.CharacterClassFactory; import org.metaborg.parsetable.characterclasses.ICharacterClass; import org.metaborg.sdf2table.exceptions.ModuleNotFoundException; import org.metaborg.sdf2table.exceptions.UnexpectedTermException; -import org.metaborg.sdf2table.grammar.AltSymbol; -import org.metaborg.sdf2table.grammar.CharacterClassSymbol; -import org.metaborg.sdf2table.grammar.ConstructorAttribute; -import org.metaborg.sdf2table.grammar.ContextFreeSymbol; -import org.metaborg.sdf2table.grammar.DeprecatedAttribute; -import org.metaborg.sdf2table.grammar.FileStartSymbol; -import org.metaborg.sdf2table.grammar.GeneralAttribute; -import org.metaborg.sdf2table.grammar.IAttribute; -import org.metaborg.sdf2table.grammar.ISymbol; -import org.metaborg.sdf2table.grammar.IterSepSymbol; -import org.metaborg.sdf2table.grammar.IterStarSepSymbol; -import org.metaborg.sdf2table.grammar.IterStarSymbol; -import org.metaborg.sdf2table.grammar.IterSymbol; -import org.metaborg.sdf2table.grammar.Layout; -import org.metaborg.sdf2table.grammar.LayoutConstraintAttribute; -import org.metaborg.sdf2table.grammar.LexicalSymbol; -import org.metaborg.sdf2table.grammar.LiteralType; -import org.metaborg.sdf2table.grammar.NormGrammar; -import org.metaborg.sdf2table.grammar.OptionalSymbol; -import org.metaborg.sdf2table.grammar.Priority; -import org.metaborg.sdf2table.grammar.Production; -import org.metaborg.sdf2table.grammar.ProductionReference; -import org.metaborg.sdf2table.grammar.SequenceSymbol; -import org.metaborg.sdf2table.grammar.Sort; -import org.metaborg.sdf2table.grammar.StartSymbol; -import org.metaborg.sdf2table.grammar.Symbol; -import org.metaborg.sdf2table.grammar.TermAttribute; -import org.metaborg.sdf2table.grammar.UniqueProduction; -import org.spoofax.interpreter.terms.IStrategoAppl; -import org.spoofax.interpreter.terms.IStrategoList; -import org.spoofax.interpreter.terms.IStrategoString; -import org.spoofax.interpreter.terms.IStrategoTerm; -import org.spoofax.interpreter.terms.ITermFactory; +import org.metaborg.sdf2table.grammar.*; +import org.spoofax.interpreter.terms.*; import org.spoofax.terms.StrategoAppl; import org.spoofax.terms.StrategoList; import org.spoofax.terms.StrategoString; @@ -115,7 +79,7 @@ private void normalizeIndexedPriorities() { for(Integer arg : grammar.priorities().get(p)) { if(arg != -1 && arg != Integer.MIN_VALUE && arg != Integer.MAX_VALUE) { grammar.getIndexedPriorities().put(p, arg); - } + } } } @@ -389,6 +353,7 @@ private Symbol processSymbol(IStrategoTerm term) { Symbol symbol = null; String enquoted; + term = removeLabelFromSymbolTerm(term); symbol = grammar.getCacheSymbolsRead().get(term.toString()); if(symbol != null) { @@ -453,9 +418,6 @@ private Symbol processSymbol(IStrategoTerm term) { case "FileStart": symbol = new FileStartSymbol(); break; - case "Label": - symbol = processSymbol(app.getSubterm(1)); - break; default: System.err.println("Unknown symbol type `" + app.getName() + "'. Is that normalized SDF3?"); return null; @@ -465,14 +427,39 @@ private Symbol processSymbol(IStrategoTerm term) { return null; } - if(grammar != null && symbol != null) { - grammar.getCacheSymbolsRead().put(term.toString(), symbol); - } - + grammar.getCacheSymbolsRead().put(term.toString(), symbol); grammar.getSymbols().add(symbol); return symbol; } + // TODO this should be done in Stratego instead, which is a lot cleaner than this ad-hoc pattern-matching + private IStrategoTerm removeLabelFromSymbolTerm(IStrategoTerm term) { + if(!(term instanceof StrategoAppl)) + return term; + StrategoAppl app = (StrategoAppl) term; + + if(app.getName().equals("Label")) { + return removeLabelFromSymbolTerm(app.getSubterm(1)); + } + + IStrategoTerm[] children = app.getAllSubterms(); + boolean changed = false; + for(int i = 0; i < children.length; i++) { + IStrategoTerm newChild = removeLabelFromSymbolTerm(children[i]); + if(newChild != children[i]) { + changed = true; + children[i] = newChild; + } + } + + // Only create a new Stratego term if the children have changed. + if(changed) { + return new StrategoAppl(app.getConstructor(), children, app.getAnnotations(), app.getStorageType()); + } + // If there is no `Label` subterm, the full term is reused. + return term; + } + public List processSymbolList(IStrategoTerm term) { List list = Lists.newLinkedList();