diff --git a/runtime/Java/src/org/antlr/v4/runtime/BaseRecognizer.java b/runtime/Java/src/org/antlr/v4/runtime/BaseRecognizer.java index 2d9eb0030..c43853ebd 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/BaseRecognizer.java +++ b/runtime/Java/src/org/antlr/v4/runtime/BaseRecognizer.java @@ -106,20 +106,20 @@ public abstract class BaseRecognizer extends Recognizer { failed = false; return matchedSymbol; } - System.out.println("MATCH failure at state "+_ctx.s+ - ", ctx="+_ctx.toString(this)); +// System.out.println("MATCH failure at state "+_ctx.s+ +// ", ctx="+_ctx.toString(this)); IntervalSet expecting = _interp.atn.nextTokens(_ctx); - System.out.println("could match "+expecting); +// System.out.println("could match "+expecting); matchedSymbol = recoverFromMismatchedToken(ttype, expecting); - System.out.println("rsync'd to "+matchedSymbol); +// System.out.println("rsync'd to "+matchedSymbol); return matchedSymbol; } // like matchSet but w/o consume; error checking routine. public void sync(IntervalSet expecting) { if ( expecting.member(input.LA(1)) ) return; - System.out.println("failed sync to "+expecting); +// System.out.println("failed sync to "+expecting); IntervalSet followSet = computeErrorRecoverySet(); followSet.addAll(expecting); NoViableAltException e = new NoViableAltException(this, _ctx); diff --git a/runtime/Java/src/org/antlr/v4/runtime/tree/BaseTree.java b/runtime/Java/src/org/antlr/v4/runtime/tree/BaseTree.java index df6efc11f..5e99a19fc 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/tree/BaseTree.java +++ b/runtime/Java/src/org/antlr/v4/runtime/tree/BaseTree.java @@ -261,7 +261,7 @@ public abstract class BaseTree implements Tree { throw new IllegalStateException("parents don't match; expected "+parent+" found "+this.getParent()); } if ( i!=this.getChildIndex() ) { - throw new IllegalStateException("child indexes don't match; expected "+i+" found "+this.getChildIndex()); + throw new IllegalStateException("child index of "+this.toStringTree()+" doesn't match in "+parent.toStringTree()+"; expected "+i+" found "+this.getChildIndex()); } int n = this.getChildCount(); for (int c = 0; c < n; c++) { diff --git a/tool/playground/T.g b/tool/playground/T.g index e50015c8e..baaa787c7 100644 --- a/tool/playground/T.g +++ b/tool/playground/T.g @@ -1,16 +1,15 @@ grammar T; options {output=AST;} -tokens {I;} -a : A B -> ^(A B); +a : 'var' (ID ':' type ';')+ -> ^('var' ^(':' ID type)*) ; -atom : A ; - -b : B | C ; +type : ID ; +ID : 'a'..'z'+ ; +INT : '0'..'9'+; +WS : (' '|'\n') {$channel=HIDDEN;} ; /* c : A B C -> A ( D A B C*)* (B A*)? ; -*/ A : 'a'; B : 'b'; @@ -18,6 +17,7 @@ C : 'c'; D : 'd'; SEMI : ';'; WS : ' '|'\t'|'\n' {skip();} ; +*/ /* r[int a] returns [int b] diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg index bcdbcce83..beb6d197a 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg @@ -131,7 +131,9 @@ CodeBlockForAlt(c, locals, preamble, ops) ::= << } >> -LL1AltBlock(choice, alts, error) ::= << +LL1AltBlock(choice, preamble, alts, error) ::= << + = input.LT(1); + switch ( input.LA(1) ) { @@ -211,7 +213,9 @@ do { // LL(*) stuff -AltBlock(choice, alts, error) ::= << +AltBlock(choice, preamble, alts, error) ::= << + = input.LT(1); + switch ( _interp.adaptivePredict(input,,_ctx) ) { : @@ -281,6 +285,11 @@ _localctx.s = ; = }>(Token)match(); >> +Wildcard(w) ::= << +_localctx.s = ; + = }>input.LT(1); input.consume(); +>> + // ACTION STUFF Action(a, chunks) ::= "" @@ -381,16 +390,29 @@ ClearElementList(c) ::= ".clear();" TrackRuleElement(e) ::= ".add(.tree);" TrackTokenElement(e) ::= ".add(_adaptor.create());" +// REWRITE AST stuff // assume roots are always locals in tree rewrites -TreeRewrite(tr, locals, preamble, ops) ::= << +TreeRewrite(tr, locals, preamble, alts) ::= << // rewrite: code level= , tree level = - + _localctx.tree = _root0; >> +RewriteChoice(c, predicate, ops) ::= << + +if ( ) { + +} + +{ + +} + +>> + RewriteIteratorDecl(d) ::= "Iterator ;" RewriteIteratorInit(i) ::= " = .iterator();" RewriteIteratorName(elemName,level) ::= "it_" diff --git a/tool/src/org/antlr/v4/codegen/ActionTranslator.java b/tool/src/org/antlr/v4/codegen/ActionTranslator.java index 6778b7a64..921552db2 100644 --- a/tool/src/org/antlr/v4/codegen/ActionTranslator.java +++ b/tool/src/org/antlr/v4/codegen/ActionTranslator.java @@ -245,7 +245,7 @@ public class ActionTranslator implements ActionSplitterListener { Class c = tokenPropToModelMap.get(y.getText()); Constructor ctor = c.getConstructor(new Class[] {String.class}); TokenPropertyRef ref = - (TokenPropertyRef)ctor.newInstance(getRuleLabel(x.getText())); + (TokenPropertyRef)ctor.newInstance(getTokenLabel(x.getText())); return ref; } catch (Exception e) { diff --git a/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java b/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java index a70a1ce40..5c6623b3a 100644 --- a/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java +++ b/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java @@ -77,15 +77,19 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory { public List rootRule(List ops) { return ops; } + public List wildcard(GrammarAST ast, GrammarAST labelAST) { return null; } + // AST REWRITES public TreeRewrite treeRewrite(GrammarAST ast) { return null; } + public RewriteChoice rewrite_choice(PredAST pred, List ops) { return null; } + public RewriteTreeOptional rewrite_optional(GrammarAST ast) { return null; } public RewriteTreeClosure rewrite_closure(GrammarAST ast) { return null; } - public RewriteTreeStructure rewrite_tree(GrammarAST root) { return null; } + public RewriteTreeStructure rewrite_treeStructure(GrammarAST root) { return null; } public List rewrite_ruleRef(GrammarAST ID, boolean isRoot) { return null; } @@ -99,19 +103,21 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory { public List rewrite_action(ActionAST action, boolean isRoot) { return null; } + public List rewrite_epsilon(GrammarAST epsilon) { return null; } + // BLOCKS - public Choice getChoiceBlock(BlockAST blkAST, List alts) { return null; } + public Choice getChoiceBlock(BlockAST blkAST, List alts, GrammarAST label) { return null; } public Choice getEBNFBlock(GrammarAST ebnfRoot, List alts) { return null; } public Choice getLL1ChoiceBlock(BlockAST blkAST, List alts) { return null; } - public Choice getLLStarChoiceBlock(BlockAST blkAST, List alts) { return null; } + public Choice getComplexChoiceBlock(BlockAST blkAST, List alts) { return null; } public Choice getLL1EBNFBlock(GrammarAST ebnfRoot, List alts) { return null; } - public Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List alts) { return null; } + public Choice getComplexEBNFBlock(GrammarAST ebnfRoot, List alts) { return null; } public List getLL1Test(IntervalSet look, GrammarAST blkAST) { return null; } diff --git a/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java b/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java index 898ccf380..cac693164 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java +++ b/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java @@ -68,6 +68,7 @@ public class CodeGeneratorExtension { public List stringRef(List ops) { return ops; } + public List wildcard(List ops) { return ops; } // ACTIONS @@ -87,15 +88,35 @@ public class CodeGeneratorExtension { public List leafRule(List ops) { return ops; } + // BLOCKS + + public List getChoiceBlock(List ops) { return ops; } + + public List getEBNFBlock(List ops) { return ops; } + + /* + public List getLL1ChoiceBlock(List ops) { return ops; } + + public List getLL1EBNFBlock(List ops) { return ops; } + + public List getComplexChoiceBlock(List ops) { return ops; } + + public List getComplexEBNFBlock(List ops) { return ops; } + */ + + public boolean needsImplicitLabel(GrammarAST ID, LabeledOp op) { return false; } + // AST REWRITEs public TreeRewrite treeRewrite(TreeRewrite r) { return r; } + public RewriteChoice rewrite_choice(RewriteChoice r) { return r; } + public RewriteTreeOptional rewrite_optional(RewriteTreeOptional o) { return o; } public RewriteTreeClosure rewrite_closure(RewriteTreeClosure c) { return c; } - public RewriteTreeStructure rewrite_tree(RewriteTreeStructure t) { return t; } + public RewriteTreeStructure rewrite_treeStructure(RewriteTreeStructure t) { return t; } public List rewrite_ruleRef(List ops) { return ops; } @@ -107,21 +128,5 @@ public class CodeGeneratorExtension { public List rewrite_action(List ops) { return ops; } - // BLOCKS - - public List getChoiceBlock(List ops) { return ops; } - - public List getEBNFBlock(List ops) { return ops; } - - public List getLL1ChoiceBlock(List ops) { return ops; } - - public List getLLStarChoiceBlock(List ops) { return ops; } - - public List getLL1EBNFBlock(List ops) { return ops; } - - public List getLLStarEBNFBlock(List ops) { return ops; } - - public List getLL1Test(List ops) { return ops; } - - public boolean needsImplicitLabel(GrammarAST ID, LabeledOp op) { return false; } + public List rewrite_epsilon(List ops) { return ops; } } diff --git a/tool/src/org/antlr/v4/codegen/DefaultOutputModelFactory.java b/tool/src/org/antlr/v4/codegen/DefaultOutputModelFactory.java index bd6a5d54c..30b2551bf 100644 --- a/tool/src/org/antlr/v4/codegen/DefaultOutputModelFactory.java +++ b/tool/src/org/antlr/v4/codegen/DefaultOutputModelFactory.java @@ -55,6 +55,8 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory this.controller = controller; } + // Convenience methods + public Grammar getGrammar() { return g; } public CodeGenerator getGenerator() { return gen; } @@ -95,4 +97,3 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory } } - diff --git a/tool/src/org/antlr/v4/codegen/OutputModelController.java b/tool/src/org/antlr/v4/codegen/OutputModelController.java index c7fd6c9e7..4bccea77e 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelController.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelController.java @@ -34,7 +34,6 @@ import org.antlr.v4.codegen.model.*; import org.antlr.v4.codegen.model.ast.*; import org.antlr.v4.codegen.model.decl.CodeBlock; import org.antlr.v4.parse.*; -import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.tool.*; import java.util.*; @@ -99,7 +98,7 @@ public class OutputModelController { e.printStackTrace(System.err); } - function.ctxType = gen.target.getRuleFunctionContextStructName(r); + function.ctxType = gen.target.getRuleFunctionContextStructName(function); function.ruleCtx.name = function.ctxType; function.postamble = rulePostamble(function, r); @@ -237,8 +236,14 @@ public class OutputModelController { return ops; } - public Choice getChoiceBlock(BlockAST blkAST, List alts) { - Choice c = delegate.getChoiceBlock(blkAST, alts); + public List wildcard(GrammarAST ast, GrammarAST labelAST) { + List ops = delegate.wildcard(ast, labelAST); + for (CodeGeneratorExtension ext : extensions) ops = ext.wildcard(ops); + return ops; + } + + public Choice getChoiceBlock(BlockAST blkAST, List alts, GrammarAST label) { + Choice c = delegate.getChoiceBlock(blkAST, alts, label); List ops = DefaultOutputModelFactory.list(c); for (CodeGeneratorExtension ext : extensions) ops = ext.getChoiceBlock(ops); return c; @@ -251,40 +256,6 @@ public class OutputModelController { return c; } - public Choice getLL1ChoiceBlock(BlockAST blkAST, List alts) { - Choice c = delegate.getLL1ChoiceBlock(blkAST, alts); - List ops = DefaultOutputModelFactory.list(c); - for (CodeGeneratorExtension ext : extensions) ops = ext.getLL1ChoiceBlock(ops); - return c; - } - - public Choice getLLStarChoiceBlock(BlockAST blkAST, List alts) { - Choice c = delegate.getLLStarChoiceBlock(blkAST, alts); - List ops = DefaultOutputModelFactory.list(c); - for (CodeGeneratorExtension ext : extensions) ops = ext.getLLStarChoiceBlock(ops); - return c; - } - - public Choice getLL1EBNFBlock(GrammarAST ebnfRoot, List alts) { - Choice c = delegate.getLL1EBNFBlock(ebnfRoot, alts); - List ops = DefaultOutputModelFactory.list(c); - for (CodeGeneratorExtension ext : extensions) ops = ext.getLL1EBNFBlock(ops); - return c; - } - - public Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List alts) { - Choice c = delegate.getLLStarEBNFBlock(ebnfRoot, alts); - List ops = DefaultOutputModelFactory.list(c); - for (CodeGeneratorExtension ext : extensions) ops = ext.getLLStarEBNFBlock(ops); - return c; - } - - public List getLL1Test(IntervalSet look, GrammarAST blkAST) { - List ops = delegate.getLL1Test(look, blkAST); - for (CodeGeneratorExtension ext : extensions) ops = ext.getLL1Test(ops); - return ops; - } - public boolean needsImplicitLabel(GrammarAST ID, LabeledOp op) { boolean needs = delegate.needsImplicitLabel(ID, op); for (CodeGeneratorExtension ext : extensions) needs |= ext.needsImplicitLabel(ID, op); @@ -299,6 +270,12 @@ public class OutputModelController { return r; } + public RewriteChoice rewrite_choice(PredAST pred, List ops) { + RewriteChoice r = delegate.rewrite_choice(pred, ops); + for (CodeGeneratorExtension ext : extensions) r = ext.rewrite_choice(r); + return r; + } + public RewriteTreeOptional rewrite_optional(GrammarAST ast) { RewriteTreeOptional o = delegate.rewrite_optional(ast); for (CodeGeneratorExtension ext : extensions) o = ext.rewrite_optional(o); @@ -311,9 +288,9 @@ public class OutputModelController { return c; } - public RewriteTreeStructure rewrite_tree(GrammarAST root) { - RewriteTreeStructure t = delegate.rewrite_tree(root); - for (CodeGeneratorExtension ext : extensions) t = ext.rewrite_tree(t); + public RewriteTreeStructure rewrite_treeStructure(GrammarAST root) { + RewriteTreeStructure t = delegate.rewrite_treeStructure(root); + for (CodeGeneratorExtension ext : extensions) t = ext.rewrite_treeStructure(t); return t; } @@ -345,6 +322,12 @@ public class OutputModelController { return ops; } + public List rewrite_epsilon(GrammarAST epsilon) { + List ops = delegate.rewrite_epsilon(epsilon); + for (CodeGeneratorExtension ext : extensions) ops = ext.rewrite_epsilon(ops); + return ops; + } + public OutputModelObject getRoot() { return root; } public void setRoot(OutputModelObject root) { this.root = root; } diff --git a/tool/src/org/antlr/v4/codegen/OutputModelFactory.java b/tool/src/org/antlr/v4/codegen/OutputModelFactory.java index 44f777b0e..da91f4ad6 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelFactory.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelFactory.java @@ -80,17 +80,19 @@ public interface OutputModelFactory { List rootRule(List ops); - Choice getChoiceBlock(BlockAST blkAST, List alts); + List wildcard(GrammarAST ast, GrammarAST labelAST); + + Choice getChoiceBlock(BlockAST blkAST, List alts, GrammarAST label); Choice getEBNFBlock(GrammarAST ebnfRoot, List alts); Choice getLL1ChoiceBlock(BlockAST blkAST, List alts); - Choice getLLStarChoiceBlock(BlockAST blkAST, List alts); + Choice getComplexChoiceBlock(BlockAST blkAST, List alts); Choice getLL1EBNFBlock(GrammarAST ebnfRoot, List alts); - Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List alts); + Choice getComplexEBNFBlock(GrammarAST ebnfRoot, List alts); List getLL1Test(IntervalSet look, GrammarAST blkAST); @@ -102,11 +104,13 @@ public interface OutputModelFactory { TreeRewrite treeRewrite(GrammarAST ast); + RewriteChoice rewrite_choice(PredAST pred, List ops); + RewriteTreeOptional rewrite_optional(GrammarAST ast); RewriteTreeClosure rewrite_closure(GrammarAST ast); - RewriteTreeStructure rewrite_tree(GrammarAST root); + RewriteTreeStructure rewrite_treeStructure(GrammarAST root); List rewrite_ruleRef(GrammarAST ID, boolean isRoot); @@ -118,6 +122,8 @@ public interface OutputModelFactory { List rewrite_action(ActionAST action, boolean isRoot); + List rewrite_epsilon(GrammarAST epsilon); + // CONTEXT INFO OutputModelObject getRoot(); diff --git a/tool/src/org/antlr/v4/codegen/ParserASTExtension.java b/tool/src/org/antlr/v4/codegen/ParserASTExtension.java index 856855c99..477992c00 100644 --- a/tool/src/org/antlr/v4/codegen/ParserASTExtension.java +++ b/tool/src/org/antlr/v4/codegen/ParserASTExtension.java @@ -44,6 +44,16 @@ public class ParserASTExtension extends CodeGeneratorExtension { super(factory); } + @Override + public List getChoiceBlock(List ops) { + Choice choice = (Choice)Utils.find(ops, Choice.class); + Alternative alt = factory.getCurrentAlt(); + if ( alt.hasRewrite() && choice.label!=null ) { + trackExplicitLabel(choice.preamble, choice.label, choice); + } + return ops; + } + @Override public CodeBlockForAlt alternative(CodeBlockForAlt blk) { Alternative alt = factory.getCurrentAlt(); @@ -133,62 +143,89 @@ public class ParserASTExtension extends CodeGeneratorExtension { CodeBlock blk = factory.getCurrentAlternativeBlock(); String elemListName = factory.getGenerator().target.getElementListName(invokeOp.ast.getText()); blk.addLocalDecl(new ElementListDecl(factory, elemListName)); - // track any explicit label like _track_label but not implicit label - if ( !label.isImplicit ) { - String labelListName = - factory.getGenerator().target.getElementListName(label.name); - blk.addLocalDecl(new ElementListDecl(factory, labelListName)); - } + + // add code to track rule results in _track_r String trackName = factory.getGenerator().target.getElementListName(invokeOp.ast.getText()); TrackRuleElement t = new TrackRuleElement(factory, invokeOp.ast, trackName, label); + clearTrackingIfSingularLabel(ops, invokeOp, trackName); ops.add(t); - if ( !label.isImplicit ) { - trackName = factory.getGenerator().target.getElementListName(label.name); - TrackRuleElement t2 = new TrackRuleElement(factory, invokeOp.ast, trackName, - label); - if ( invokeOp.ast.parent.getType() == ANTLRParser.ASSIGN ) { - // if x=A must keep it a single-element list; clear before add - ClearElementList c = new ClearElementList(factory, invokeOp.ast, trackName); - ops.add(c); - } - ops.add(t2); - } + + // track any explicit label like _track_label but not implicit label + if ( !label.isImplicit ) trackExplicitLabel(ops, label, invokeOp); + return ops; } - public List leafTokenInRewriteAlt(MatchToken matchOp, List ops) { + public List leafTokenInRewriteAlt(SrcOp matchOp, List ops) { CodeBlock blk = factory.getCurrentAlternativeBlock(); - TokenDecl label = (TokenDecl)matchOp.getLabels().get(0); + TokenDecl label = (TokenDecl)((LabeledOp)matchOp).getLabels().get(0); // First declare tracking lists for elements, labels // track the named element like _track_A String elemListName = factory.getGenerator().target.getElementListName(matchOp.ast.getText()); blk.addLocalDecl(new ElementListDecl(factory, elemListName)); - // track any explicit label like _track_label but not implicit label - if ( !label.isImplicit ) { - String labelListName = - factory.getGenerator().target.getElementListName(label.name); - blk.addLocalDecl(new ElementListDecl(factory, labelListName)); - } // Now, generate track instructions for element and any labels // do element String trackName = factory.getGenerator().target.getElementListName(matchOp.ast.getText()); TrackTokenElement t = new TrackTokenElement(factory, matchOp.ast, trackName, label); + clearTrackingIfSingularLabel(ops, matchOp, trackName); ops.add(t); - if ( !label.isImplicit ) { // track all explicit labels - trackName = factory.getGenerator().target.getElementListName(label.name); - TrackTokenElement t2 = new TrackTokenElement(factory, matchOp.ast, trackName, - label); - if ( matchOp.ast.parent.getType() == ANTLRParser.ASSIGN ) { - // if x=A must keep it a single-element list; clear before add - ClearElementList c = new ClearElementList(factory, matchOp.ast, trackName); - ops.add(c); - } - ops.add(t2); - } + if ( !label.isImplicit ) trackExplicitLabel(ops, label, matchOp); return ops; } + @Override + public List wildcard(List ops) { + Wildcard wild = (Wildcard)Utils.find(ops, Wildcard.class); + Alternative alt = factory.getCurrentAlt(); + if ( alt.hasRewrite() ) { + TokenDecl label = (TokenDecl)((LabeledOp)wild).getLabels().get(0); + if ( !label.isImplicit ) trackExplicitLabel(ops, label, wild); + return ops; + } + else { + TokenDecl label = (TokenDecl)wild.getLabels().get(0); + SrcOp treeOp = new TokenAST(factory, wild.ast, label); + String rootName = factory.getGenerator().target.getRootName(0); + SrcOp add = new AddChild(factory, rootName, treeOp); + ops.add(add); + return ops; + } + } + + public void trackExplicitLabel(List ops, Decl label, SrcOp opWithLabel) { + CodeBlock blk = factory.getCurrentAlternativeBlock(); + // declare _track_label + String labelListName = + factory.getGenerator().target.getElementListName(label.name); + blk.addLocalDecl(new ElementListDecl(factory, labelListName)); + + // add elements to _track_label + SrcOp trk; + if ( opWithLabel instanceof InvokeRule ) { + trk = new TrackRuleElement(factory, opWithLabel.ast, labelListName, label); + } + else if ( opWithLabel instanceof Choice || + opWithLabel instanceof MatchToken || + opWithLabel instanceof Wildcard ) + { + trk = new TrackTokenElement(factory, opWithLabel.ast, labelListName, label); + } + else { + trk = null; + } + clearTrackingIfSingularLabel(ops, opWithLabel, labelListName); + ops.add(trk); + } + + public void clearTrackingIfSingularLabel(List ops, SrcOp opWithLabel, String trackName) { + if ( opWithLabel.ast.parent.getType() == ANTLRParser.ASSIGN ) { + // if x=A must keep it a single-element list; clear before add + ClearElementList c = new ClearElementList(factory, opWithLabel.ast, trackName); + ops.add(c); + } + } + @Override public List stringRef(List ops) { return leafToken(ops); } diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index 54a3740e0..c3188953e 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -82,21 +82,64 @@ public class ParserFactory extends DefaultOutputModelFactory { return list(invokeOp, listLabelOp); } - public List tokenRef(GrammarAST ID, GrammarAST label, GrammarAST args) { - LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID, label); + public List tokenRef(GrammarAST ID, GrammarAST labelAST, GrammarAST args) { + LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID); + if ( labelAST!=null ) { + String label = labelAST.getText(); + TokenDecl d = new TokenDecl(this, label); + ((MatchToken)matchOp).labels.add(d); + getCurrentRuleFunction().addContextDecl(d); + if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) { + TokenListDecl l = new TokenListDecl(this, gen.target.getListLabel(label)); + getCurrentRuleFunction().addContextDecl(l); + } + } if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp); - AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, label); + AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, labelAST); return list(matchOp, listLabelOp); } - public Choice getChoiceBlock(BlockAST blkAST, List alts) { + @Override + public List wildcard(GrammarAST ast, GrammarAST labelAST) { + Wildcard wild = new Wildcard(this, ast); + // TODO: dup with tokenRef + if ( labelAST!=null ) { + String label = labelAST.getText(); + TokenDecl d = new TokenDecl(this, label); + wild.labels.add(d); + getCurrentRuleFunction().addContextDecl(d); + if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) { + TokenListDecl l = new TokenListDecl(this, gen.target.getListLabel(label)); + getCurrentRuleFunction().addContextDecl(l); + } + } + AddToLabelList listLabelOp = getListLabelIfPresent(wild, labelAST); + return list(wild, listLabelOp); + } + + public Choice getChoiceBlock(BlockAST blkAST, List alts, GrammarAST labelAST) { int decision = ((DecisionState)blkAST.atnState).decision; + Choice c; if ( AnalysisPipeline.disjoint(g.decisionLOOK.get(decision)) ) { - return getLL1ChoiceBlock(blkAST, alts); + c = getLL1ChoiceBlock(blkAST, alts); } else { - return getLLStarChoiceBlock(blkAST, alts); + c = getComplexChoiceBlock(blkAST, alts); } + + if ( labelAST!=null ) { // for x=(...), define x or x_list + String label = labelAST.getText(); + TokenDecl d = new TokenDecl(this,label); + c.label = d; + getCurrentRuleFunction().addContextDecl(d); + if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) { + String listLabel = gen.target.getListLabel(label); + TokenListDecl l = new TokenListDecl(this, listLabel); + getCurrentRuleFunction().addContextDecl(l); + } + } + + return c; } public Choice getEBNFBlock(GrammarAST ebnfRoot, List alts) { @@ -114,7 +157,7 @@ public class ParserFactory extends DefaultOutputModelFactory { return getLL1EBNFBlock(ebnfRoot, alts); } else { - return getLLStarEBNFBlock(ebnfRoot, alts); + return getComplexEBNFBlock(ebnfRoot, alts); } } @@ -122,7 +165,7 @@ public class ParserFactory extends DefaultOutputModelFactory { return new LL1AltBlock(this, blkAST, alts); } - public Choice getLLStarChoiceBlock(BlockAST blkAST, List alts) { + public Choice getComplexChoiceBlock(BlockAST blkAST, List alts) { return new AltBlock(this, blkAST, alts); } @@ -147,7 +190,7 @@ public class ParserFactory extends DefaultOutputModelFactory { return c; } - public Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List alts) { + public Choice getComplexEBNFBlock(GrammarAST ebnfRoot, List alts) { int ebnf = 0; if ( ebnfRoot!=null ) ebnf = ebnfRoot.getType(); Choice c = null; @@ -196,6 +239,14 @@ public class ParserFactory extends DefaultOutputModelFactory { return tr; } + @Override + public RewriteChoice rewrite_choice(PredAST pred, List ops) { + RewriteAction predAction = null; + if ( pred!=null ) predAction = new RewriteAction(this, pred); + RewriteChoice c = new RewriteChoice(this, predAction, ops); + return c; + } + @Override public RewriteTreeOptional rewrite_optional(GrammarAST ast) { RewriteTreeOptional o = @@ -237,7 +288,7 @@ public class ParserFactory extends DefaultOutputModelFactory { } @Override - public RewriteTreeStructure rewrite_tree(GrammarAST root) { + public RewriteTreeStructure rewrite_treeStructure(GrammarAST root) { RewriteTreeStructure t = new RewriteTreeStructure(this, root, getTreeLevel(), getCodeBlockLevel()); t.addLocalDecl( new RootDecl(this, getTreeLevel()) ); return t; @@ -298,7 +349,8 @@ public class ParserFactory extends DefaultOutputModelFactory { Rule r = g.getRule(ID.getText()); if ( r!=null ) { String implLabel = gen.target.getImplicitRuleLabel(ID.getText()); - String ctxName = gen.target.getRuleFunctionContextStructName(r); + String ctxName = + gen.target.getRuleFunctionContextStructName(r); d = new RuleContextDecl(this, implLabel, ctxName); ((RuleContextDecl)d).isImplicit = true; } @@ -308,7 +360,8 @@ public class ParserFactory extends DefaultOutputModelFactory { ((TokenDecl)d).isImplicit = true; } op.getLabels().add(d); - getCurrentRuleFunction().addLocalDecl(d); + // all labels must be in scope struct in case we exec action out of context + getCurrentRuleFunction().addContextDecl(d); } public AddToLabelList getListLabelIfPresent(LabeledOp op, GrammarAST label) { diff --git a/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g b/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g index 78c178042..86884d439 100644 --- a/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g +++ b/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g @@ -40,7 +40,7 @@ block[GrammarAST label, GrammarAST ebnfRoot] returns [List omos { if ( alts.size()==1 && ebnfRoot==null) return alts; if ( ebnfRoot==null ) { - $omos = DefaultOutputModelFactory.list(controller.getChoiceBlock((BlockAST)$blk, alts)); + $omos = DefaultOutputModelFactory.list(controller.getChoiceBlock((BlockAST)$blk, alts, $label)); } else { $omos = DefaultOutputModelFactory.list(controller.getEBNFBlock($ebnfRoot, alts)); @@ -123,8 +123,8 @@ atom[GrammarAST label] returns [List omos] | range[label] {$omos = $range.omos;} | ^(DOT ID terminal[label]) | ^(DOT ID ruleref[label]) - | ^(WILDCARD .) - | WILDCARD + | ^(WILDCARD .) {$omos = controller.wildcard($WILDCARD, $label);} + | WILDCARD {$omos = controller.wildcard($WILDCARD, $label);} | ^(ROOT terminal[label]) {$omos = controller.rootToken($terminal.omos);} | ^(BANG terminal[label]) {$omos = $terminal.omos;} | terminal[label] {$omos = $terminal.omos;} @@ -174,22 +174,24 @@ rewrite returns [Rewrite code] CodeBlock save = controller.getCurrentBlock(); controller.setCurrentBlock($code); } - predicatedRewrite* nakedRewrite + ( (p=predicatedRewrite {$code.alts.add($p.alt);})+ + r=nakedRewrite {$code.alts.add($r.alt);} + | r=nakedRewrite {$code.alts.add($r.alt);} + ) { - $code.ops = $nakedRewrite.omos; controller.setCurrentBlock(save); controller.codeBlockLevel--; } ; -predicatedRewrite returns [List omos] - : ^(ST_RESULT SEMPRED rewriteSTAlt) - | ^(RESULT SEMPRED rewriteTreeAlt) +predicatedRewrite returns [RewriteChoice alt] + : ^(ST_RESULT SEMPRED rewriteSTAlt) + | ^(RESULT SEMPRED rewriteTreeAlt) {$alt = controller.rewrite_choice((PredAST)$SEMPRED, $rewriteTreeAlt.omos);} ; -nakedRewrite returns [List omos] +nakedRewrite returns [RewriteChoice alt] : ^(ST_RESULT rewriteSTAlt) - | ^(RESULT rewriteTreeAlt) {$omos = $rewriteTreeAlt.omos;} + | ^(RESULT rewriteTreeAlt) {$alt = controller.rewrite_choice(null, $rewriteTreeAlt.omos);} ; rewriteTreeAlt returns [List omos] @@ -199,7 +201,7 @@ rewriteTreeAlt returns [List omos] ) {$omos = elems;} | ETC - | EPSILON + | EPSILON {$omos = controller.rewrite_epsilon($EPSILON);} ; rewriteTreeElement returns [List omos] @@ -245,7 +247,7 @@ rewriteTree returns [List omos] // controller.codeBlockLevel++; controller.treeLevel++; List elems = new ArrayList(); - RewriteTreeStructure t = controller.rewrite_tree($start); + RewriteTreeStructure t = controller.rewrite_treeStructure($start); // CodeBlock save = controller.getCurrentBlock(); // controller.setCurrentBlock(t); } diff --git a/tool/src/org/antlr/v4/codegen/Target.java b/tool/src/org/antlr/v4/codegen/Target.java index 7ccdbb142..d3f0f9404 100644 --- a/tool/src/org/antlr/v4/codegen/Target.java +++ b/tool/src/org/antlr/v4/codegen/Target.java @@ -29,6 +29,7 @@ package org.antlr.v4.codegen; +import org.antlr.v4.codegen.model.RuleFunction; import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.runtime.*; import org.antlr.v4.tool.*; @@ -193,11 +194,30 @@ public class Target { public String getListLabel(String label) { return label+"_list"; } public String getRuleFunctionContextStructName(Rule r) { - if ( r.args==null && r.retvals==null && r.scope==null && r.getLabelNames()==null ) { + boolean hasNoExternallyVisibleElements = + r.args==null && r.retvals==null && r.scope==null && r.getLabelNames()==null; + if ( hasNoExternallyVisibleElements ) { return gen.templates.getInstanceOf("ParserRuleContext").render(); } return r.name+"_ctx"; } + + /** If we know which actual function, we can provide the actual ctx type. + * This will contain implicit labels etc... From outside, though, we + * see only ParserRuleContext unless there are externally visible stuff + * like args, locals, explicit labels, etc... + */ + public String getRuleFunctionContextStructName(RuleFunction function) { + Rule r = function.rule; + boolean hasNoExternallyVisibleElements = + r.args==null && r.retvals==null && r.scope==null && r.getLabelNames()==null; + + if ( hasNoExternallyVisibleElements && function.ruleCtx.isEmpty() ) { + return gen.templates.getInstanceOf("ParserRuleContext").render(); + } + return r.name+"_ctx"; + } + public String getRuleDynamicScopeStructName(String ruleName) { ST st = gen.templates.getInstanceOf("RuleDynamicScopeStructName"); st.add("ruleName", ruleName); diff --git a/tool/src/org/antlr/v4/codegen/Wildcard.java b/tool/src/org/antlr/v4/codegen/Wildcard.java new file mode 100644 index 000000000..ec2bbb0d5 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/Wildcard.java @@ -0,0 +1,47 @@ +/* + [The "BSD license"] + Copyright (c) 2011 Terence Parr + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.antlr.v4.codegen; + +import org.antlr.v4.codegen.model.*; +import org.antlr.v4.codegen.model.decl.Decl; +import org.antlr.v4.tool.GrammarAST; + +import java.util.*; + +public class Wildcard extends RuleElement implements LabeledOp { + public List labels = new ArrayList(); + + public Wildcard(OutputModelFactory factory, GrammarAST ast) { + super(factory, ast); + + } + + public List getLabels() { return labels; } +} diff --git a/tool/src/org/antlr/v4/codegen/model/Choice.java b/tool/src/org/antlr/v4/codegen/model/Choice.java index fb9fafe4a..e539101c2 100644 --- a/tool/src/org/antlr/v4/codegen/model/Choice.java +++ b/tool/src/org/antlr/v4/codegen/model/Choice.java @@ -49,9 +49,10 @@ import java.util.*; */ public abstract class Choice extends RuleElement { public int decision = -1; + public Decl label; @ModelElement public List alts; - @ModelElement public List preamble; + @ModelElement public List preamble = new ArrayList(); public Choice(OutputModelFactory factory, GrammarAST blkOrEbnfRootAST, @@ -62,7 +63,6 @@ public abstract class Choice extends RuleElement { } public void addPreambleOp(SrcOp op) { - if ( preamble==null ) preamble = new ArrayList(); preamble.add(op); } diff --git a/tool/src/org/antlr/v4/codegen/model/InvokeRule.java b/tool/src/org/antlr/v4/codegen/model/InvokeRule.java index 62779c1fa..c4d792d11 100644 --- a/tool/src/org/antlr/v4/codegen/model/InvokeRule.java +++ b/tool/src/org/antlr/v4/codegen/model/InvokeRule.java @@ -55,8 +55,9 @@ public class InvokeRule extends RuleElement implements LabeledOp { this.name = ast.getText(); CodeGenerator gen = factory.getGenerator(); Rule r = factory.getGrammar().getRule(name); - ctxName = gen.target.getRuleFunctionContextStructName(r); + ctxName = gen.target.getRuleFunctionContextStructName(factory.getCurrentRuleFunction()); + // TODO: move to factory if ( labelAST!=null ) { // for x=r, define x and list_x String label = labelAST.getText(); diff --git a/tool/src/org/antlr/v4/codegen/model/MatchToken.java b/tool/src/org/antlr/v4/codegen/model/MatchToken.java index 9a2a26381..b8274a19e 100644 --- a/tool/src/org/antlr/v4/codegen/model/MatchToken.java +++ b/tool/src/org/antlr/v4/codegen/model/MatchToken.java @@ -30,8 +30,7 @@ package org.antlr.v4.codegen.model; import org.antlr.v4.codegen.*; -import org.antlr.v4.codegen.model.decl.*; -import org.antlr.v4.parse.ANTLRParser; +import org.antlr.v4.codegen.model.decl.Decl; import org.antlr.v4.tool.*; import java.util.*; @@ -41,22 +40,12 @@ public class MatchToken extends RuleElement implements LabeledOp { public String name; public List labels = new ArrayList(); - public MatchToken(OutputModelFactory factory, TerminalAST ast, GrammarAST labelAST) { + public MatchToken(OutputModelFactory factory, TerminalAST ast) { super(factory, ast); Grammar g = factory.getGrammar(); CodeGenerator gen = factory.getGenerator(); int ttype = g.getTokenType(ast.getText()); name = gen.target.getTokenTypeAsTargetLabel(g, ttype); - if ( labelAST!=null ) { // TODO: move to factory - String label = labelAST.getText(); - TokenDecl d = new TokenDecl(factory, label); - labels.add(d); - factory.getCurrentRuleFunction().addContextDecl(d); - if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) { - TokenListDecl l = new TokenListDecl(factory, gen.target.getListLabel(label)); - factory.getCurrentRuleFunction().addContextDecl(l); - } - } } public List getLabels() { return labels; } diff --git a/tool/src/org/antlr/v4/codegen/model/Rewrite.java b/tool/src/org/antlr/v4/codegen/model/Rewrite.java index 9e6ce4892..622092c60 100644 --- a/tool/src/org/antlr/v4/codegen/model/Rewrite.java +++ b/tool/src/org/antlr/v4/codegen/model/Rewrite.java @@ -30,10 +30,15 @@ package org.antlr.v4.codegen.model; import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.codegen.model.ast.RewriteChoice; import org.antlr.v4.codegen.model.decl.CodeBlock; +import java.util.*; + /** Either an ST or Tree rewrite */ public class Rewrite extends CodeBlock { + @ModelElement public List alts = new ArrayList(); + public Rewrite(OutputModelFactory factory, int treeLevel, int codeBlockLevel) { super(factory, treeLevel, codeBlockLevel); } diff --git a/tool/src/org/antlr/v4/codegen/model/ast/RewriteChoice.java b/tool/src/org/antlr/v4/codegen/model/ast/RewriteChoice.java new file mode 100644 index 000000000..845091607 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/ast/RewriteChoice.java @@ -0,0 +1,50 @@ +/* + [The "BSD license"] + Copyright (c) 2011 Terence Parr + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.antlr.v4.codegen.model.ast; + +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.codegen.model.*; + +import java.util.List; + +/** A collection of operations possibly with a predicate + * that indicates whether to apply the rewrite. + * This is a single alternative and a list of predicated choices. + */ +public class RewriteChoice extends SrcOp { + @ModelElement public SrcOp predicate; + @ModelElement public List ops; + + public RewriteChoice(OutputModelFactory factory, SrcOp predicate, List ops) { + super(factory); + this.predicate = predicate; + this.ops = ops; + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/ast/TemplateRewrite.java b/tool/src/org/antlr/v4/codegen/model/ast/TemplateRewrite.java new file mode 100644 index 000000000..97d7054b3 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/ast/TemplateRewrite.java @@ -0,0 +1,39 @@ +/* + [The "BSD license"] + Copyright (c) 2011 Terence Parr + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.antlr.v4.codegen.model.ast; + +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.codegen.model.Rewrite; + +public class TemplateRewrite extends Rewrite { + public TemplateRewrite(OutputModelFactory factory, int treeLevel, int codeBlockLevel) { + super(factory, treeLevel, codeBlockLevel); + } +} diff --git a/tool/src/org/antlr/v4/misc/Utils.java b/tool/src/org/antlr/v4/misc/Utils.java index e5f2661a1..5522ea672 100644 --- a/tool/src/org/antlr/v4/misc/Utils.java +++ b/tool/src/org/antlr/v4/misc/Utils.java @@ -171,10 +171,11 @@ public class Utils { return b; } - /** Find exact object type in list */ + /** Find exact object type or sublass of cl in list */ public static Object find(List ops, Class cl) { for (Object o : ops) { - if ( o.getClass() == cl ) return o; + if ( cl.isInstance(o) ) return o; +// if ( o.getClass() == cl ) return o; } return null; } diff --git a/tool/src/org/antlr/v4/parse/ATNBuilder.g b/tool/src/org/antlr/v4/parse/ATNBuilder.g index 1d430fecc..4362e522f 100644 --- a/tool/src/org/antlr/v4/parse/ATNBuilder.g +++ b/tool/src/org/antlr/v4/parse/ATNBuilder.g @@ -83,7 +83,7 @@ block[GrammarAST ebnfRoot] returns [ATNFactory.Handle p] alternative returns [ATNFactory.Handle p] @init {List els = new ArrayList();} - : ^(ALT_REWRITE a=alternative .) {$p = $a.p;} + : ^(ALT_REWRITE a=alternative .*) {$p = $a.p;} | ^(ALT EPSILON) {$p = factory.epsilon($EPSILON);} | ^(ALT (e=element {els.add($e.p);})+) {$p = factory.alt(els);} diff --git a/tool/src/org/antlr/v4/semantics/Refs.g b/tool/src/org/antlr/v4/semantics/Refs.g index fcaac182e..03f84468e 100644 --- a/tool/src/org/antlr/v4/semantics/Refs.g +++ b/tool/src/org/antlr/v4/semantics/Refs.g @@ -31,9 +31,9 @@ public void track(GrammarAST t, int level) { // TODO: visitor would be better here } -/* -rewrite +start : predicatedRewrite* nakedRewrite + | rewriteTreeEbnf[0] ; predicatedRewrite @@ -44,13 +44,6 @@ nakedRewrite : ^(RESULT rewriteAlt) ; - */ - -start - : ^(RESULT rewriteAlt) - | rewriteTreeEbnf[0] - ; - rewriteAlt : rewriteTreeAlt[0] | ETC diff --git a/tool/test/org/antlr/v4/test/TestRewriteAST.java b/tool/test/org/antlr/v4/test/TestRewriteAST.java index b2ae0f7be..eddfbf328 100644 --- a/tool/test/org/antlr/v4/test/TestRewriteAST.java +++ b/tool/test/org/antlr/v4/test/TestRewriteAST.java @@ -874,7 +874,7 @@ public class TestRewriteAST extends BaseTest { "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "a b", debug); - assertEquals("a b\n", found); + assertEquals("a a b\n", found); } @Test public void testOptional() throws Exception { @@ -988,7 +988,6 @@ public class TestRewriteAST extends BaseTest { } @Test public void testSetWithLabel() throws Exception { - String grammar = "grammar T;\n" + "options { output = AST; } \n" + @@ -1047,7 +1046,7 @@ public class TestRewriteAST extends BaseTest { execParser("T.g", grammar, "TParser", "TLexer", "a", "a b 3 4 5", debug); String expecting = - "org.antlr.runtime.tree.RewriteCardinalityException: token ID"; + "org.antlr.v4.runtime.tree.RewriteCardinalityException: size==2 and out of elements"; String found = getFirstLineOfException(); assertEquals(expecting, found); } @@ -1064,7 +1063,7 @@ public class TestRewriteAST extends BaseTest { execParser("T.g", grammar, "TParser", "TLexer", "a", "a b", debug); String expecting = - "org.antlr.runtime.tree.RewriteCardinalityException: token ID"; + "org.antlr.v4.runtime.tree.RewriteCardinalityException: size==2 and out of elements"; String found = getFirstLineOfException(); assertEquals(expecting, found); } @@ -1081,24 +1080,7 @@ public class TestRewriteAST extends BaseTest { execParser("T.g", grammar, "TParser", "TLexer", "a", "3", debug); String expecting = - "org.antlr.runtime.tree.RewriteEmptyStreamException: token ID"; - String found = getFirstLineOfException(); - assertEquals(expecting, found); - } - - @Test public void testLoopCardinality() throws Exception { - String grammar = - "grammar T;\n" + - "options {output=AST;}\n" + - "a : ID? INT -> ID* INT ;\n" + - "op : '+'|'-' ;\n" + - "ID : 'a'..'z'+ ;\n" + - "INT : '0'..'9'+;\n" + - "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; - execParser("T.g", grammar, "TParser", "TLexer", - "a", "3", debug); - String expecting = - "org.antlr.runtime.tree.RewriteEarlyExitException"; + "org.antlr.v4.runtime.tree.RewriteEmptyStreamException: n/a"; String found = getFirstLineOfException(); assertEquals(expecting, found); } @@ -1116,6 +1098,19 @@ public class TestRewriteAST extends BaseTest { assertEquals("34\n", found); } + @Test public void testWildcard2() throws Exception { + String grammar = + "grammar T;\n" + + "options {output=AST;}\n" + + "a : ID c+=. c+=. -> $c*;\n" + + "ID : 'a'..'z'+ ;\n" + + "INT : '0'..'9'+;\n" + + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; + String found = execParser("T.g", grammar, "TParser", "TLexer", + "a", "abc 34 def", debug); + assertEquals("34 def\n", found); + } + // E R R O R S /*