forked from jasder/antlr
got lots more rewrite ast done including predicates
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8850]
This commit is contained in:
parent
a06679fec7
commit
1dc598c26e
|
@ -106,20 +106,20 @@ public abstract class BaseRecognizer extends Recognizer<ParserInterpreter> {
|
|||
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);
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -131,7 +131,9 @@ CodeBlockForAlt(c, locals, preamble, ops) ::= <<
|
|||
}
|
||||
>>
|
||||
|
||||
LL1AltBlock(choice, alts, error) ::= <<
|
||||
LL1AltBlock(choice, preamble, alts, error) ::= <<
|
||||
<if(choice.label)><labelref(choice.label)> = input.LT(1);<endif>
|
||||
<preamble; separator="\n">
|
||||
switch ( input.LA(1) ) {
|
||||
<choice.altLook,alts:{look,alt| <cases(ttypes=look)>
|
||||
<alt>
|
||||
|
@ -211,7 +213,9 @@ do {
|
|||
|
||||
// LL(*) stuff
|
||||
|
||||
AltBlock(choice, alts, error) ::= <<
|
||||
AltBlock(choice, preamble, alts, error) ::= <<
|
||||
<if(choice.label)><labelref(choice.label)> = input.LT(1);<endif>
|
||||
<preamble; separator="\n">
|
||||
switch ( _interp.adaptivePredict(input,<choice.decision>,_ctx) ) {
|
||||
<alts:{alt |
|
||||
case <i>:
|
||||
|
@ -281,6 +285,11 @@ _localctx.s = <m.stateNumber>;
|
|||
<if(m.labels)><m.labels:{l | <labelref(l)> = }>(Token)<endif>match(<m.name>);
|
||||
>>
|
||||
|
||||
Wildcard(w) ::= <<
|
||||
_localctx.s = <w.stateNumber>;
|
||||
<if(w.labels)><w.labels:{l | <labelref(l)> = }><endif>input.LT(1); input.consume();
|
||||
>>
|
||||
|
||||
// ACTION STUFF
|
||||
|
||||
Action(a, chunks) ::= "<chunks>"
|
||||
|
@ -381,16 +390,29 @@ ClearElementList(c) ::= "<c.name>.clear();"
|
|||
TrackRuleElement(e) ::= "<e.name>.add(<labelref(e.label)>.tree);"
|
||||
TrackTokenElement(e) ::= "<e.name>.add(_adaptor.create(<labelref(e.label)>));"
|
||||
|
||||
// REWRITE AST stuff
|
||||
// assume roots are always locals in tree rewrites
|
||||
|
||||
TreeRewrite(tr, locals, preamble, ops) ::= <<
|
||||
TreeRewrite(tr, locals, preamble, alts) ::= <<
|
||||
// rewrite: code level= <tr.codeBlockLevel>, tree level = <tr.treeLevel>
|
||||
<locals; separator="\n">
|
||||
<preamble; separator="\n">
|
||||
<ops; separator="\n">
|
||||
<alts; separator="else\n">
|
||||
_localctx.tree = _root0;
|
||||
>>
|
||||
|
||||
RewriteChoice(c, predicate, ops) ::= <<
|
||||
<if(predicate)>
|
||||
if ( <predicate> ) {
|
||||
<ops; separator="\n">
|
||||
}
|
||||
<else>
|
||||
{
|
||||
<ops; separator="\n"> <! empty if EPSILON alt !>
|
||||
}
|
||||
<endif>
|
||||
>>
|
||||
|
||||
RewriteIteratorDecl(d) ::= "Iterator <d.name>;"
|
||||
RewriteIteratorInit(i) ::= "<i.decl.name> = <i.decl.listName>.iterator();"
|
||||
RewriteIteratorName(elemName,level) ::= "it<level>_<elemName>"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -77,15 +77,19 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory {
|
|||
|
||||
public List<SrcOp> rootRule(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> wildcard(GrammarAST ast, GrammarAST labelAST) { return null; }
|
||||
|
||||
// AST REWRITES
|
||||
|
||||
public TreeRewrite treeRewrite(GrammarAST ast) { return null; }
|
||||
|
||||
public RewriteChoice rewrite_choice(PredAST pred, List<SrcOp> 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<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot) { return null; }
|
||||
|
||||
|
@ -99,19 +103,21 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory {
|
|||
|
||||
public List<SrcOp> rewrite_action(ActionAST action, boolean isRoot) { return null; }
|
||||
|
||||
public List<SrcOp> rewrite_epsilon(GrammarAST epsilon) { return null; }
|
||||
|
||||
// BLOCKS
|
||||
|
||||
public Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) { return null; }
|
||||
public Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label) { return null; }
|
||||
|
||||
public Choice getEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) { return null; }
|
||||
|
||||
public Choice getLL1ChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) { return null; }
|
||||
|
||||
public Choice getLLStarChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) { return null; }
|
||||
public Choice getComplexChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) { return null; }
|
||||
|
||||
public Choice getLL1EBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) { return null; }
|
||||
|
||||
public Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) { return null; }
|
||||
public Choice getComplexEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) { return null; }
|
||||
|
||||
public List<SrcOp> getLL1Test(IntervalSet look, GrammarAST blkAST) { return null; }
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ public class CodeGeneratorExtension {
|
|||
|
||||
public List<SrcOp> stringRef(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> wildcard(List<SrcOp> ops) { return ops; }
|
||||
|
||||
// ACTIONS
|
||||
|
||||
|
@ -87,15 +88,35 @@ public class CodeGeneratorExtension {
|
|||
|
||||
public List<SrcOp> leafRule(List<SrcOp> ops) { return ops; }
|
||||
|
||||
// BLOCKS
|
||||
|
||||
public List<SrcOp> getChoiceBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getEBNFBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
/*
|
||||
public List<SrcOp> getLL1ChoiceBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getLL1EBNFBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getComplexChoiceBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getComplexEBNFBlock(List<SrcOp> 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<SrcOp> rewrite_ruleRef(List<SrcOp> ops) { return ops; }
|
||||
|
||||
|
@ -107,21 +128,5 @@ public class CodeGeneratorExtension {
|
|||
|
||||
public List<SrcOp> rewrite_action(List<SrcOp> ops) { return ops; }
|
||||
|
||||
// BLOCKS
|
||||
|
||||
public List<SrcOp> getChoiceBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getEBNFBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getLL1ChoiceBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getLLStarChoiceBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getLL1EBNFBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getLLStarEBNFBlock(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public List<SrcOp> getLL1Test(List<SrcOp> ops) { return ops; }
|
||||
|
||||
public boolean needsImplicitLabel(GrammarAST ID, LabeledOp op) { return false; }
|
||||
public List<SrcOp> rewrite_epsilon(List<SrcOp> ops) { return ops; }
|
||||
}
|
||||
|
|
|
@ -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
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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<CodeBlockForAlt> alts) {
|
||||
Choice c = delegate.getChoiceBlock(blkAST, alts);
|
||||
public List<SrcOp> wildcard(GrammarAST ast, GrammarAST labelAST) {
|
||||
List<SrcOp> ops = delegate.wildcard(ast, labelAST);
|
||||
for (CodeGeneratorExtension ext : extensions) ops = ext.wildcard(ops);
|
||||
return ops;
|
||||
}
|
||||
|
||||
public Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label) {
|
||||
Choice c = delegate.getChoiceBlock(blkAST, alts, label);
|
||||
List<SrcOp> 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<CodeBlockForAlt> alts) {
|
||||
Choice c = delegate.getLL1ChoiceBlock(blkAST, alts);
|
||||
List<SrcOp> ops = DefaultOutputModelFactory.list(c);
|
||||
for (CodeGeneratorExtension ext : extensions) ops = ext.getLL1ChoiceBlock(ops);
|
||||
return c;
|
||||
}
|
||||
|
||||
public Choice getLLStarChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) {
|
||||
Choice c = delegate.getLLStarChoiceBlock(blkAST, alts);
|
||||
List<SrcOp> ops = DefaultOutputModelFactory.list(c);
|
||||
for (CodeGeneratorExtension ext : extensions) ops = ext.getLLStarChoiceBlock(ops);
|
||||
return c;
|
||||
}
|
||||
|
||||
public Choice getLL1EBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) {
|
||||
Choice c = delegate.getLL1EBNFBlock(ebnfRoot, alts);
|
||||
List<SrcOp> ops = DefaultOutputModelFactory.list(c);
|
||||
for (CodeGeneratorExtension ext : extensions) ops = ext.getLL1EBNFBlock(ops);
|
||||
return c;
|
||||
}
|
||||
|
||||
public Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) {
|
||||
Choice c = delegate.getLLStarEBNFBlock(ebnfRoot, alts);
|
||||
List<SrcOp> ops = DefaultOutputModelFactory.list(c);
|
||||
for (CodeGeneratorExtension ext : extensions) ops = ext.getLLStarEBNFBlock(ops);
|
||||
return c;
|
||||
}
|
||||
|
||||
public List<SrcOp> getLL1Test(IntervalSet look, GrammarAST blkAST) {
|
||||
List<SrcOp> 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<SrcOp> 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<SrcOp> rewrite_epsilon(GrammarAST epsilon) {
|
||||
List<SrcOp> 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; }
|
||||
|
|
|
@ -80,17 +80,19 @@ public interface OutputModelFactory {
|
|||
|
||||
List<SrcOp> rootRule(List<SrcOp> ops);
|
||||
|
||||
Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts);
|
||||
List<SrcOp> wildcard(GrammarAST ast, GrammarAST labelAST);
|
||||
|
||||
Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts, GrammarAST label);
|
||||
|
||||
Choice getEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts);
|
||||
|
||||
Choice getLL1ChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts);
|
||||
|
||||
Choice getLLStarChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts);
|
||||
Choice getComplexChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts);
|
||||
|
||||
Choice getLL1EBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts);
|
||||
|
||||
Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts);
|
||||
Choice getComplexEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts);
|
||||
|
||||
List<SrcOp> getLL1Test(IntervalSet look, GrammarAST blkAST);
|
||||
|
||||
|
@ -102,11 +104,13 @@ public interface OutputModelFactory {
|
|||
|
||||
TreeRewrite treeRewrite(GrammarAST ast);
|
||||
|
||||
RewriteChoice rewrite_choice(PredAST pred, List<SrcOp> ops);
|
||||
|
||||
RewriteTreeOptional rewrite_optional(GrammarAST ast);
|
||||
|
||||
RewriteTreeClosure rewrite_closure(GrammarAST ast);
|
||||
|
||||
RewriteTreeStructure rewrite_tree(GrammarAST root);
|
||||
RewriteTreeStructure rewrite_treeStructure(GrammarAST root);
|
||||
|
||||
List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot);
|
||||
|
||||
|
@ -118,6 +122,8 @@ public interface OutputModelFactory {
|
|||
|
||||
List<SrcOp> rewrite_action(ActionAST action, boolean isRoot);
|
||||
|
||||
List<SrcOp> rewrite_epsilon(GrammarAST epsilon);
|
||||
|
||||
// CONTEXT INFO
|
||||
|
||||
OutputModelObject getRoot();
|
||||
|
|
|
@ -44,6 +44,16 @@ public class ParserASTExtension extends CodeGeneratorExtension {
|
|||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SrcOp> getChoiceBlock(List<SrcOp> 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<SrcOp> leafTokenInRewriteAlt(MatchToken matchOp, List<SrcOp> ops) {
|
||||
public List<SrcOp> leafTokenInRewriteAlt(SrcOp matchOp, List<SrcOp> 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<SrcOp> wildcard(List<SrcOp> 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<SrcOp> 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<SrcOp> 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<SrcOp> stringRef(List<SrcOp> ops) { return leafToken(ops); }
|
||||
|
||||
|
|
|
@ -82,21 +82,64 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
return list(invokeOp, listLabelOp);
|
||||
}
|
||||
|
||||
public List<SrcOp> tokenRef(GrammarAST ID, GrammarAST label, GrammarAST args) {
|
||||
LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID, label);
|
||||
public List<SrcOp> 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<CodeBlockForAlt> alts) {
|
||||
@Override
|
||||
public List<SrcOp> 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<CodeBlockForAlt> 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<CodeBlockForAlt> 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<CodeBlockForAlt> alts) {
|
||||
public Choice getComplexChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) {
|
||||
return new AltBlock(this, blkAST, alts);
|
||||
}
|
||||
|
||||
|
@ -147,7 +190,7 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
return c;
|
||||
}
|
||||
|
||||
public Choice getLLStarEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) {
|
||||
public Choice getComplexEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> 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<SrcOp> 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) {
|
||||
|
|
|
@ -40,7 +40,7 @@ block[GrammarAST label, GrammarAST ebnfRoot] returns [List<? extends SrcOp> 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<SrcOp> 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<SrcOp> 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<SrcOp> 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<SrcOp> omos]
|
||||
|
@ -199,7 +201,7 @@ rewriteTreeAlt returns [List<SrcOp> omos]
|
|||
)
|
||||
{$omos = elems;}
|
||||
| ETC
|
||||
| EPSILON
|
||||
| EPSILON {$omos = controller.rewrite_epsilon($EPSILON);}
|
||||
;
|
||||
|
||||
rewriteTreeElement returns [List<SrcOp> omos]
|
||||
|
@ -245,7 +247,7 @@ rewriteTree returns [List<SrcOp> omos]
|
|||
// controller.codeBlockLevel++;
|
||||
controller.treeLevel++;
|
||||
List<SrcOp> elems = new ArrayList<SrcOp>();
|
||||
RewriteTreeStructure t = controller.rewrite_tree($start);
|
||||
RewriteTreeStructure t = controller.rewrite_treeStructure($start);
|
||||
// CodeBlock save = controller.getCurrentBlock();
|
||||
// controller.setCurrentBlock(t);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Decl> labels = new ArrayList<Decl>();
|
||||
|
||||
public Wildcard(OutputModelFactory factory, GrammarAST ast) {
|
||||
super(factory, ast);
|
||||
|
||||
}
|
||||
|
||||
public List<Decl> getLabels() { return labels; }
|
||||
}
|
|
@ -49,9 +49,10 @@ import java.util.*;
|
|||
*/
|
||||
public abstract class Choice extends RuleElement {
|
||||
public int decision = -1;
|
||||
public Decl label;
|
||||
|
||||
@ModelElement public List<CodeBlockForAlt> alts;
|
||||
@ModelElement public List<SrcOp> preamble;
|
||||
@ModelElement public List<SrcOp> preamble = new ArrayList<SrcOp>();
|
||||
|
||||
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<SrcOp>();
|
||||
preamble.add(op);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <rule-context-type> x and list_x
|
||||
String label = labelAST.getText();
|
||||
|
|
|
@ -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<Decl> labels = new ArrayList<Decl>();
|
||||
|
||||
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<Decl> getLabels() { return labels; }
|
||||
|
|
|
@ -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<RewriteChoice> alts = new ArrayList<RewriteChoice>();
|
||||
|
||||
public Rewrite(OutputModelFactory factory, int treeLevel, int codeBlockLevel) {
|
||||
super(factory, treeLevel, codeBlockLevel);
|
||||
}
|
||||
|
|
|
@ -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<SrcOp> ops;
|
||||
|
||||
public RewriteChoice(OutputModelFactory factory, SrcOp predicate, List<SrcOp> ops) {
|
||||
super(factory);
|
||||
this.predicate = predicate;
|
||||
this.ops = ops;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ block[GrammarAST ebnfRoot] returns [ATNFactory.Handle p]
|
|||
|
||||
alternative returns [ATNFactory.Handle p]
|
||||
@init {List<ATNFactory.Handle> els = new ArrayList<ATNFactory.Handle>();}
|
||||
: ^(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);}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue