forked from jasder/antlr
Merge remote-tracking branch 'parrt/master'
This commit is contained in:
commit
27806dc490
|
@ -1,5 +1,9 @@
|
|||
ANTLR v4 Honey Badger early access
|
||||
|
||||
Feb 14, 2012
|
||||
|
||||
* Fixed https://github.com/antlr/antlr4/issues/8 and lots of other little things.
|
||||
|
||||
Jan 30, 2012
|
||||
|
||||
* Moving to github.
|
||||
|
|
|
@ -64,8 +64,10 @@ public class CommonToken implements WritableToken, Serializable {
|
|||
this.channel = channel;
|
||||
this.start = start;
|
||||
this.stop = stop;
|
||||
this.line = source.getLine();
|
||||
this.charPositionInLine = source.getCharPositionInLine();
|
||||
if (source != null) {
|
||||
this.line = source.getLine();
|
||||
this.charPositionInLine = source.getCharPositionInLine();
|
||||
}
|
||||
}
|
||||
|
||||
public CommonToken(int type, String text) {
|
||||
|
@ -190,7 +192,7 @@ public class CommonToken implements WritableToken, Serializable {
|
|||
}
|
||||
|
||||
public CharStream getInputStream() {
|
||||
return source.getInputStream();
|
||||
return source != null ? source.getInputStream() : null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
|
@ -88,7 +88,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
|
|||
/** The token type for the current token */
|
||||
public int _type;
|
||||
|
||||
public ArrayDeque<Integer> _modeStack;
|
||||
public ArrayDeque<Integer> _modeStack = new ArrayDeque<Integer>();
|
||||
public int _mode = Lexer.DEFAULT_MODE;
|
||||
|
||||
/** You can set the text for the current token to override what is in
|
||||
|
@ -115,9 +115,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
|
|||
|
||||
_hitEOF = false;
|
||||
_mode = Lexer.DEFAULT_MODE;
|
||||
if (_modeStack != null) {
|
||||
_modeStack.clear();
|
||||
}
|
||||
_modeStack.clear();
|
||||
|
||||
getInterpreter().reset();
|
||||
}
|
||||
|
@ -184,14 +182,13 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
|
|||
|
||||
public void pushMode(int m) {
|
||||
if ( LexerATNSimulator.debug ) System.out.println("pushMode "+m);
|
||||
if ( _modeStack ==null ) _modeStack = new ArrayDeque<Integer>();
|
||||
getInterpreter().tracePushMode(m);
|
||||
_modeStack.push(_mode);
|
||||
mode(m);
|
||||
}
|
||||
|
||||
public int popMode() {
|
||||
if ( _modeStack ==null ) throw new EmptyStackException();
|
||||
if ( _modeStack.isEmpty() ) throw new EmptyStackException();
|
||||
if ( LexerATNSimulator.debug ) System.out.println("popMode back to "+ _modeStack.peek());
|
||||
getInterpreter().tracePopMode();
|
||||
mode( _modeStack.pop() );
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
package org.antlr.v4.runtime;
|
||||
|
||||
import org.antlr.v4.runtime.atn.ATNConfigSet;
|
||||
import org.antlr.v4.runtime.misc.Utils;
|
||||
|
||||
public class LexerNoViableAltException extends RecognitionException {
|
||||
/** Matching attempted at what input index? */
|
||||
|
@ -47,7 +48,19 @@ public class LexerNoViableAltException extends RecognitionException {
|
|||
this.deadEndConfigs = deadEndConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharStream getInputStream() {
|
||||
return (CharStream)super.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NoViableAltException('')";
|
||||
String symbol = "";
|
||||
if (startIndex >= 0 && startIndex < input.size()) {
|
||||
symbol = getInputStream().substring(startIndex, startIndex);
|
||||
symbol = Utils.escapeWhitespace(symbol, false);
|
||||
}
|
||||
|
||||
return "NoViableAltException('" + symbol + "')";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
[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.runtime;
|
||||
|
||||
// TODO: del or rename LexerNoViableAlt?
|
||||
public class LexerRecognitionExeption extends RuntimeException {
|
||||
/** Who threw the exception? */
|
||||
public Lexer lexer;
|
||||
|
||||
/** What is index of token/char were we looking at when the error occurred? */
|
||||
public int index;
|
||||
|
||||
/** The current char when an error occurred. For lexers. */
|
||||
public int c;
|
||||
|
||||
/** Track the line at which the error occurred in case this is
|
||||
* generated from a lexer. We need to track this since the
|
||||
* unexpected char doesn't carry the line info.
|
||||
*/
|
||||
public int line;
|
||||
|
||||
public int charPositionInLine;
|
||||
|
||||
/** Used for remote debugger deserialization */
|
||||
public LexerRecognitionExeption() {
|
||||
}
|
||||
|
||||
public LexerRecognitionExeption(Lexer lexer, CharStream input) {
|
||||
this.lexer = lexer;
|
||||
this.index = input.index();
|
||||
this.c = input.LA(1);
|
||||
if ( lexer!=null ) {
|
||||
this.line = lexer.getLine();
|
||||
this.charPositionInLine = lexer.getCharPositionInLine();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -63,7 +63,7 @@ import java.util.List;
|
|||
* satisfy the superclass interface.
|
||||
*/
|
||||
public class ParserRuleContext<Symbol> extends RuleContext {
|
||||
public static final ParserRuleContext EMPTY = new ParserRuleContext();
|
||||
public static final ParserRuleContext<?> EMPTY = new ParserRuleContext<Object>();
|
||||
|
||||
/** If we are debugging or building a parse tree for a visitor,
|
||||
* we need to track all of the tokens and rule invocations associated
|
||||
|
@ -131,17 +131,6 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
|||
this(parent, parent!=null ? parent.s : -1 /* invoking state */, stateNumber);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public int hashCode() {
|
||||
// return super.hashCode() + s;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean equals(Object o) {
|
||||
// if ( !super.equals(o) ) return false;
|
||||
// return s != ((RuleContext)o).s; // must be parsing the same location in the ATN
|
||||
// }
|
||||
|
||||
// Double dispatch methods
|
||||
|
||||
public void enterRule(ParseTreeListener<Symbol> listener) { }
|
||||
|
@ -187,7 +176,101 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
|||
|
||||
@Override
|
||||
public ParseTree getChild(int i) {
|
||||
return children!=null ? children.get(i) : null;
|
||||
return children!=null && i>=0 && i<children.size() ? children.get(i) : null;
|
||||
}
|
||||
|
||||
public <T extends ParseTree> T getChild(Class<? extends T> ctxType, int i) {
|
||||
if ( children==null || i < 0 || i >= children.size() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int j = -1; // what element have we found with ctxType?
|
||||
for (ParseTree o : children) {
|
||||
if ( ctxType.isInstance(o) ) {
|
||||
j++;
|
||||
if ( j == i ) {
|
||||
return ctxType.cast(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Token getToken(int ttype, int i) {
|
||||
if ( children==null || i < 0 || i >= children.size() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int j = -1; // what token with ttype have we found?
|
||||
for (ParseTree o : children) {
|
||||
if ( o instanceof TerminalNode<?> ) {
|
||||
TerminalNode<?> tnode = (TerminalNode<?>)o;
|
||||
if ( tnode.getSymbol() instanceof Token ) {
|
||||
Token symbol = (Token)tnode.getSymbol();
|
||||
if ( symbol.getType()==ttype ) {
|
||||
j++;
|
||||
if ( j == i ) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<? extends Token> getTokens(int ttype) {
|
||||
if ( children==null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Token> tokens = null;
|
||||
for (ParseTree o : children) {
|
||||
if ( o instanceof TerminalNode<?> ) {
|
||||
TerminalNode<?> tnode = (TerminalNode<?>)o;
|
||||
if ( tnode.getSymbol() instanceof Token ) {
|
||||
Token symbol = (Token)tnode.getSymbol();
|
||||
if ( tokens==null ) {
|
||||
tokens = new ArrayList<Token>();
|
||||
}
|
||||
tokens.add(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( tokens==null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
public <T extends ParserRuleContext<?>> T getRuleContext(Class<? extends T> ctxType, int i) {
|
||||
return getChild(ctxType, i);
|
||||
}
|
||||
|
||||
public <T extends ParserRuleContext<?>> List<? extends T> getRuleContexts(Class<? extends T> ctxType) {
|
||||
if ( children==null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<T> contexts = null;
|
||||
for (ParseTree o : children) {
|
||||
if ( ctxType.isInstance(o) ) {
|
||||
if ( contexts==null ) {
|
||||
contexts = new ArrayList<T>();
|
||||
}
|
||||
|
||||
contexts.add(ctxType.cast(o));
|
||||
}
|
||||
}
|
||||
|
||||
if ( contexts==null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return contexts;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -203,7 +286,7 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
|||
public String toString(@NotNull Recognizer<?,?> recog, RuleContext stop) {
|
||||
if ( recog==null ) return super.toString(recog, stop);
|
||||
StringBuilder buf = new StringBuilder();
|
||||
ParserRuleContext p = this;
|
||||
ParserRuleContext<?> p = this;
|
||||
buf.append("[");
|
||||
while ( p != null && p != stop ) {
|
||||
ATN atn = recog.getATN();
|
||||
|
@ -214,7 +297,7 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
|||
// ATNState invoker = atn.states.get(ctx.invokingState);
|
||||
// RuleTransition rt = (RuleTransition)invoker.transition(0);
|
||||
// buf.append(recog.getRuleNames()[rt.target.ruleIndex]);
|
||||
p = (ParserRuleContext)p.parent;
|
||||
p = (ParserRuleContext<?>)p.parent;
|
||||
}
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
|
|
|
@ -80,16 +80,6 @@ public class RuleContext implements ParseTree.RuleNode {
|
|||
|
||||
public RuleContext() {}
|
||||
|
||||
// public RuleContext(RuleContext parent) {
|
||||
// this(parent, -1);
|
||||
// }
|
||||
//
|
||||
// public RuleContext(RuleContext parent, int stateNumber) {
|
||||
// // capture state that called us as we create this context; use later for
|
||||
// // return state in closure
|
||||
// this(parent, parent != null ? parent.s : -1, stateNumber);
|
||||
// }
|
||||
|
||||
public RuleContext(RuleContext parent, int invokingState) {
|
||||
this.parent = parent;
|
||||
//if ( parent!=null ) System.out.println("invoke "+stateNumber+" from "+parent);
|
||||
|
@ -103,13 +93,6 @@ public class RuleContext implements ParseTree.RuleNode {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// int h = 0;
|
||||
// RuleContext p = this;
|
||||
// while ( p!=null ) {
|
||||
// h += p.stateNumber;
|
||||
// p = p.parent;
|
||||
// }
|
||||
// return h;
|
||||
return cachedHashCode; // works with tests; don't recompute.
|
||||
}
|
||||
|
||||
|
|
|
@ -363,6 +363,10 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
|
|||
// TODO: v3 dfa don't do this.
|
||||
break;
|
||||
}
|
||||
|
||||
// t is not updated if one of these states is reached
|
||||
assert !s.isCtxSensitive && !s.isAcceptState;
|
||||
|
||||
// if no edge, pop over to ATN interpreter, update DFA and return
|
||||
if ( s.edges == null || t >= s.edges.length || t < -1 || s.edges[t+1] == null ) {
|
||||
if ( dfa_debug && t>=0 ) System.out.println("no edge for "+parser.getTokenNames()[t]);
|
||||
|
@ -398,8 +402,10 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
|
|||
throw noViableAlt(input, outerContext, s.configset, startIndex);
|
||||
}
|
||||
s = target;
|
||||
input.consume();
|
||||
t = input.LA(1);
|
||||
if (!s.isCtxSensitive && !s.isAcceptState) {
|
||||
input.consume();
|
||||
t = input.LA(1);
|
||||
}
|
||||
}
|
||||
// if ( acceptState==null ) {
|
||||
// if ( debug ) System.out.println("!!! no viable alt in dfa");
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
*/
|
||||
package org.antlr.v4.runtime.misc;
|
||||
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -56,11 +55,6 @@ public class IntervalSet implements IntSet {
|
|||
|
||||
protected boolean readonly;
|
||||
|
||||
/** Create a set with no elements */
|
||||
public IntervalSet() {
|
||||
intervals = new ArrayList<Interval>(2); // most sets are 1 or 2 elements
|
||||
}
|
||||
|
||||
public IntervalSet(List<Interval> intervals) {
|
||||
this.intervals = intervals;
|
||||
}
|
||||
|
@ -70,6 +64,16 @@ public class IntervalSet implements IntSet {
|
|||
addAll(set);
|
||||
}
|
||||
|
||||
public IntervalSet(int... els) {
|
||||
if ( els==null ) {
|
||||
intervals = new ArrayList<Interval>(2); // most sets are 1 or 2 elements
|
||||
}
|
||||
else {
|
||||
intervals = new ArrayList<Interval>(els.length);
|
||||
for (int e : els) add(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a set with a single element, el. */
|
||||
@NotNull
|
||||
public static IntervalSet of(int a) {
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
grammar A;
|
||||
|
||||
s : q=e {System.out.println("result = "+$e.v);} ;
|
||||
s : e ;
|
||||
|
||||
e returns [int v]
|
||||
: a=e op='*' b=e {$v = $a.v * $b.v;} -> mult
|
||||
| a=e '+' b=e {$v = $a.v + $b.v;} -> add
|
||||
| INT {$v = $INT.int;}
|
||||
| '(' x=e ')' {$v = $x.v;}
|
||||
| e '++' -> inc
|
||||
| e '--'
|
||||
| ID -> anID
|
||||
e : e '*' e -> Mult
|
||||
| e '+' e -> Add
|
||||
| INT -> Int
|
||||
| '(' e ')' -> Parens
|
||||
;
|
||||
|
||||
INT : '0'..'9'+ ;
|
||||
WS : (' '|'\n')+ {skip();} ;
|
||||
INT : [0-9]+ ;
|
||||
WS : [ \t\n]+ -> skip ;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
grammar A2;
|
||||
|
||||
s : e {System.out.println($e.v);} ;
|
||||
|
||||
e returns [int v]
|
||||
: a=e '*' b=e {$v = $a.v * $b.v;} -> Mult
|
||||
| a=e '+' b=e {$v = $a.v + $b.v;} -> Add
|
||||
| INT {$v = $INT.int;} -> Int
|
||||
| '(' x=e ')' {$v = $x.v;} -> Parens
|
||||
;
|
||||
|
||||
INT : [0-9]+ ;
|
||||
WS : [ \t\n]+ -> skip ;
|
|
@ -77,6 +77,7 @@ prog : expr_or_assign* ;
|
|||
//prog : expr_or_assign prog | ;
|
||||
|
||||
expr_or_assign
|
||||
@after {System.out.println(getRuleInvocationStack());}
|
||||
: expr '++'
|
||||
| expr // match ID a, fall out, reenter, match "(i)<-x" via alt 1
|
||||
// it thinks it's same context from prog, but it's not; it's
|
||||
|
|
|
@ -27,41 +27,70 @@
|
|||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.ANTLRFileStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class TestA {
|
||||
public static class Do extends BlankAListener {
|
||||
Parser p;
|
||||
public Do(Parser p ) { this.p = p; }
|
||||
/** An example listener that uses a stack to store return values
|
||||
* so that exit methods executed on notes further up the parse tree
|
||||
* can see the results of these computations.
|
||||
*
|
||||
* Because we are using only the exit routines, the same listener works
|
||||
* as a parse listener and is a parse tree listener. It generates
|
||||
* the following output from input 3+4*5:
|
||||
|
||||
Int: 3
|
||||
Int: 4
|
||||
Int: 5
|
||||
Mult: 20
|
||||
Add: 23
|
||||
tree = (s (e (e 3) + (e (e 4) * (e 5))))
|
||||
Int: 3
|
||||
Int: 4
|
||||
Int: 5
|
||||
Mult: 20
|
||||
Add: 23
|
||||
result from tree walk = 23
|
||||
|
||||
* The key things to notice are that there are no actions
|
||||
* and the labels in the grammar--it is completely language neutral.
|
||||
* Also, I have labeled each alternative so that we get a different
|
||||
* context object. That way we get a listener method for each
|
||||
* alternative.
|
||||
*
|
||||
* Compare this to A2.g4, which adds a field to the context objects
|
||||
* by using a "returns [int v]" on the expression rule.
|
||||
*/
|
||||
public static class Do extends ABaseListener {
|
||||
Stack<Integer> results = new Stack<Integer>();
|
||||
|
||||
@Override
|
||||
public void exitEveryRule(ParserRuleContext<Token> ctx) {
|
||||
System.out.println("exit "+ctx.toStringTree(p));
|
||||
public void exit(AParser.AddContext ctx) {
|
||||
results.push( results.pop() + results.pop() );
|
||||
System.out.println("Add: " + results.peek());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterRule(AParser.eContext ctx) {
|
||||
System.out.println("enter alt w/o -> label: "+ctx.toInfoString(p));
|
||||
public void exit(AParser.IntContext ctx) {
|
||||
results.push( Integer.valueOf(ctx.INT().getText()) );
|
||||
System.out.println("Int: "+results.peek());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTerminal(ParserRuleContext<Token> ctx, Token symbol) {
|
||||
if ( ctx instanceof AParser.eContext && symbol.getType()==AParser.INT ) {
|
||||
AParser.eContext ectx = (AParser.eContext)ctx;
|
||||
ectx.v = Integer.valueOf(symbol.getText());
|
||||
}
|
||||
public void exit(AParser.MultContext ctx) {
|
||||
results.push( results.pop() * results.pop() );
|
||||
System.out.println("Mult: " + results.peek());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitRule(AParser.multContext ctx) {
|
||||
System.out.println("mult "+ctx.a.v+" * "+ctx.b.v);
|
||||
ctx.v = ctx.a.v * ctx.b.v; // repeat of what parser did--set return value
|
||||
}
|
||||
@Override
|
||||
public void exitRule(AParser.addContext ctx) {
|
||||
System.out.println("add "+ctx.a.v+" + "+ctx.b.v);
|
||||
ctx.v = ctx.a.v + ctx.b.v;
|
||||
public void exit(AParser.ParensContext ctx) {
|
||||
// result already on stack
|
||||
System.out.println("Parens: "+results.peek());
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
@ -69,14 +98,13 @@ public class TestA {
|
|||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
AParser p = new AParser(tokens);
|
||||
p.setBuildParseTree(true);
|
||||
// p.addParseListener(new Do(p));
|
||||
p.addParseListener(new Do());
|
||||
ParserRuleContext<Token> t = p.s();
|
||||
System.out.println("tree = "+t.toStringTree(p));
|
||||
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
Do doer = new Do(p);
|
||||
Do doer = new Do();
|
||||
walker.walk(doer, t);
|
||||
AParser.eContext ectx = (AParser.eContext)t.getChild(0);
|
||||
System.out.println("result from tree walk = "+ ectx.v);
|
||||
System.out.println("result from tree walk = "+ doer.results.pop());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
[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.
|
||||
*/
|
||||
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
public class TestA2 {
|
||||
/** An example listener that squirrels away a return value in a field
|
||||
* called v that we get added to the expression context objects
|
||||
* by adding a return value to rule e. This is a version of A.g4
|
||||
* that performs actions during the parse with user-defined actions.
|
||||
* AND, we pass in a listener that gets executed during the parse
|
||||
* and we use a listener on a tree walk that executes after the parse.
|
||||
* So, it affect, we compute the result of the expression 3 times.
|
||||
*/
|
||||
public static class Do extends A2BaseListener {
|
||||
A2Parser p;
|
||||
public Do(A2Parser p) { this.p = p; }
|
||||
@Override
|
||||
public void exit(A2Parser.AddContext ctx) {
|
||||
ctx.v = ctx.e(0).v + ctx.e(1).v;
|
||||
System.out.println("Add: " + ctx.v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(A2Parser.IntContext ctx) {
|
||||
ctx.v = Integer.valueOf(ctx.INT().getText());
|
||||
System.out.println("Int: "+ctx.v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(A2Parser.MultContext ctx) {
|
||||
ctx.v = ctx.e(0).v * ctx.e(1).v;
|
||||
System.out.println("Mult: " + ctx.v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(A2Parser.ParensContext ctx) {
|
||||
ctx.v = ctx.e().v;
|
||||
System.out.println("Parens: "+ctx.v);
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) throws Exception {
|
||||
A2Lexer lexer = new A2Lexer(new ANTLRFileStream(args[0]));
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
A2Parser p = new A2Parser(tokens);
|
||||
p.setBuildParseTree(true);
|
||||
p.addParseListener(new Do(p));
|
||||
ParserRuleContext<Token> t = p.s();
|
||||
System.out.println("tree = "+t.toStringTree(p));
|
||||
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
Do doer = new Do(p);
|
||||
walker.walk(doer, t);
|
||||
A2Parser.eContext ectx = (A2Parser.eContext)t.getChild(0);
|
||||
System.out.println("result from tree walk = "+ ectx.v);
|
||||
}
|
||||
}
|
|
@ -81,6 +81,11 @@
|
|||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.12</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -34,21 +34,21 @@ import org.antlr.v4.runtime.Token;
|
|||
|
||||
public interface <file.grammarName>Listener extends ParseTreeListener\<<InputSymbolType()>\> {
|
||||
<file.listenerNames:{lname |
|
||||
void enterRule(<file.parserName>.<lname>Context ctx);
|
||||
void exitRule(<file.parserName>.<lname>Context ctx);}; separator="\n">
|
||||
void enter(<file.parserName>.<lname>Context ctx);
|
||||
void exit(<file.parserName>.<lname>Context ctx);}; separator="\n">
|
||||
}
|
||||
>>
|
||||
|
||||
BlankListenerFile(file, header) ::= <<
|
||||
BaseListenerFile(file, header) ::= <<
|
||||
<header>
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public class Blank<file.grammarName>Listener implements <file.grammarName>Listener {
|
||||
public class <file.grammarName>BaseListener implements <file.grammarName>Listener {
|
||||
<file.listenerNames:{lname |
|
||||
@Override public void enterRule(<file.parserName>.<lname>Context ctx) { \}
|
||||
@Override public void exitRule(<file.parserName>.<lname>Context ctx) { \}}; separator="\n">
|
||||
@Override public void enter(<file.parserName>.<lname>Context ctx) { \}
|
||||
@Override public void exit(<file.parserName>.<lname>Context ctx) { \}}; separator="\n">
|
||||
|
||||
@Override public void enterEveryRule(ParserRuleContext\<<InputSymbolType()>\> ctx) { }
|
||||
@Override public void exitEveryRule(ParserRuleContext\<<InputSymbolType()>\> ctx) { }
|
||||
|
@ -156,7 +156,7 @@ case <index> : return <actions.(index)>;}; separator="\n">
|
|||
RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble) ::= <<
|
||||
|
||||
<ruleCtx>
|
||||
<altLabelCtxs; separator="\n">
|
||||
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
|
||||
|
||||
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
|
||||
<currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, <currentRule.startState><currentRule.args:{a | , <a.name>}>);
|
||||
|
@ -186,7 +186,7 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
|
|||
<<
|
||||
|
||||
<ruleCtx>
|
||||
<altLabelCtxs; separator="\n">
|
||||
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
|
||||
|
||||
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
|
||||
ParserRuleContext\<Token> _parentctx = _ctx;
|
||||
|
@ -214,13 +214,13 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
|
|||
}
|
||||
>>
|
||||
|
||||
CodeBlockForOuterMostAlt(c, locals, preamble, ops) ::= <<
|
||||
<if(c.altLabel)>_localctx = new <c.altLabel>Context(_localctx);<endif>
|
||||
enterOuterAlt(_localctx, <c.alt.altNum>);
|
||||
<CodeBlockForAlt(...)>
|
||||
CodeBlockForOuterMostAlt(currentOuterMostAltCodeBlock, locals, preamble, ops) ::= <<
|
||||
<if(currentOuterMostAltCodeBlock.altLabel)>_localctx = new <currentOuterMostAltCodeBlock.altLabel>Context(_localctx);<endif>
|
||||
enterOuterAlt(_localctx, <currentOuterMostAltCodeBlock.alt.altNum>);
|
||||
<CodeBlockForAlt(currentAltCodeBlock=currentOuterMostAltCodeBlock, ...)>
|
||||
>>
|
||||
|
||||
CodeBlockForAlt(c, locals, preamble, ops) ::= <<
|
||||
CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= <<
|
||||
{
|
||||
<locals; separator="\n">
|
||||
<preamble; separator="\n">
|
||||
|
@ -425,7 +425,7 @@ setState(<w.stateNumber>);
|
|||
|
||||
// ACTION STUFF
|
||||
|
||||
Action(a, chunks) ::= "<chunks>"
|
||||
Action(a, foo, chunks) ::= "<chunks>"
|
||||
|
||||
ArgAction(a, chunks) ::= "<chunks>"
|
||||
|
||||
|
@ -448,32 +448,33 @@ LexerPushModeCommand(arg) ::= "pushMode(<arg>);"
|
|||
DefaultParserSuperClass(s) ::= "Parser"
|
||||
|
||||
ActionText(t) ::= "<t.text>"
|
||||
ActionTemplate(t) ::= "<t.st>"
|
||||
ArgRef(a) ::= "_localctx.<a.name>"
|
||||
LocalRef(a) ::= "_localctx.<a.name>"
|
||||
RetValueRef(a) ::= "_localctx.<a.name>"
|
||||
QRetValueRef(a) ::= "_localctx.<a.dict>.<a.name>"
|
||||
QRetValueRef(a) ::= "<ctx(a)>.<a.dict>.<a.name>"
|
||||
/** How to translate $tokenLabel */
|
||||
TokenRef(t) ::= "_localctx.<t.name>"
|
||||
LabelRef(t) ::= "_localctx.<t.name>"
|
||||
ListLabelRef(t) ::= "_localctx.<ListLabelName(t.name)>"
|
||||
SetAttr(s,rhsChunks) ::= "_localctx.<s.name> = <rhsChunks>;"
|
||||
TokenRef(t) ::= "<ctx(t)>.<t.name>"
|
||||
LabelRef(t) ::= "<ctx(t)>.<t.name>"
|
||||
ListLabelRef(t) ::= "<ctx(t)>.<ListLabelName(t.name)>"
|
||||
SetAttr(s,rhsChunks) ::= "<ctx(s)>.<s.name> = <rhsChunks>;"
|
||||
LexerSetAttr(s,rhsChunks) ::= "_<s.name> = <rhsChunks>;" // _type etc...
|
||||
|
||||
TokenLabelType() ::= "<file.TokenLabelType; null={Token}>"
|
||||
InputSymbolType() ::= "<file.InputSymbolType; null={Token}>"
|
||||
|
||||
TokenPropertyRef_text(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getText():null)"
|
||||
TokenPropertyRef_type(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getType():0)"
|
||||
TokenPropertyRef_line(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getLine():0)"
|
||||
TokenPropertyRef_pos(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getCharPositionInLine():0)"
|
||||
TokenPropertyRef_channel(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getChannel():0)"
|
||||
TokenPropertyRef_index(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getTokenIndex():0)"
|
||||
TokenPropertyRef_int(t) ::= "(_localctx.<t.label>!=null?Integer.valueOf(_localctx.<t.label>.getText()):0)"
|
||||
TokenPropertyRef_text(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getText():null)"
|
||||
TokenPropertyRef_type(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getType():0)"
|
||||
TokenPropertyRef_line(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getLine():0)"
|
||||
TokenPropertyRef_pos(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getCharPositionInLine():0)"
|
||||
TokenPropertyRef_channel(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getChannel():0)"
|
||||
TokenPropertyRef_index(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getTokenIndex():0)"
|
||||
TokenPropertyRef_int(t) ::= "(<ctx(t)>.<t.label>!=null?Integer.valueOf(<ctx(t)>.<t.label>.getText()):0)"
|
||||
|
||||
RulePropertyRef_start(r) ::= "(_localctx.<r.label>!=null?(_localctx.<r.label>.start):null)"
|
||||
RulePropertyRef_stop(r) ::= "(_localctx.<r.label>!=null?(_localctx.<r.label>.stop):null)"
|
||||
RulePropertyRef_text(r) ::= "(_localctx.<r.label>!=null?_input.toString(_localctx.<r.label>.start,_localctx.<r.label>.stop):null)"
|
||||
RulePropertyRef_ctx(r) ::= "_localctx.<r.label>"
|
||||
RulePropertyRef_start(r) ::= "(<ctx(r)>.<r.label>!=null?(<ctx(r)>.<r.label>.start):null)"
|
||||
RulePropertyRef_stop(r) ::= "(<ctx(r)>.<r.label>!=null?(<ctx(r)>.<r.label>.stop):null)"
|
||||
RulePropertyRef_text(r) ::= "(<ctx(r)>.<r.label>!=null?_input.toString(<ctx(r)>.<r.label>.start,<ctx(r)>.<r.label>.stop):null)"
|
||||
RulePropertyRef_ctx(r) ::= "<ctx(r)>.<r.label>"
|
||||
|
||||
ThisRulePropertyRef_start(r) ::= "_localctx.start"
|
||||
ThisRulePropertyRef_stop(r) ::= "_localctx.stop"
|
||||
|
@ -484,13 +485,38 @@ NonLocalAttrRef(s) ::= "((<s.ruleName>Context)getInvokingContext(<s.ruleIndex>
|
|||
SetNonLocalAttr(s, rhsChunks) ::=
|
||||
"((<s.ruleName>Context)getInvokingContext(<s.ruleIndex>)).<s.name> = <rhsChunks>;"
|
||||
|
||||
AddToLabelList(a) ::= "_localctx.<a.listName>.add(<labelref(a.label)>);"
|
||||
AddToLabelList(a) ::= "<ctx(a.label)>.<a.listName>.add(<labelref(a.label)>);"
|
||||
|
||||
TokenDecl(t) ::= "Token <t.name>;"
|
||||
TokenDecl(t) ::= "public Token <t.name>;"
|
||||
TokenTypeDecl(t) ::= "int <t.name>;"
|
||||
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();"
|
||||
RuleContextDecl(r) ::= "<r.ctxName> <r.name>;"
|
||||
RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
|
||||
TokenListDecl(t) ::= "public List\<Token> <t.name> = new ArrayList\<Token>();"
|
||||
RuleContextDecl(r) ::= "public <r.ctxName> <r.name>;"
|
||||
RuleContextListDecl(rdecl) ::= "public List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
|
||||
|
||||
ContextTokenGetterDecl(t) ::=
|
||||
"public Token <t.name>() { return getToken(<parser.name>.<t.name>, 0); }"
|
||||
ContextTokenListGetterDecl(t) ::=
|
||||
"public List\<? extends Token> <t.name>() { return getTokens(<parser.name>.<t.name>); }"
|
||||
ContextTokenListIndexedGetterDecl(t) ::= <<
|
||||
public Token <t.name>(int i) {
|
||||
return getToken(<parser.name>.<t.name>, i);
|
||||
}
|
||||
>>
|
||||
ContextRuleGetterDecl(r) ::= <<
|
||||
public <r.ctxName> <r.name>() {
|
||||
return (<r.ctxName>)getRuleContext(<r.ctxName>.class,0);
|
||||
}
|
||||
>>
|
||||
ContextRuleListGetterDecl(r) ::= <<
|
||||
public List\<? extends <r.ctxName>\> <r.name>() {
|
||||
return (List\<<r.ctxName>\>)getRuleContexts(<r.ctxName>.class);
|
||||
}
|
||||
>>
|
||||
ContextRuleListIndexedGetterDecl(r) ::= <<
|
||||
public <r.ctxName> <r.name>(int i) {
|
||||
return (<r.ctxName>)getRuleContext(<r.ctxName>.class,i);
|
||||
}
|
||||
>>
|
||||
|
||||
LexerRuleContext() ::= "RuleContext"
|
||||
|
||||
|
@ -499,18 +525,19 @@ LexerRuleContext() ::= "RuleContext"
|
|||
*/
|
||||
RuleContextNameSuffix() ::= "Context"
|
||||
|
||||
ImplicitTokenLabel(tokenName) ::= "_t<tokenName>"
|
||||
ImplicitRuleLabel(ruleName) ::= "_r<ruleName>"
|
||||
ImplicitTokenLabel(tokenName) ::= "<tokenName>"
|
||||
ImplicitRuleLabel(ruleName) ::= "<ruleName>"
|
||||
ImplicitSetLabel(id) ::= "_tset<id>"
|
||||
ListLabelName(label) ::= "<label>_list"
|
||||
ListLabelName(label) ::= "<label>"
|
||||
|
||||
CaptureNextToken(d) ::= "<d.varName> = _input.LT(1);"
|
||||
CaptureNextTokenType(d) ::= "<d.varName> = _input.LA(1);"
|
||||
|
||||
StructDecl(s,attrs,visitorDispatchMethods,interfaces,extensionMembers,
|
||||
StructDecl(s,attrs,getters,visitorDispatchMethods,interfaces,extensionMembers,
|
||||
superClass={ParserRuleContext\<<InputSymbolType()>>}) ::= <<
|
||||
public static class <s.name> extends <superClass><if(interfaces)> implements <interfaces; separator=", "><endif> {
|
||||
<attrs:{a | public <a>;}; separator="\n">
|
||||
<attrs:{a | <a>}; separator="\n">
|
||||
<getters:{g | <g>}; separator="\n">
|
||||
<if(s.ctorAttrs)>public <s.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state) { super(parent, state); }<endif>
|
||||
public <s.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state<s.ctorAttrs:{a | , <a>}>) {
|
||||
super(parent, state);
|
||||
|
@ -528,9 +555,11 @@ public static class <s.name> extends <superClass><if(interfaces)> implements <in
|
|||
}
|
||||
>>
|
||||
|
||||
AltLabelStructDecl(s,attrs,visitorDispatchMethods) ::= <<
|
||||
public static class <s.label>Context extends <currentRule.name>Context {
|
||||
public <s.label>Context(<currentRule.name>Context ctx) { copyFrom(ctx); }
|
||||
AltLabelStructDecl(s,attrs,getters,visitorDispatchMethods) ::= <<
|
||||
public static class <s.name> extends <currentRule.name>Context {
|
||||
<attrs:{a | <a>}; separator="\n">
|
||||
<getters:{g | <g>}; separator="\n">
|
||||
public <s.name>(<currentRule.name>Context ctx) { copyFrom(ctx); }
|
||||
<visitorDispatchMethods; separator="\n">
|
||||
}
|
||||
>>
|
||||
|
@ -538,14 +567,17 @@ public static class <s.label>Context extends <currentRule.name>Context {
|
|||
VisitorDispatchMethod(method) ::= <<
|
||||
@Override
|
||||
public void <if(method.isEnter)>enter<else>exit<endif>Rule(ParseTreeListener\<<InputSymbolType()>\> listener) {
|
||||
if ( listener!=null && listener instanceof <parser.grammarName>Listener ) ((<parser.grammarName>Listener)listener).<if(method.isEnter)>enter<else>exit<endif>Rule(this);
|
||||
if ( listener instanceof <parser.grammarName>Listener ) ((<parser.grammarName>Listener)listener).<if(method.isEnter)>enter<else>exit<endif>(this);
|
||||
}
|
||||
>>
|
||||
|
||||
AttributeDecl(d) ::= "<d.decl>"
|
||||
AttributeDecl(d) ::= "public <d.decl>;"
|
||||
|
||||
/** If we don't know location of label def x, use this template */
|
||||
labelref(x) ::= "<if(!x.isLocal)>_localctx.<endif><x.name>"
|
||||
labelref(x) ::= "<if(!x.isLocal)>((<x.ctx.name>)_localctx).<endif><x.name>"
|
||||
|
||||
/** For any action chunk, what is correctly-typed context struct ptr? */
|
||||
ctx(actionChunk) ::= "((<actionChunk.ctx.name>)_localctx)"
|
||||
|
||||
// used for left-recursive rules
|
||||
recRuleDefArg() ::= "int _p"
|
||||
|
@ -563,10 +595,10 @@ pushNewRecursionContext(_localctx, RULE_<ruleName>);
|
|||
_localctx.start = _prevctx.start;
|
||||
>>
|
||||
|
||||
recRuleLabeledAltStartAction(ruleName, ctxName, label) ::= <<
|
||||
_localctx = new <ctxName>Context(new <ruleName>Context(_parentctx, _startState, _p));
|
||||
recRuleLabeledAltStartAction(ruleName, currentAltLabel, label) ::= <<
|
||||
_localctx = new <currentAltLabel>Context(new <ruleName>Context(_parentctx, _startState, _p));
|
||||
_localctx.addChild(_prevctx);
|
||||
<if(label)>_localctx.<label> = _prevctx;<endif>
|
||||
<if(label)>((<currentAltLabel>Context)_localctx).<label> = _prevctx;<endif>
|
||||
pushNewRecursionContext(_localctx, RULE_<ruleName>);
|
||||
_localctx.start = _prevctx.start;
|
||||
>>
|
||||
|
|
|
@ -58,7 +58,7 @@ import java.util.List;
|
|||
public class Tool {
|
||||
public String VERSION = "4.0-"+new Date();
|
||||
|
||||
public static enum OptionArgType { NONE, STRING }
|
||||
public static enum OptionArgType { NONE, STRING } // NONE implies boolean
|
||||
public static class Option {
|
||||
String fieldName;
|
||||
String name;
|
||||
|
@ -90,11 +90,13 @@ public class Tool {
|
|||
public String grammarEncoding = null; // use default locale's encoding
|
||||
public String msgFormat = "antlr";
|
||||
public boolean saveLexer = false;
|
||||
public boolean genListener = true;
|
||||
public boolean launch_ST_inspector = false;
|
||||
public boolean force_atn = false;
|
||||
public boolean log = false;
|
||||
public boolean verbose_dfa = false;
|
||||
public boolean no_auto_element_labels = false;
|
||||
public boolean gen_listener = true;
|
||||
public boolean gen_visitor = false;
|
||||
|
||||
public static Option[] optionDefs = {
|
||||
new Option("outputDirectory", "-o", OptionArgType.STRING, "specify output directory where all output is generated"),
|
||||
|
@ -103,10 +105,14 @@ public class Tool {
|
|||
new Option("printGrammar", "-print", "print out the grammar without actions"),
|
||||
new Option("debug", "-debug", "generate a parser that emits debugging events"),
|
||||
new Option("profile", "-profile", "generate a parser that computes profiling information"),
|
||||
new Option("generate_ATN_dot", "-atn", "generate rule augmented transition networks"),
|
||||
new Option("generate_ATN_dot", "-atn", "generate rule augmented transition network diagrams"),
|
||||
new Option("grammarEncoding", "-encoding", OptionArgType.STRING, "specify grammar file encoding; e.g., euc-jp"),
|
||||
new Option("msgFormat", "-message-format", OptionArgType.STRING, "specify output style for messages"),
|
||||
new Option("genListener", "-walker", "generate parse tree walker and listener"),
|
||||
new Option("gen_listener", "-listener", "generate parse tree listener (default)"),
|
||||
new Option("gen_listener", "-no-listener", "don't generate parse tree listener"),
|
||||
new Option("gen_visitor", "-visitor", "generate parse tree visitor"),
|
||||
new Option("gen_visitor", "-no-visitor", "don't generate parse tree visitor (default)"),
|
||||
|
||||
new Option("saveLexer", "-Xsave-lexer", "save temp lexer file created for combined grammars"),
|
||||
new Option("launch_ST_inspector", "-XdbgST", "launch StringTemplate visualizer on generated code"),
|
||||
new Option("force_atn", "-Xforce-atn", "use the ATN simulator for all predictions"),
|
||||
|
@ -182,17 +188,20 @@ public class Tool {
|
|||
}
|
||||
for (Option o : optionDefs) {
|
||||
if ( arg.equals(o.name) ) {
|
||||
String value = null;
|
||||
String argValue = null;
|
||||
if ( o.argType==OptionArgType.STRING ) {
|
||||
value = args[i];
|
||||
argValue = args[i];
|
||||
i++;
|
||||
}
|
||||
// use reflection to set field
|
||||
Class c = this.getClass();
|
||||
try {
|
||||
Field f = c.getField(o.fieldName);
|
||||
if ( value==null ) f.setBoolean(this, true);
|
||||
else f.set(this, value);
|
||||
if ( argValue==null ) {
|
||||
if ( o.fieldName.startsWith("-no-") ) f.setBoolean(this, false);
|
||||
else f.setBoolean(this, true);
|
||||
}
|
||||
else f.set(this, argValue);
|
||||
}
|
||||
catch (Exception e) {
|
||||
errMgr.toolError(ErrorType.INTERNAL_ERROR, "can't access field "+o.fieldName);
|
||||
|
|
|
@ -32,19 +32,19 @@ package org.antlr.v4.analysis;
|
|||
import org.antlr.v4.tool.ast.AltAST;
|
||||
|
||||
public class LeftRecursiveRuleAltInfo {
|
||||
public int alt;
|
||||
public int altNum; // original alt index (from 1)
|
||||
public String leftRecursiveRuleRefLabel;
|
||||
public String altLabel;
|
||||
public String altText;
|
||||
public AltAST altAST;
|
||||
public int nextPrec;
|
||||
|
||||
public LeftRecursiveRuleAltInfo(int alt, String altText) {
|
||||
this(alt, altText, null, null);
|
||||
public LeftRecursiveRuleAltInfo(int altNum, String altText) {
|
||||
this(altNum, altText, null, null);
|
||||
}
|
||||
|
||||
public LeftRecursiveRuleAltInfo(int alt, String altText, String leftRecursiveRuleRefLabel, String altLabel) {
|
||||
this.alt = alt;
|
||||
public LeftRecursiveRuleAltInfo(int altNum, String altText, String leftRecursiveRuleRefLabel, String altLabel) {
|
||||
this.altNum = altNum;
|
||||
this.altText = altText;
|
||||
this.leftRecursiveRuleRefLabel = leftRecursiveRuleRefLabel;
|
||||
this.altLabel = altLabel;
|
||||
|
|
|
@ -29,21 +29,15 @@
|
|||
|
||||
package org.antlr.v4.analysis;
|
||||
|
||||
import org.antlr.runtime.CommonToken;
|
||||
import org.antlr.runtime.TokenStream;
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.antlr.runtime.tree.Tree;
|
||||
import org.antlr.runtime.*;
|
||||
import org.antlr.runtime.tree.*;
|
||||
import org.antlr.v4.Tool;
|
||||
import org.antlr.v4.codegen.CodeGenerator;
|
||||
import org.antlr.v4.parse.GrammarASTAdaptor;
|
||||
import org.antlr.v4.parse.LeftRecursiveRuleWalker;
|
||||
import org.antlr.v4.misc.Pair;
|
||||
import org.antlr.v4.parse.*;
|
||||
import org.antlr.v4.tool.ErrorType;
|
||||
import org.antlr.v4.tool.ast.AltAST;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
import org.antlr.v4.tool.ast.GrammarASTWithOptions;
|
||||
import org.stringtemplate.v4.ST;
|
||||
import org.stringtemplate.v4.STGroup;
|
||||
import org.stringtemplate.v4.STGroupFile;
|
||||
import org.antlr.v4.tool.ast.*;
|
||||
import org.stringtemplate.v4.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -62,7 +56,8 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
public List<LeftRecursiveRuleAltInfo> otherAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
|
||||
|
||||
/** Pointer to ID node of ^(= ID element) */
|
||||
public List<GrammarAST> leftRecursiveRuleRefLabels = new ArrayList<GrammarAST>();
|
||||
public List<Pair<GrammarAST,String>> leftRecursiveRuleRefLabels =
|
||||
new ArrayList<Pair<GrammarAST,String>>();
|
||||
|
||||
public GrammarAST retvals;
|
||||
|
||||
|
@ -131,10 +126,13 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
@Override
|
||||
public void binaryAlt(AltAST altTree, int alt) {
|
||||
altTree = (AltAST)altTree.dupTree();
|
||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||
|
||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
||||
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
|
||||
if ( lrlabel!=null ) {
|
||||
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST,String>(lrlabel,altLabel));
|
||||
}
|
||||
stripAssocOptions(altTree);
|
||||
stripAltLabel(altTree);
|
||||
|
||||
|
@ -145,7 +143,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
stripAltLabel(altTree);
|
||||
String altText = text(altTree);
|
||||
altText = altText.trim();
|
||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
||||
a.nextPrec = nextPrec;
|
||||
binaryAlts.put(alt, a);
|
||||
|
@ -156,10 +153,13 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
@Override
|
||||
public void ternaryAlt(AltAST altTree, int alt) {
|
||||
altTree = (AltAST)altTree.dupTree();
|
||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||
|
||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
||||
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
|
||||
if ( lrlabel!=null ) {
|
||||
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST,String>(lrlabel,altLabel));
|
||||
}
|
||||
stripAssocOptions(altTree);
|
||||
stripAltLabel(altTree);
|
||||
|
||||
|
@ -168,7 +168,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
|
||||
String altText = text(altTree);
|
||||
altText = altText.trim();
|
||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
||||
a.nextPrec = nextPrec;
|
||||
ternaryAlts.put(alt, a);
|
||||
|
@ -195,13 +194,16 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
@Override
|
||||
public void suffixAlt(AltAST altTree, int alt) {
|
||||
altTree = (AltAST)altTree.dupTree();
|
||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||
|
||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
||||
if ( lrlabel!=null ) {
|
||||
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST,String>(lrlabel,altLabel));
|
||||
}
|
||||
stripAltLabel(altTree);
|
||||
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
|
||||
String altText = text(altTree);
|
||||
altText = altText.trim();
|
||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
||||
suffixAlts.put(alt, a);
|
||||
// System.out.println("suffixAlt " + alt + ": " + altText + ", rewrite=" + rewriteText);
|
||||
|
@ -210,17 +212,10 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
@Override
|
||||
public void otherAlt(AltAST altTree, int alt) {
|
||||
altTree = (AltAST)altTree.dupTree();
|
||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
||||
stripAltLabel(altTree);
|
||||
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
|
||||
String altText = text(altTree);
|
||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
||||
// if ( altLabel!=null ) {
|
||||
// a.startAction = codegenTemplates.getInstanceOf("recRuleReplaceContext");
|
||||
// a.startAction.add("ctxName", altLabel);
|
||||
// }
|
||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, null, altLabel);
|
||||
otherAlts.add(a);
|
||||
// System.out.println("otherAlt " + alt + ": " + altText);
|
||||
}
|
||||
|
@ -256,8 +251,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
|||
ruleST.add("primaryAlts", prefixAlts);
|
||||
ruleST.add("primaryAlts", otherAlts);
|
||||
|
||||
ruleST.add("leftRecursiveRuleRefLabels", leftRecursiveRuleRefLabels);
|
||||
|
||||
tool.log("left-recursion", ruleST.render());
|
||||
|
||||
return ruleST.render();
|
||||
|
|
|
@ -32,6 +32,7 @@ package org.antlr.v4.analysis;
|
|||
import org.antlr.runtime.*;
|
||||
import org.antlr.v4.Tool;
|
||||
import org.antlr.v4.misc.OrderedHashMap;
|
||||
import org.antlr.v4.misc.Pair;
|
||||
import org.antlr.v4.parse.*;
|
||||
import org.antlr.v4.tool.*;
|
||||
import org.antlr.v4.tool.ast.*;
|
||||
|
@ -142,12 +143,16 @@ public class LeftRecursiveRuleTransformer {
|
|||
}
|
||||
|
||||
// define labels on recursive rule refs we delete; they don't point to nodes of course
|
||||
for (GrammarAST labelNode : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
|
||||
// these are so $label in action translation works
|
||||
for (Pair<GrammarAST,String> pair : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
|
||||
GrammarAST labelNode = pair.a;
|
||||
GrammarAST labelOpNode = (GrammarAST)labelNode.getParent();
|
||||
GrammarAST elementNode = (GrammarAST)labelOpNode.getChild(1);
|
||||
LabelElementPair lp = new LabelElementPair(g, labelNode, elementNode, labelOpNode.getType());
|
||||
r.alt[1].labelDefs.map(labelNode.getText(), lp);
|
||||
}
|
||||
// copy to rule from walker
|
||||
r.leftRecursiveRuleRefLabels = leftRecursiveRuleWalker.leftRecursiveRuleRefLabels;
|
||||
|
||||
tool.log("grammar", "added: "+t.toStringTree());
|
||||
return true;
|
||||
|
@ -189,6 +194,7 @@ public class LeftRecursiveRuleTransformer {
|
|||
|
||||
*/
|
||||
public void setAltASTPointers(LeftRecursiveRule r, RuleAST t) {
|
||||
// System.out.println("RULE: "+t.toStringTree());
|
||||
BlockAST ruleBlk = (BlockAST)t.getFirstChildWithType(ANTLRParser.BLOCK);
|
||||
AltAST mainAlt = (AltAST)ruleBlk.getChild(0);
|
||||
BlockAST primaryBlk = (BlockAST)mainAlt.getChild(0);
|
||||
|
@ -196,11 +202,13 @@ public class LeftRecursiveRuleTransformer {
|
|||
for (int i = 0; i < r.recPrimaryAlts.size(); i++) {
|
||||
LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i);
|
||||
altInfo.altAST = (AltAST)primaryBlk.getChild(i);
|
||||
altInfo.altAST.leftRecursiveAltInfo = altInfo;
|
||||
// System.out.println(altInfo.altAST.toStringTree());
|
||||
}
|
||||
for (int i = 0; i < r.recOpAlts.size(); i++) {
|
||||
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
|
||||
altInfo.altAST = (AltAST)opsBlk.getChild(i);
|
||||
altInfo.altAST.leftRecursiveAltInfo = altInfo;
|
||||
// System.out.println(altInfo.altAST.toStringTree());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.antlr.runtime.ANTLRStringStream;
|
|||
import org.antlr.runtime.Token;
|
||||
import org.antlr.v4.codegen.model.RuleFunction;
|
||||
import org.antlr.v4.codegen.model.chunk.*;
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
import org.antlr.v4.parse.ActionSplitter;
|
||||
import org.antlr.v4.parse.ActionSplitterListener;
|
||||
import org.antlr.v4.tool.Attribute;
|
||||
|
@ -78,6 +79,7 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
RuleFunction rf;
|
||||
List<ActionChunk> chunks = new ArrayList<ActionChunk>();
|
||||
OutputModelFactory factory;
|
||||
StructDecl nodeContext;
|
||||
|
||||
public ActionTranslator(OutputModelFactory factory, ActionAST node) {
|
||||
this.factory = factory;
|
||||
|
@ -116,6 +118,9 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
ActionTranslator translator = new ActionTranslator(factory, node);
|
||||
translator.rf = rf;
|
||||
factory.getGrammar().tool.log("action-translator", "translate " + action);
|
||||
String altLabel = node.getAltLabel();
|
||||
if ( rf!=null ) translator.nodeContext = rf.ruleCtx;
|
||||
if ( altLabel!=null ) translator.nodeContext = rf.altLabelCtxs.get(altLabel);
|
||||
ANTLRStringStream in = new ANTLRStringStream(action);
|
||||
in.setLine(tokenWithinAction.getLine());
|
||||
in.setCharPositionInLine(tokenWithinAction.getCharPositionInLine());
|
||||
|
@ -130,27 +135,27 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
Attribute a = node.resolver.resolveToAttribute(x.getText(), node);
|
||||
if ( a!=null ) {
|
||||
switch ( a.dict.type ) {
|
||||
case ARG: chunks.add(new ArgRef(x.getText())); break;
|
||||
case RET: chunks.add(new RetValueRef(x.getText())); break;
|
||||
case LOCAL: chunks.add(new LocalRef(x.getText())); break;
|
||||
case ARG: chunks.add(new ArgRef(nodeContext,x.getText())); break;
|
||||
case RET: chunks.add(new RetValueRef(rf.ruleCtx, x.getText())); break;
|
||||
case LOCAL: chunks.add(new LocalRef(nodeContext,x.getText())); break;
|
||||
case PREDEFINED_RULE: chunks.add(getRulePropertyRef(x)); break;
|
||||
}
|
||||
}
|
||||
if ( node.resolver.resolvesToToken(x.getText(), node) ) {
|
||||
chunks.add(new TokenRef(getTokenLabel(x.getText()))); // $label
|
||||
chunks.add(new TokenRef(nodeContext,getTokenLabel(x.getText()))); // $label
|
||||
return;
|
||||
}
|
||||
if ( node.resolver.resolvesToLabel(x.getText(), node) ) {
|
||||
chunks.add(new LabelRef(getTokenLabel(x.getText()))); // $x for x=ID etc...
|
||||
chunks.add(new LabelRef(nodeContext,getTokenLabel(x.getText()))); // $x for x=ID etc...
|
||||
return;
|
||||
}
|
||||
if ( node.resolver.resolvesToListLabel(x.getText(), node) ) {
|
||||
chunks.add(new ListLabelRef(x.getText())); // $ids for ids+=ID etc...
|
||||
chunks.add(new ListLabelRef(nodeContext,x.getText())); // $ids for ids+=ID etc...
|
||||
return;
|
||||
}
|
||||
Rule r = factory.getGrammar().getRule(x.getText());
|
||||
if ( r!=null ) {
|
||||
chunks.add(new LabelRef(getRuleLabel(x.getText()))); // $r for r rule ref
|
||||
chunks.add(new LabelRef(nodeContext,getRuleLabel(x.getText()))); // $r for r rule ref
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,22 +164,22 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
gen.g.tool.log("action-translator", "setQAttr "+x+"."+y+"="+rhs);
|
||||
// x has to be current rule; just set y attr
|
||||
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
|
||||
chunks.add(new SetAttr(y.getText(), rhsChunks));
|
||||
chunks.add(new SetAttr(nodeContext,y.getText(), rhsChunks));
|
||||
}
|
||||
|
||||
public void qualifiedAttr(String expr, Token x, Token y) {
|
||||
gen.g.tool.log("action-translator", "qattr "+x+"."+y);
|
||||
Attribute a = node.resolver.resolveToAttribute(x.getText(), y.getText(), node);
|
||||
switch ( a.dict.type ) {
|
||||
case ARG: chunks.add(new ArgRef(y.getText())); break; // has to be current rule
|
||||
case ARG: chunks.add(new ArgRef(nodeContext,y.getText())); break; // has to be current rule
|
||||
case RET:
|
||||
if ( factory.getCurrentRuleFunction()!=null &&
|
||||
factory.getCurrentRuleFunction().name.equals(x.getText()) )
|
||||
{
|
||||
chunks.add(new RetValueRef(y.getText())); break;
|
||||
chunks.add(new RetValueRef(rf.ruleCtx, y.getText())); break;
|
||||
}
|
||||
else {
|
||||
chunks.add(new QRetValueRef(getRuleLabel(x.getText()), y.getText())); break;
|
||||
chunks.add(new QRetValueRef(nodeContext, getRuleLabel(x.getText()), y.getText())); break;
|
||||
}
|
||||
case PREDEFINED_RULE:
|
||||
if ( factory.getCurrentRuleFunction()!=null &&
|
||||
|
@ -195,22 +200,22 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
public void setAttr(String expr, Token x, Token rhs) {
|
||||
gen.g.tool.log("action-translator", "setAttr "+x+" "+rhs);
|
||||
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
|
||||
SetAttr s = new SetAttr(x.getText(), rhsChunks);
|
||||
if ( factory.getGrammar().isLexer() ) s = new LexerSetAttr(x.getText(), rhsChunks);
|
||||
SetAttr s = new SetAttr(nodeContext, x.getText(), rhsChunks);
|
||||
if ( factory.getGrammar().isLexer() ) s = new LexerSetAttr(nodeContext, x.getText(), rhsChunks);
|
||||
chunks.add(s);
|
||||
}
|
||||
|
||||
public void nonLocalAttr(String expr, Token x, Token y) {
|
||||
gen.g.tool.log("action-translator", "nonLocalAttr "+x+"::"+y);
|
||||
Rule r = factory.getGrammar().getRule(x.getText());
|
||||
chunks.add(new NonLocalAttrRef(x.getText(), y.getText(), r.index));
|
||||
chunks.add(new NonLocalAttrRef(nodeContext, x.getText(), y.getText(), r.index));
|
||||
}
|
||||
|
||||
public void setNonLocalAttr(String expr, Token x, Token y, Token rhs) {
|
||||
gen.g.tool.log("action-translator", "setNonLocalAttr "+x+"::"+y+"="+rhs);
|
||||
Rule r = factory.getGrammar().getRule(x.getText());
|
||||
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
|
||||
SetNonLocalAttr s = new SetNonLocalAttr(x.getText(), y.getText(), r.index, rhsChunks);
|
||||
SetNonLocalAttr s = new SetNonLocalAttr(nodeContext, x.getText(), y.getText(), r.index, rhsChunks);
|
||||
chunks.add(s);
|
||||
}
|
||||
|
||||
|
@ -218,15 +223,15 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
}
|
||||
|
||||
public void text(String text) {
|
||||
chunks.add(new ActionText(text));
|
||||
chunks.add(new ActionText(nodeContext,text));
|
||||
}
|
||||
|
||||
TokenPropertyRef getTokenPropertyRef(Token x, Token y) {
|
||||
try {
|
||||
Class c = tokenPropToModelMap.get(y.getText());
|
||||
Constructor ctor = c.getConstructor(new Class[] {String.class});
|
||||
Constructor ctor = c.getConstructor(new Class[] {StructDecl.class, String.class});
|
||||
TokenPropertyRef ref =
|
||||
(TokenPropertyRef)ctor.newInstance(getTokenLabel(x.getText()));
|
||||
(TokenPropertyRef)ctor.newInstance(nodeContext, getTokenLabel(x.getText()));
|
||||
return ref;
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -239,9 +244,9 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
RulePropertyRef getRulePropertyRef(Token prop) {
|
||||
try {
|
||||
Class c = thisRulePropToModelMap.get(prop.getText());
|
||||
Constructor ctor = c.getConstructor(new Class[] {String.class});
|
||||
Constructor ctor = c.getConstructor(new Class[] {StructDecl.class, String.class});
|
||||
RulePropertyRef ref =
|
||||
(RulePropertyRef)ctor.newInstance(getRuleLabel(prop.getText()));
|
||||
(RulePropertyRef)ctor.newInstance(nodeContext, getRuleLabel(prop.getText()));
|
||||
return ref;
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -254,9 +259,9 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
Grammar g = factory.getGrammar();
|
||||
try {
|
||||
Class c = rulePropToModelMap.get(prop.getText());
|
||||
Constructor ctor = c.getConstructor(new Class[] {String.class});
|
||||
Constructor ctor = c.getConstructor(new Class[] {StructDecl.class, String.class});
|
||||
RulePropertyRef ref =
|
||||
(RulePropertyRef)ctor.newInstance(getRuleLabel(x.getText()));
|
||||
(RulePropertyRef)ctor.newInstance(nodeContext, getRuleLabel(x.getText()));
|
||||
return ref;
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
|
|
@ -46,7 +46,7 @@ public class CodeGenPipeline {
|
|||
}
|
||||
else {
|
||||
gen.writeRecognizer(gen.generateParser());
|
||||
if ( g.tool.genListener) {
|
||||
if ( g.tool.gen_listener) {
|
||||
gen.writeListener(gen.generateListener());
|
||||
gen.writeBlankListener(gen.generateBlankListener());
|
||||
}
|
||||
|
|
|
@ -303,6 +303,7 @@ public class CodeGenerator {
|
|||
* TListener.java, if we're using the Java target.
|
||||
*/
|
||||
public String getListenerFileName() {
|
||||
assert g.name != null;
|
||||
ST extST = templates.getInstanceOf("codeFileExtension");
|
||||
String listenerName = g.name + "Listener";
|
||||
return listenerName+extST.render();
|
||||
|
@ -312,8 +313,9 @@ public class CodeGenerator {
|
|||
* such as BlankTListener.java, if we're using the Java target.
|
||||
*/
|
||||
public String getBlankListenerFileName() {
|
||||
assert g.name != null;
|
||||
ST extST = templates.getInstanceOf("codeFileExtension");
|
||||
String listenerName = "Blank" + g.name + "Listener";
|
||||
String listenerName = g.name + "BaseListener";
|
||||
return listenerName+extST.render();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,18 +29,12 @@
|
|||
|
||||
package org.antlr.v4.codegen;
|
||||
|
||||
import org.antlr.v4.codegen.model.OutputModelObject;
|
||||
import org.antlr.v4.codegen.model.RuleFunction;
|
||||
import org.antlr.v4.codegen.model.SrcOp;
|
||||
import org.antlr.v4.codegen.model.decl.CodeBlock;
|
||||
import org.antlr.v4.codegen.model.decl.Decl;
|
||||
import org.antlr.v4.runtime.misc.NotNull;
|
||||
import org.antlr.v4.runtime.misc.Nullable;
|
||||
import org.antlr.v4.tool.Alternative;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.antlr.v4.codegen.model.*;
|
||||
import org.antlr.v4.codegen.model.decl.*;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
import org.antlr.v4.tool.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/** Create output objects for elements *within* rule functions except
|
||||
* buildOutputModel() which builds outer/root model object and any
|
||||
|
@ -66,6 +60,11 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
|
|||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputModelController getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
// Convenience methods
|
||||
|
||||
@NotNull
|
||||
|
@ -87,7 +86,7 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
|
|||
public CodeBlock getCurrentBlock() { return controller.getCurrentBlock(); }
|
||||
|
||||
@Override
|
||||
public CodeBlock getCurrentOuterMostAlternativeBlock() { return controller.getCurrentOuterMostAlternativeBlock(); }
|
||||
public CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock() { return controller.getCurrentOuterMostAlternativeBlock(); }
|
||||
|
||||
@Override
|
||||
public int getCodeBlockLevel() { return controller.codeBlockLevel; }
|
||||
|
|
|
@ -72,8 +72,7 @@ public class OutputModelController {
|
|||
public Stack<RuleFunction> currentRule = new Stack<RuleFunction>();
|
||||
public Alternative currentOuterMostAlt;
|
||||
public CodeBlock currentBlock;
|
||||
public CodeBlock currentOuterMostAlternativeBlock;
|
||||
|
||||
public CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock;
|
||||
|
||||
public OutputModelController(OutputModelFactory factory) {
|
||||
this.delegate = factory;
|
||||
|
@ -121,7 +120,7 @@ public class OutputModelController {
|
|||
|
||||
public OutputModelObject buildBlankListenerOutputModel() {
|
||||
CodeGenerator gen = delegate.getGenerator();
|
||||
return new BlankListenerFile(delegate, gen.getBlankListenerFileName());
|
||||
return new BaseListenerFile(delegate, gen.getBlankListenerFileName());
|
||||
}
|
||||
|
||||
public ParserFile parserFile(String fileName) {
|
||||
|
@ -151,6 +150,7 @@ public class OutputModelController {
|
|||
RuleFunction function = rule(r);
|
||||
parser.funcs.add(function);
|
||||
pushCurrentRule(function);
|
||||
function.fillNamedActions(delegate, r);
|
||||
|
||||
if ( r instanceof LeftRecursiveRule ) {
|
||||
buildLeftRecursiveRuleFunction((LeftRecursiveRule)r,
|
||||
|
@ -214,36 +214,39 @@ public class OutputModelController {
|
|||
if ( altInfo.altLabel==null ) continue;
|
||||
ST altActionST = codegenTemplates.getInstanceOf("recRuleReplaceContext");
|
||||
altActionST.add("ctxName", altInfo.altLabel);
|
||||
Action altAction = new Action(delegate, altActionST.render());
|
||||
Action altAction =
|
||||
new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST);
|
||||
CodeBlockForAlt alt = primaryAltsCode.get(i);
|
||||
alt.insertOp(0, altAction);
|
||||
}
|
||||
|
||||
// Insert code to set ctx.stop after primary block and before op * loop
|
||||
ST setStopTokenAST = codegenTemplates.getInstanceOf("recRuleSetStopToken");
|
||||
Action setStopTokenAction = new Action(delegate, setStopTokenAST.render());
|
||||
Action setStopTokenAction = new Action(delegate, function.ruleCtx, setStopTokenAST);
|
||||
outerAlt.insertOp(1, setStopTokenAction);
|
||||
|
||||
// Insert code to set _prevctx at start of * loop
|
||||
ST setPrevCtx = codegenTemplates.getInstanceOf("recRuleSetPrevCtx");
|
||||
Action setPrevCtxAction = new Action(delegate, setPrevCtx.render());
|
||||
Action setPrevCtxAction = new Action(delegate, function.ruleCtx, setPrevCtx);
|
||||
opAltStarBlock.addIterationOp(setPrevCtxAction);
|
||||
|
||||
// Insert code in front of each op alt to create specialized ctx if there was a label
|
||||
// Insert code in front of each op alt to create specialized ctx if there was an alt label
|
||||
for (int i = 0; i < opAltsCode.size(); i++) {
|
||||
ST altActionST;
|
||||
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
|
||||
if ( altInfo.altLabel!=null ) {
|
||||
altActionST = codegenTemplates.getInstanceOf("recRuleLabeledAltStartAction");
|
||||
altActionST.add("ctxName", altInfo.altLabel);
|
||||
altActionST.add("currentAltLabel", altInfo.altLabel);
|
||||
}
|
||||
else {
|
||||
altActionST = codegenTemplates.getInstanceOf("recRuleAltStartAction");
|
||||
altActionST.add("ctxName", r.name);
|
||||
}
|
||||
altActionST.add("ruleName", r.name);
|
||||
// add label of any lr ref we deleted
|
||||
altActionST.add("label", altInfo.leftRecursiveRuleRefLabel);
|
||||
Action altAction = new Action(delegate, altActionST.render());
|
||||
Action altAction =
|
||||
new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST);
|
||||
CodeBlockForAlt alt = opAltsCode.get(i);
|
||||
alt.insertOp(0, altAction);
|
||||
}
|
||||
|
@ -312,7 +315,9 @@ public class OutputModelController {
|
|||
|
||||
public CodeBlockForAlt alternative(Alternative alt, boolean outerMost) {
|
||||
CodeBlockForAlt blk = delegate.alternative(alt, outerMost);
|
||||
if ( outerMost ) currentOuterMostAlternativeBlock = blk;
|
||||
if ( outerMost ) {
|
||||
currentOuterMostAlternativeBlock = (CodeBlockForOuterMostAlt)blk;
|
||||
}
|
||||
for (CodeGeneratorExtension ext : extensions) blk = ext.alternative(blk, outerMost);
|
||||
return blk;
|
||||
}
|
||||
|
@ -431,15 +436,13 @@ public class OutputModelController {
|
|||
return currentBlock;
|
||||
}
|
||||
|
||||
public void setCurrentOuterMostAlternativeBlock(CodeBlock currentOuterMostAlternativeBlock) {
|
||||
public void setCurrentOuterMostAlternativeBlock(CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock) {
|
||||
this.currentOuterMostAlternativeBlock = currentOuterMostAlternativeBlock;
|
||||
}
|
||||
|
||||
public CodeBlock getCurrentOuterMostAlternativeBlock() {
|
||||
public CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock() {
|
||||
return currentOuterMostAlternativeBlock;
|
||||
}
|
||||
|
||||
public int getCodeBlockLevel() { return codeBlockLevel; }
|
||||
|
||||
public int getTreeLevel() { return treeLevel; }
|
||||
}
|
||||
|
|
|
@ -32,11 +32,8 @@ package org.antlr.v4.codegen;
|
|||
import org.antlr.v4.codegen.model.*;
|
||||
import org.antlr.v4.codegen.model.decl.CodeBlock;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
import org.antlr.v4.tool.Alternative;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
import org.antlr.v4.tool.ast.BlockAST;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
import org.antlr.v4.tool.*;
|
||||
import org.antlr.v4.tool.ast.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -47,6 +44,8 @@ public interface OutputModelFactory {
|
|||
|
||||
void setController(OutputModelController controller);
|
||||
|
||||
OutputModelController getController();
|
||||
|
||||
ParserFile parserFile(String fileName);
|
||||
|
||||
Parser parser(ParserFile file);
|
||||
|
@ -109,7 +108,7 @@ public interface OutputModelFactory {
|
|||
|
||||
CodeBlock getCurrentBlock();
|
||||
|
||||
CodeBlock getCurrentOuterMostAlternativeBlock();
|
||||
CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock();
|
||||
|
||||
int getCodeBlockLevel();
|
||||
|
||||
|
|
|
@ -66,7 +66,8 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
return new LeftRecursiveRuleFunction(this, (LeftRecursiveRule)r);
|
||||
}
|
||||
else {
|
||||
return new RuleFunction(this, r);
|
||||
RuleFunction rf = new RuleFunction(this, r);
|
||||
return rf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +92,7 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
InvokeRule invokeOp = new InvokeRule(this, ID, label);
|
||||
// If no manual label and action refs as token/rule not label, we need to define implicit label
|
||||
if ( controller.needsImplicitLabel(ID, invokeOp) ) defineImplicitLabel(ID, invokeOp);
|
||||
AddToLabelList listLabelOp = getListLabelIfPresent(invokeOp, label);
|
||||
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(invokeOp, label);
|
||||
return list(invokeOp, listLabelOp);
|
||||
}
|
||||
|
||||
|
@ -99,16 +100,29 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID);
|
||||
if ( labelAST!=null ) {
|
||||
String label = labelAST.getText();
|
||||
Decl d = getTokenLabelDecl(label);
|
||||
((MatchToken)matchOp).labels.add(d);
|
||||
getCurrentRuleFunction().addContextDecl(d);
|
||||
RuleFunction rf = getCurrentRuleFunction();
|
||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||
// add Token _X and List<Token> X decls
|
||||
defineImplicitLabel(ID, matchOp); // adds _X
|
||||
TokenListDecl l = getTokenListLabelDecl(label);
|
||||
getCurrentRuleFunction().addContextDecl(l);
|
||||
rf.addContextDecl(ID.getAltLabel(), l);
|
||||
}
|
||||
else {
|
||||
Decl d = getTokenLabelDecl(label);
|
||||
((MatchToken) matchOp).labels.add(d);
|
||||
rf.addContextDecl(ID.getAltLabel(), d);
|
||||
}
|
||||
|
||||
// Decl d = getTokenLabelDecl(label);
|
||||
// ((MatchToken)matchOp).labels.add(d);
|
||||
// getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), d);
|
||||
// if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||
// TokenListDecl l = getTokenListLabelDecl(label);
|
||||
// getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), l);
|
||||
// }
|
||||
}
|
||||
if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp);
|
||||
AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, labelAST);
|
||||
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(matchOp, labelAST);
|
||||
return list(matchOp, listLabelOp);
|
||||
}
|
||||
|
||||
|
@ -129,14 +143,14 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
String label = labelAST.getText();
|
||||
Decl d = getTokenLabelDecl(label);
|
||||
((MatchSet)matchOp).labels.add(d);
|
||||
getCurrentRuleFunction().addContextDecl(d);
|
||||
getCurrentRuleFunction().addContextDecl(setAST.getAltLabel(), d);
|
||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||
TokenListDecl l = getTokenListLabelDecl(label);
|
||||
getCurrentRuleFunction().addContextDecl(l);
|
||||
getCurrentRuleFunction().addContextDecl(setAST.getAltLabel(), l);
|
||||
}
|
||||
}
|
||||
if ( controller.needsImplicitLabel(setAST, matchOp) ) defineImplicitLabel(setAST, matchOp);
|
||||
AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, labelAST);
|
||||
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(matchOp, labelAST);
|
||||
return list(matchOp, listLabelOp);
|
||||
}
|
||||
|
||||
|
@ -148,14 +162,14 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
String label = labelAST.getText();
|
||||
Decl d = getTokenLabelDecl(label);
|
||||
wild.labels.add(d);
|
||||
getCurrentRuleFunction().addContextDecl(d);
|
||||
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d);
|
||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||
TokenListDecl l = getTokenListLabelDecl(label);
|
||||
getCurrentRuleFunction().addContextDecl(l);
|
||||
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), l);
|
||||
}
|
||||
}
|
||||
if ( controller.needsImplicitLabel(ast, wild) ) defineImplicitLabel(ast, wild);
|
||||
AddToLabelList listLabelOp = getListLabelIfPresent(wild, labelAST);
|
||||
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(wild, labelAST);
|
||||
return list(wild, listLabelOp);
|
||||
}
|
||||
|
||||
|
@ -173,11 +187,11 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
String label = labelAST.getText();
|
||||
Decl d = getTokenLabelDecl(label);
|
||||
c.label = d;
|
||||
getCurrentRuleFunction().addContextDecl(d);
|
||||
getCurrentRuleFunction().addContextDecl(labelAST.getAltLabel(), d);
|
||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||
String listLabel = gen.target.getListLabel(label);
|
||||
TokenListDecl l = new TokenListDecl(this, listLabel);
|
||||
getCurrentRuleFunction().addContextDecl(l);
|
||||
getCurrentRuleFunction().addContextDecl(labelAST.getAltLabel(), l);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,10 +302,10 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
|||
}
|
||||
op.getLabels().add(d);
|
||||
// all labels must be in scope struct in case we exec action out of context
|
||||
getCurrentRuleFunction().addContextDecl(d);
|
||||
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d);
|
||||
}
|
||||
|
||||
public AddToLabelList getListLabelIfPresent(LabeledOp op, GrammarAST label) {
|
||||
public AddToLabelList getAddToListOpIfListLabelPresent(LabeledOp op, GrammarAST label) {
|
||||
AddToLabelList labelOp = null;
|
||||
if ( label!=null && label.parent.getType()==ANTLRParser.PLUS_ASSIGN ) {
|
||||
String listLabel = gen.target.getListLabel(label.getText());
|
||||
|
|
|
@ -84,8 +84,10 @@ alternative returns [CodeBlockForAlt altCodeBlock, List<SrcOp> ops]
|
|||
alt[boolean outerMost] returns [CodeBlockForAlt altCodeBlock, List<SrcOp> ops]
|
||||
: {
|
||||
// set alt if outer ALT only (the only ones with alt field set to Alternative object)
|
||||
if ( outerMost ) controller.setCurrentOuterMostAlt(((AltAST)$start).alt);
|
||||
List<SrcOp> elems = new ArrayList<SrcOp>();
|
||||
AltAST altAST = (AltAST)retval.start;
|
||||
if ( outerMost ) controller.setCurrentOuterMostAlt(altAST.alt);
|
||||
List<SrcOp> elems = new ArrayList<SrcOp>();
|
||||
// TODO: shouldn't we pass $start to controller.alternative()?
|
||||
$altCodeBlock = controller.alternative(controller.getCurrentOuterMostAlt(), outerMost);
|
||||
$altCodeBlock.ops = $ops = elems;
|
||||
controller.setCurrentBlock($altCodeBlock);
|
||||
|
|
|
@ -30,16 +30,14 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.runtime.CommonToken;
|
||||
import org.antlr.v4.codegen.ActionTranslator;
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
||||
import org.antlr.v4.codegen.model.chunk.ActionText;
|
||||
import org.antlr.v4.codegen.*;
|
||||
import org.antlr.v4.codegen.model.chunk.*;
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
import org.antlr.v4.tool.ast.ActionAST;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
import org.antlr.v4.tool.ast.*;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/** */
|
||||
public class Action extends RuleElement {
|
||||
|
@ -57,7 +55,7 @@ public class Action extends RuleElement {
|
|||
//System.out.println("actions="+chunks);
|
||||
}
|
||||
|
||||
public Action(OutputModelFactory factory, String action) {
|
||||
public Action(OutputModelFactory factory, StructDecl ctx, String action) {
|
||||
super(factory,null);
|
||||
ActionAST ast = new ActionAST(new CommonToken(ANTLRParser.ACTION, action));
|
||||
RuleFunction rf = factory.getCurrentRuleFunction();
|
||||
|
@ -67,7 +65,14 @@ public class Action extends RuleElement {
|
|||
}
|
||||
else {
|
||||
chunks = new ArrayList<ActionChunk>();
|
||||
chunks.add(new ActionText(action));
|
||||
chunks.add(new ActionText(ctx, action));
|
||||
}
|
||||
}
|
||||
|
||||
public Action(OutputModelFactory factory, StructDecl ctx, ST actionST) {
|
||||
super(factory, null);
|
||||
chunks = new ArrayList<ActionChunk>();
|
||||
chunks.add(new ActionTemplate(ctx, actionST));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
public class BaseListenerFile extends ListenerFile {
|
||||
public BaseListenerFile(OutputModelFactory factory, String fileName) {
|
||||
super(factory, fileName);
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
public class BlankListenerFile extends ListenerFile {
|
||||
public BlankListenerFile(OutputModelFactory factory, String fileName) {
|
||||
super(factory, fileName);
|
||||
}
|
||||
}
|
|
@ -34,5 +34,8 @@ import org.antlr.v4.codegen.model.decl.CodeBlock;
|
|||
|
||||
/** Contains Rewrite block (usually as last op) */
|
||||
public class CodeBlockForAlt extends CodeBlock {
|
||||
public CodeBlockForAlt(OutputModelFactory factory) { super(factory); }
|
||||
|
||||
public CodeBlockForAlt(OutputModelFactory factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,19 +29,14 @@
|
|||
|
||||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.ActionTranslator;
|
||||
import org.antlr.v4.codegen.CodeGenerator;
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.*;
|
||||
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
||||
import org.antlr.v4.codegen.model.decl.Decl;
|
||||
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
|
||||
import org.antlr.v4.codegen.model.decl.RuleContextListDecl;
|
||||
import org.antlr.v4.codegen.model.decl.*;
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
import org.antlr.v4.runtime.atn.RuleTransition;
|
||||
import org.antlr.v4.runtime.misc.OrderedHashSet;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
import org.antlr.v4.tool.ast.ActionAST;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
import org.antlr.v4.tool.ast.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -72,11 +67,11 @@ public class InvokeRule extends RuleElement implements LabeledOp {
|
|||
String label = labelAST.getText();
|
||||
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
||||
labels.add(d);
|
||||
rf.addContextDecl(d);
|
||||
rf.addContextDecl(ast.getAltLabel(), d);
|
||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||
String listLabel = gen.target.getListLabel(label);
|
||||
RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, ctxName);
|
||||
rf.addContextDecl(l);
|
||||
rf.addContextDecl(ast.getAltLabel(), l);
|
||||
}
|
||||
}
|
||||
if ( ast.getChildCount()>0 ) {
|
||||
|
@ -89,15 +84,8 @@ public class InvokeRule extends RuleElement implements LabeledOp {
|
|||
String label = gen.target.getImplicitRuleLabel(ast.getText());
|
||||
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
||||
labels.add(d);
|
||||
rf.addContextDecl(d);
|
||||
rf.addContextDecl(ast.getAltLabel(), d);
|
||||
}
|
||||
|
||||
// LinearApproximator approx = new LinearApproximator(factory.g, ATN.INVALID_DECISION_NUMBER);
|
||||
// RuleTransition call = (RuleTransition)ast.atnState.transition(0);
|
||||
// IntervalSet fset = approx.FIRST(call.followState);
|
||||
// System.out.println("follow rule ref "+name+"="+fset);
|
||||
// follow = factory.createFollowBitSet(ast, fset);
|
||||
// factory.defineBitSet(follow);
|
||||
}
|
||||
|
||||
public List<Decl> getLabels() {
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.antlr.v4.codegen.model.decl.Decl;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
/** */
|
||||
/** All the rule elements we can label like tokens, rules, sets, wildcard. */
|
||||
public interface LabeledOp {
|
||||
public List<Decl> getLabels();
|
||||
}
|
||||
|
|
|
@ -29,34 +29,35 @@
|
|||
|
||||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.CodeGenerator;
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
|
||||
import org.antlr.v4.tool.LabelElementPair;
|
||||
import org.antlr.v4.tool.LabelType;
|
||||
import org.antlr.v4.tool.LeftRecursiveRule;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
import org.stringtemplate.v4.misc.MultiMap;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import org.antlr.v4.codegen.*;
|
||||
import org.antlr.v4.codegen.model.decl.*;
|
||||
import org.antlr.v4.misc.Pair;
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
import org.antlr.v4.tool.*;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
|
||||
public class LeftRecursiveRuleFunction extends RuleFunction {
|
||||
public LeftRecursiveRuleFunction(OutputModelFactory factory, LeftRecursiveRule r) {
|
||||
super(factory, r);
|
||||
|
||||
// Since we delete x=lr, we have to manually add decls for all labels on left-recur refs
|
||||
CodeGenerator gen = factory.getGenerator();
|
||||
MultiMap<String,LabelElementPair> labelDefs = r.alt[1].labelDefs;
|
||||
Set<String> labels = labelDefs.keySet();
|
||||
for (Iterator<String> iterator = labels.iterator(); iterator.hasNext(); ) {
|
||||
String label = iterator.next();
|
||||
LabelElementPair l = r.getAnyLabelDef(label);
|
||||
Rule targetRule = factory.getGrammar().getRule(l.element.getText());
|
||||
if ( l.type == LabelType.RULE_LABEL ) {
|
||||
// Since we delete x=lr, we have to manually add decls for all labels
|
||||
// on left-recur refs to proper structs
|
||||
for (Pair<GrammarAST,String> pair : r.leftRecursiveRuleRefLabels) {
|
||||
GrammarAST idAST = pair.a;
|
||||
String altLabel = pair.b;
|
||||
String label = idAST.getText();
|
||||
GrammarAST rrefAST = (GrammarAST)idAST.getParent().getChild(1);
|
||||
if ( rrefAST.getType() == ANTLRParser.RULE_REF ) {
|
||||
Rule targetRule = factory.getGrammar().getRule(rrefAST.getText());
|
||||
String ctxName = gen.target.getRuleFunctionContextStructName(targetRule);
|
||||
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
||||
addContextDecl(d);
|
||||
StructDecl struct = ruleCtx;
|
||||
if ( altLabelCtxs!=null ) {
|
||||
StructDecl s = altLabelCtxs.get(altLabel);
|
||||
if ( s!=null ) struct = s; // if alt label, use subctx
|
||||
}
|
||||
struct.addDecl(d); // stick in overall rule's ctx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
import org.antlr.v4.tool.ast.ActionAST;
|
||||
import org.antlr.v4.misc.Triple;
|
||||
import org.antlr.v4.tool.*;
|
||||
import org.antlr.v4.tool.ast.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/** A model object representing a parse tree listener file.
|
||||
* These are the rules specific events triggered by a parse tree visitor.
|
||||
|
@ -26,11 +24,11 @@ public class ListenerFile extends OutputFile {
|
|||
parserName = g.getRecognizerName();
|
||||
grammarName = g.name;
|
||||
for (Rule r : g.rules.values()) {
|
||||
List<String> labels = r.getAltLabels();
|
||||
List<Triple<Integer,AltAST,String>> labels = r.getAltLabels();
|
||||
listenerNames.add(r.name);
|
||||
if ( labels!=null ) {
|
||||
for (String label : labels) {
|
||||
listenerNames.add(label);
|
||||
for (Triple<Integer,AltAST,String> pair : labels) {
|
||||
listenerNames.add(pair.c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,9 @@
|
|||
|
||||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.CodeGenerator;
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
||||
import org.antlr.v4.codegen.model.chunk.ActionText;
|
||||
import org.antlr.v4.codegen.model.chunk.DefaultParserSuperClass;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
import org.antlr.v4.codegen.*;
|
||||
import org.antlr.v4.codegen.model.chunk.*;
|
||||
import org.antlr.v4.tool.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -86,7 +82,7 @@ public class Parser extends OutputModelObject {
|
|||
rules = g.rules.values();
|
||||
atn = new SerializedATN(factory, g.atn);
|
||||
if (g.getOptionString("superClass") != null) {
|
||||
superclass = new ActionText(g.getOptionString("superClass"));
|
||||
superclass = new ActionText(null, g.getOptionString("superClass"));
|
||||
} else {
|
||||
superclass = new DefaultParserSuperClass();
|
||||
}
|
||||
|
|
|
@ -30,18 +30,22 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.model.decl.AltLabelStructDecl;
|
||||
import org.antlr.v4.codegen.model.decl.Decl;
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
import org.antlr.v4.codegen.model.decl.*;
|
||||
import org.antlr.v4.misc.FrequencySet;
|
||||
import org.antlr.v4.misc.Triple;
|
||||
import org.antlr.v4.misc.Utils;
|
||||
import org.antlr.v4.runtime.atn.ATNState;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
import org.antlr.v4.runtime.misc.OrderedHashSet;
|
||||
import org.antlr.v4.tool.Attribute;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
import org.antlr.v4.tool.ast.AltAST;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.antlr.v4.parse.ANTLRParser.*;
|
||||
|
||||
/** */
|
||||
public class RuleFunction extends OutputModelObject {
|
||||
public String name;
|
||||
|
@ -54,12 +58,13 @@ public class RuleFunction extends OutputModelObject {
|
|||
public int index;
|
||||
public Collection<Attribute> args = null;
|
||||
public Rule rule;
|
||||
public AltLabelStructDecl[] altToContext;
|
||||
|
||||
@ModelElement public List<SrcOp> code;
|
||||
@ModelElement public OrderedHashSet<Decl> locals; // TODO: move into ctx?
|
||||
@ModelElement public StructDecl ruleCtx;
|
||||
@ModelElement public Set<AltLabelStructDecl> altLabelCtxs;
|
||||
@ModelElement public Map<String, Action> namedActions;
|
||||
@ModelElement public Map<String,AltLabelStructDecl> altLabelCtxs;
|
||||
@ModelElement public Map<String,Action> namedActions;
|
||||
@ModelElement public Action finallyAction;
|
||||
@ModelElement public List<SrcOp> postamble;
|
||||
|
||||
|
@ -76,12 +81,33 @@ public class RuleFunction extends OutputModelObject {
|
|||
index = r.index;
|
||||
|
||||
ruleCtx = new StructDecl(factory, r);
|
||||
altToContext = new AltLabelStructDecl[r.getOriginalNumberOfAlts()+1];
|
||||
|
||||
List<String> labels = r.getAltLabels();
|
||||
// Add ctx labels for elements in alts with no -> label
|
||||
if ( !factory.getGrammar().tool.no_auto_element_labels ) {
|
||||
List<AltAST> altsNoLabels = r.getUnlabeledAltASTs();
|
||||
if ( altsNoLabels!=null ) {
|
||||
Set<Decl> decls = getDeclsForAllElements(altsNoLabels);
|
||||
// we know to put in rule ctx, so do it directly
|
||||
for (Decl d : decls) ruleCtx.addDecl(d);
|
||||
}
|
||||
}
|
||||
|
||||
// make structs for -> labeled alts, define ctx labels for elements
|
||||
altLabelCtxs = new HashMap<String,AltLabelStructDecl>();
|
||||
List<Triple<Integer,AltAST,String>> labels = r.getAltLabels();
|
||||
if ( labels!=null ) {
|
||||
altLabelCtxs = new HashSet<AltLabelStructDecl>();
|
||||
for (String label : labels) {
|
||||
altLabelCtxs.add(new AltLabelStructDecl(factory, r, label));
|
||||
for (Triple<Integer,AltAST,String> pair : labels) {
|
||||
Integer altNum = pair.a;
|
||||
AltAST altAST = pair.b;
|
||||
String label = pair.c;
|
||||
altToContext[altNum] = new AltLabelStructDecl(factory, r, altNum, label);
|
||||
altLabelCtxs.put(label, altToContext[altNum]);
|
||||
if ( !factory.getGrammar().tool.no_auto_element_labels ) {
|
||||
Set<Decl> decls = getDeclsForAltElements(altAST);
|
||||
// we know which ctx to put in, so do it directly
|
||||
for (Decl d : decls) altToContext[altNum].addDecl(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,13 +128,100 @@ public class RuleFunction extends OutputModelObject {
|
|||
exceptions = Utils.nodesToStrings(r.exceptionActions);
|
||||
if ( r.finallyAction!=null ) finallyAction = new Action(factory, r.finallyAction);
|
||||
|
||||
startState = factory.getGrammar().atn.ruleToStartState[r.index];
|
||||
}
|
||||
|
||||
public void fillNamedActions(OutputModelFactory factory, Rule r) {
|
||||
namedActions = new HashMap<String, Action>();
|
||||
for (String name : r.namedActions.keySet()) {
|
||||
GrammarAST ast = r.namedActions.get(name);
|
||||
namedActions.put(name, new Action(factory, ast));
|
||||
}
|
||||
}
|
||||
|
||||
startState = factory.getGrammar().atn.ruleToStartState[r.index];
|
||||
/** for all alts, find which ref X or r in way which needs List
|
||||
Must see across alts. If any alt needs X or r as list, then
|
||||
define as list.
|
||||
*/
|
||||
public Set<Decl> getDeclsForAllElements(List<AltAST> altASTs) {
|
||||
Set<String> needsList = new HashSet<String>();
|
||||
List<GrammarAST> allRefs = new ArrayList<GrammarAST>();
|
||||
// for (Alternative a :alts) {
|
||||
for (AltAST ast : altASTs) {
|
||||
IntervalSet reftypes = new IntervalSet(RULE_REF, TOKEN_REF);
|
||||
List<GrammarAST> refs = ast.getNodesWithType(reftypes);
|
||||
FrequencySet<String> altFreq = new FrequencySet<String>();
|
||||
for (GrammarAST t : refs) {
|
||||
String refLabelName = t.getText();
|
||||
altFreq.add(refLabelName);
|
||||
allRefs.add(t);
|
||||
}
|
||||
for (GrammarAST t : refs) {
|
||||
String refLabelName = t.getText();
|
||||
if ( altFreq.count(t.getText())>1 ) needsList.add(refLabelName);
|
||||
}
|
||||
}
|
||||
Set<Decl> decls = new HashSet<Decl>();
|
||||
for (GrammarAST t : allRefs) {
|
||||
String refLabelName = t.getText();
|
||||
List<Decl> d = getDeclForAltElement(t,
|
||||
refLabelName,
|
||||
needsList.contains(refLabelName));
|
||||
decls.addAll(d);
|
||||
}
|
||||
return decls;
|
||||
}
|
||||
|
||||
/** Get list of decls for token/rule refs.
|
||||
* Single ref X becomes X() getter
|
||||
* Multiple refs to X becomes List X() method, X(int i) method.
|
||||
* Ref X in a loop then we get List X(), X(int i)
|
||||
*
|
||||
* Does not gen labels for literals like '+', 'begin', ';', ...
|
||||
*/
|
||||
public Set<Decl> getDeclsForAltElements(AltAST altAST) {
|
||||
IntervalSet reftypes = new IntervalSet(RULE_REF,
|
||||
TOKEN_REF);
|
||||
List<GrammarAST> refs = altAST.getNodesWithType(reftypes);
|
||||
Set<Decl> decls = new HashSet<Decl>();
|
||||
FrequencySet<String> freq = new FrequencySet<String>();
|
||||
for (GrammarAST t : refs) freq.add(t.getText());
|
||||
for (GrammarAST t : refs) {
|
||||
String refLabelName = t.getText();
|
||||
boolean inLoop = t.hasAncestor(CLOSURE) || t.hasAncestor(POSITIVE_CLOSURE);
|
||||
boolean multipleRefs = freq.count(refLabelName)>1;
|
||||
boolean needList = inLoop || multipleRefs;
|
||||
// System.out.println(altAST.toStringTree()+" "+t+" inLoop? "+inLoop);
|
||||
List<Decl> d = getDeclForAltElement(t, refLabelName, needList);
|
||||
decls.addAll(d);
|
||||
}
|
||||
return decls;
|
||||
}
|
||||
|
||||
public List<Decl> getDeclForAltElement(GrammarAST t, String refLabelName, boolean needList) {
|
||||
List<Decl> decls = new ArrayList<Decl>();
|
||||
if ( t.getType()==RULE_REF ) {
|
||||
Rule rref = factory.getGrammar().getRule(t.getText());
|
||||
String ctxName = factory.getGenerator().target
|
||||
.getRuleFunctionContextStructName(rref);
|
||||
if ( needList ) {
|
||||
decls.add( new ContextRuleListGetterDecl(factory, refLabelName, ctxName) );
|
||||
decls.add( new ContextRuleListIndexedGetterDecl(factory, refLabelName, ctxName) );
|
||||
}
|
||||
else {
|
||||
decls.add( new ContextRuleGetterDecl(factory, refLabelName, ctxName) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( needList ) {
|
||||
decls.add( new ContextTokenListGetterDecl(factory, refLabelName) );
|
||||
decls.add( new ContextTokenListIndexedGetterDecl(factory, refLabelName) );
|
||||
}
|
||||
else {
|
||||
decls.add( new ContextTokenGetterDecl(factory, refLabelName) );
|
||||
}
|
||||
}
|
||||
return decls;
|
||||
}
|
||||
|
||||
/** Add local var decl */
|
||||
|
@ -118,8 +231,19 @@ public class RuleFunction extends OutputModelObject {
|
|||
d.isLocal = true;
|
||||
}
|
||||
|
||||
/** Add decl to struct ctx */
|
||||
public void addContextDecl(Decl d) {
|
||||
ruleCtx.addDecl(d);
|
||||
/** Add decl to struct ctx for rule or alt if labeled */
|
||||
public void addContextDecl(String altLabel, Decl d) {
|
||||
CodeBlockForOuterMostAlt alt = d.getOuterMostAltCodeBlock();
|
||||
// if we found code blk and might be alt label, try to add to that label ctx
|
||||
if ( alt!=null && altLabelCtxs!=null ) {
|
||||
// System.out.println(d.name+" lives in alt "+alt.alt.altNum);
|
||||
AltLabelStructDecl altCtx = altLabelCtxs.get(altLabel);
|
||||
if ( altCtx!=null ) { // we have an alt ctx
|
||||
// System.out.println("ctx is "+ altCtx.name);
|
||||
altCtx.addDecl(d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ruleCtx.addDecl(d); // stick in overall rule's ctx
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.model.decl.CodeBlock;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
|
||||
/** */
|
||||
|
@ -39,17 +40,42 @@ public abstract class SrcOp extends OutputModelObject {
|
|||
|
||||
/** All operations know in which block they live:
|
||||
*
|
||||
* CodeBlockForAlt, TreeRewrite, STRewrite
|
||||
* CodeBlock, CodeBlockForAlt
|
||||
*
|
||||
* Templates might need to know block nesting level or find
|
||||
* a specific declaration, etc...
|
||||
*/
|
||||
public SrcOp enclosingBlock;
|
||||
public CodeBlock enclosingBlock;
|
||||
|
||||
public RuleFunction enclosingRuleRunction;
|
||||
|
||||
public SrcOp(OutputModelFactory factory) { this(factory,null); }
|
||||
public SrcOp(OutputModelFactory factory, GrammarAST ast) {
|
||||
super(factory,ast);
|
||||
if ( ast!=null ) uniqueID = ast.token.getTokenIndex();
|
||||
enclosingBlock = factory.getCurrentBlock();
|
||||
enclosingRuleRunction = factory.getCurrentRuleFunction();
|
||||
}
|
||||
|
||||
/** Walk upwards in model tree, looking for outer alt's code block */
|
||||
public CodeBlockForOuterMostAlt getOuterMostAltCodeBlock() {
|
||||
if ( this instanceof CodeBlockForOuterMostAlt ) {
|
||||
return (CodeBlockForOuterMostAlt)this;
|
||||
}
|
||||
CodeBlock p = enclosingBlock;
|
||||
while ( p!=null ) {
|
||||
if ( p instanceof CodeBlockForOuterMostAlt ) {
|
||||
return (CodeBlockForOuterMostAlt)p;
|
||||
}
|
||||
p = p.enclosingBlock;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Return label alt or return name of rule */
|
||||
public String getContextName() {
|
||||
CodeBlockForOuterMostAlt alt = getOuterMostAltCodeBlock();
|
||||
if ( alt!=null && alt.altLabel!=null ) return alt.altLabel;
|
||||
return enclosingRuleRunction.name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package org.antlr.v4.codegen.model;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.misc.Triple;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
import org.antlr.v4.tool.ast.AltAST;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -12,7 +14,7 @@ public class VisitorDispatchMethod extends OutputModelObject {
|
|||
public VisitorDispatchMethod(OutputModelFactory factory, Rule r, boolean isEnter) {
|
||||
super(factory);
|
||||
this.isEnter = isEnter;
|
||||
List<String> label = r.getAltLabels();
|
||||
if ( label!=null ) listenerName = label.get(0);
|
||||
List<Triple<Integer,AltAST,String>> label = r.getAltLabels();
|
||||
if ( label!=null ) listenerName = label.get(0).c;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,14 @@
|
|||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.OutputModelObject;
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class ActionChunk extends OutputModelObject {
|
||||
/** Where is the ctx that defines attrs,labels etc... for this action? */
|
||||
public StructDecl ctx;
|
||||
|
||||
public ActionChunk(StructDecl ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
public class ActionTemplate extends ActionChunk {
|
||||
public ST st;
|
||||
|
||||
public ActionTemplate(StructDecl ctx, ST st) {
|
||||
super(ctx);
|
||||
this.st = st;
|
||||
}
|
||||
}
|
|
@ -29,11 +29,14 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class ActionText extends ActionChunk {
|
||||
public String text;
|
||||
|
||||
public ActionText(String text) {
|
||||
public ActionText(StructDecl ctx, String text) {
|
||||
super(ctx);
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class ArgRef extends LocalRef {
|
||||
public ArgRef(String name) {
|
||||
super(name);
|
||||
public ArgRef(StructDecl ctx, String name) {
|
||||
super(ctx, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,4 +30,5 @@
|
|||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
public class DefaultParserSuperClass extends ActionChunk {
|
||||
public DefaultParserSuperClass() { super(null); }
|
||||
}
|
||||
|
|
|
@ -29,10 +29,13 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
public class LabelRef extends ActionChunk {
|
||||
public String name;
|
||||
|
||||
public LabelRef(String name) {
|
||||
public LabelRef(StructDecl ctx, String name) {
|
||||
super(ctx);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,12 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LexerSetAttr extends SetAttr {
|
||||
public LexerSetAttr(String name, List<ActionChunk> rhsChunks) {
|
||||
super(name, rhsChunks);
|
||||
public LexerSetAttr(StructDecl ctx, String name, List<ActionChunk> rhsChunks) {
|
||||
super(ctx, name, rhsChunks);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
public class ListLabelRef extends LabelRef {
|
||||
public ListLabelRef(String name) { super(name); }
|
||||
public ListLabelRef(StructDecl ctx, String name) { super(ctx, name); }
|
||||
}
|
||||
|
|
|
@ -29,10 +29,13 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
public class LocalRef extends ActionChunk {
|
||||
public String name;
|
||||
|
||||
public LocalRef(String name) {
|
||||
public LocalRef(StructDecl ctx, String name) {
|
||||
super(ctx);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,12 +29,15 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
public class NonLocalAttrRef extends ActionChunk {
|
||||
public String ruleName;
|
||||
public String name;
|
||||
public int ruleIndex;
|
||||
|
||||
public NonLocalAttrRef(String ruleName, String name, int ruleIndex) {
|
||||
public NonLocalAttrRef(StructDecl ctx, String ruleName, String name, int ruleIndex) {
|
||||
super(ctx);
|
||||
this.name = name;
|
||||
this.ruleName = ruleName;
|
||||
this.ruleIndex = ruleIndex;
|
||||
|
|
|
@ -29,11 +29,13 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class QRetValueRef extends RetValueRef {
|
||||
public String dict;
|
||||
public QRetValueRef(String dict, String name) {
|
||||
super(name);
|
||||
public QRetValueRef(StructDecl ctx, String dict, String name) {
|
||||
super(ctx,name);
|
||||
this.dict = dict;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class RetValueRef extends ActionChunk {
|
||||
public String name;
|
||||
|
||||
public RetValueRef(String name) {
|
||||
public RetValueRef(StructDecl ctx, String name) {
|
||||
super(ctx);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class RulePropertyRef extends ActionChunk {
|
||||
public String label;
|
||||
|
||||
public RulePropertyRef(String label) {
|
||||
public RulePropertyRef(StructDecl ctx, String label) {
|
||||
super(ctx);
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,10 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
public class RulePropertyRef_ctx extends RulePropertyRef {
|
||||
public RulePropertyRef_ctx(String label) {
|
||||
super(label);
|
||||
public RulePropertyRef_ctx(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class RulePropertyRef_start extends RulePropertyRef {
|
||||
public RulePropertyRef_start(String label) {
|
||||
super(label);
|
||||
public RulePropertyRef_start(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class RulePropertyRef_stop extends RulePropertyRef {
|
||||
public RulePropertyRef_stop(String label) {
|
||||
super(label);
|
||||
public RulePropertyRef_stop(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class RulePropertyRef_text extends RulePropertyRef {
|
||||
public RulePropertyRef_text(String label) {
|
||||
super(label);
|
||||
public RulePropertyRef_text(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.ModelElement;
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -38,17 +39,9 @@ public class SetAttr extends ActionChunk {
|
|||
public String name;
|
||||
@ModelElement public List<ActionChunk> rhsChunks;
|
||||
|
||||
public SetAttr(String name, List<ActionChunk> rhsChunks) {
|
||||
public SetAttr(StructDecl ctx, String name, List<ActionChunk> rhsChunks) {
|
||||
super(ctx);
|
||||
this.name = name;
|
||||
this.rhsChunks = rhsChunks;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public List<String> getChildren() {
|
||||
// final List<String> sup = super.getChildren();
|
||||
// return new ArrayList<String>() {{
|
||||
// if ( sup!=null ) addAll(sup);
|
||||
// add("rhsChunks");
|
||||
// }};
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -29,16 +29,19 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SetNonLocalAttr extends SetAttr {
|
||||
public String ruleName;
|
||||
public int ruleIndex;
|
||||
|
||||
public SetNonLocalAttr(String ruleName, String name, int ruleIndex,
|
||||
public SetNonLocalAttr(StructDecl ctx,
|
||||
String ruleName, String name, int ruleIndex,
|
||||
List<ActionChunk> rhsChunks)
|
||||
{
|
||||
super(name, rhsChunks);
|
||||
super(ctx, name, rhsChunks);
|
||||
this.ruleName = ruleName;
|
||||
this.ruleIndex = ruleIndex;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,10 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
public class ThisRulePropertyRef_ctx extends RulePropertyRef {
|
||||
public ThisRulePropertyRef_ctx(String label) {
|
||||
super(label);
|
||||
public ThisRulePropertyRef_ctx(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class ThisRulePropertyRef_start extends RulePropertyRef {
|
||||
public ThisRulePropertyRef_start(String label) {
|
||||
super(label);
|
||||
public ThisRulePropertyRef_start(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class ThisRulePropertyRef_stop extends RulePropertyRef {
|
||||
public ThisRulePropertyRef_stop(String label) {
|
||||
super(label);
|
||||
public ThisRulePropertyRef_stop(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class ThisRulePropertyRef_text extends RulePropertyRef {
|
||||
public ThisRulePropertyRef_text(String label) {
|
||||
super(label);
|
||||
public ThisRulePropertyRef_text(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef extends ActionChunk {
|
||||
public String label;
|
||||
|
||||
public TokenPropertyRef(String label) {
|
||||
public TokenPropertyRef(StructDecl ctx, String label) {
|
||||
super(ctx);
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef_channel extends TokenPropertyRef {
|
||||
public TokenPropertyRef_channel(String label) {
|
||||
super(label);
|
||||
public TokenPropertyRef_channel(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef_index extends TokenPropertyRef {
|
||||
public TokenPropertyRef_index(String label) {
|
||||
super(label);
|
||||
public TokenPropertyRef_index(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef_int extends TokenPropertyRef {
|
||||
public TokenPropertyRef_int(String label) {
|
||||
super(label);
|
||||
public TokenPropertyRef_int(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef_line extends TokenPropertyRef {
|
||||
public TokenPropertyRef_line(String label) {
|
||||
super(label);
|
||||
public TokenPropertyRef_line(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef_pos extends TokenPropertyRef {
|
||||
public TokenPropertyRef_pos(String label) {
|
||||
super(label);
|
||||
public TokenPropertyRef_pos(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef_text extends TokenPropertyRef {
|
||||
public TokenPropertyRef_text(String label) {
|
||||
super(label);
|
||||
public TokenPropertyRef_text(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenPropertyRef_type extends TokenPropertyRef {
|
||||
public TokenPropertyRef_type(String label) {
|
||||
super(label);
|
||||
public TokenPropertyRef_type(StructDecl ctx, String label) {
|
||||
super(ctx, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
|
||||
package org.antlr.v4.codegen.model.chunk;
|
||||
|
||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||
|
||||
/** */
|
||||
public class TokenRef extends ActionChunk {
|
||||
public String name;
|
||||
|
||||
public TokenRef(String name) {
|
||||
public TokenRef(StructDecl ctx, String name) {
|
||||
super(ctx);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,15 +34,21 @@ import org.antlr.v4.tool.Rule;
|
|||
|
||||
/** A StructDecl to handle a -> label on alt */
|
||||
public class AltLabelStructDecl extends StructDecl {
|
||||
public String label;
|
||||
public AltLabelStructDecl(OutputModelFactory factory, Rule r, String label) {
|
||||
public int altNum;
|
||||
public AltLabelStructDecl(OutputModelFactory factory, Rule r,
|
||||
int altNum, String label)
|
||||
{
|
||||
super(factory, r);
|
||||
this.label = label;
|
||||
this.altNum = altNum;
|
||||
this.name = // override name set in super to the label ctx
|
||||
label+
|
||||
factory.getGenerator().templates
|
||||
.getInstanceOf("RuleContextNameSuffix").render();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return label.hashCode();
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,7 +56,7 @@ public class AltLabelStructDecl extends StructDecl {
|
|||
if ( obj == this ) return true;
|
||||
if ( obj.hashCode() != this.hashCode() ) return false;
|
||||
if ( obj instanceof AltLabelStructDecl ) {
|
||||
return label.equals(((AltLabelStructDecl)obj).label);
|
||||
return name.equals(((AltLabelStructDecl)obj).name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.antlr.v4.codegen.model.decl;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
public abstract class ContextGetterDecl extends Decl {
|
||||
public ContextGetterDecl(OutputModelFactory factory, String name) {
|
||||
super(factory, name);
|
||||
}
|
||||
|
||||
/** Not used for output; just used to distinguish between decl types
|
||||
* to avoid dups.
|
||||
*/
|
||||
public String getArgType() { return ""; }; // assume no args
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode() + getArgType().hashCode();
|
||||
}
|
||||
|
||||
/** Make sure that a getter does not equal a label. X() and X are ok.
|
||||
* OTOH, treat X() with two diff return values as the same. Treat
|
||||
* two X() with diff args as different.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ( obj==null ) return false;
|
||||
// A() and label A are different
|
||||
if ( !(obj instanceof ContextGetterDecl) ) return false;
|
||||
if ( this==obj ) return true;
|
||||
if ( this.hashCode() != obj.hashCode() ) return false;
|
||||
return
|
||||
name.equals(((Decl) obj).name) &&
|
||||
getArgType().equals(((ContextGetterDecl) obj).getArgType());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.antlr.v4.codegen.model.decl;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
/** public XContext X() { } */
|
||||
public class ContextRuleGetterDecl extends ContextGetterDecl {
|
||||
public String ctxName;
|
||||
public ContextRuleGetterDecl(OutputModelFactory factory, String name, String ctxName) {
|
||||
super(factory, name);
|
||||
this.ctxName = ctxName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package org.antlr.v4.codegen.model.decl;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
/** public List<XContext> X() { }
|
||||
* public XContext X(int i) { }
|
||||
*/
|
||||
public class ContextRuleListGetterDecl extends ContextGetterDecl {
|
||||
public String ctxName;
|
||||
public ContextRuleListGetterDecl(OutputModelFactory factory, String name, String ctxName) {
|
||||
super(factory, name);
|
||||
this.ctxName = ctxName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package org.antlr.v4.codegen.model.decl;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
public class ContextRuleListIndexedGetterDecl extends ContextRuleListGetterDecl {
|
||||
public ContextRuleListIndexedGetterDecl(OutputModelFactory factory, String name, String ctxName) {
|
||||
super(factory, name, ctxName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgType() {
|
||||
return "int";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.antlr.v4.codegen.model.decl;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
/** public Token X() { } */
|
||||
public class ContextTokenGetterDecl extends ContextGetterDecl {
|
||||
public ContextTokenGetterDecl(OutputModelFactory factory, String name) {
|
||||
super(factory, name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.antlr.v4.codegen.model.decl;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
/** public List<Token> X() { }
|
||||
* public Token X(int i) { }
|
||||
*/
|
||||
public class ContextTokenListGetterDecl extends ContextGetterDecl {
|
||||
public ContextTokenListGetterDecl(OutputModelFactory factory, String name) {
|
||||
super(factory, name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package org.antlr.v4.codegen.model.decl;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
|
||||
public class ContextTokenListIndexedGetterDecl extends ContextTokenListGetterDecl {
|
||||
public ContextTokenListIndexedGetterDecl(OutputModelFactory factory, String name) {
|
||||
super(factory, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgType() {
|
||||
return "int";
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ public class Decl extends SrcOp {
|
|||
public String name;
|
||||
public String decl; // whole thing if copied from action
|
||||
public boolean isLocal; // if local var (not in RuleContext struct)
|
||||
public StructDecl ctx; // which context contains us? set by addDecl
|
||||
|
||||
public Decl(OutputModelFactory factory, String name, String decl) {
|
||||
this(factory, name);
|
||||
|
@ -53,8 +54,14 @@ public class Decl extends SrcOp {
|
|||
return name.hashCode();
|
||||
}
|
||||
|
||||
/** If same name, can't redefine, unless it's a getter */
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return name.equals(((Decl)obj).name);
|
||||
if ( obj==null ) return false;
|
||||
// A() and label A are different
|
||||
if ( obj instanceof ContextGetterDecl ) return false;
|
||||
if ( this==obj ) return true;
|
||||
if ( this.hashCode() != obj.hashCode() ) return false;
|
||||
return name.equals(((Decl) obj).name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public class StructDecl extends Decl {
|
|||
public String superClass;
|
||||
public boolean provideCopyFrom;
|
||||
@ModelElement public OrderedHashSet<Decl> attrs = new OrderedHashSet<Decl>();
|
||||
@ModelElement public OrderedHashSet<Decl> getters = new OrderedHashSet<Decl>();
|
||||
@ModelElement public Collection<Attribute> ctorAttrs;
|
||||
@ModelElement public List<VisitorDispatchMethod> visitorDispatchMethods;
|
||||
@ModelElement public List<OutputModelObject> interfaces;
|
||||
|
@ -65,7 +66,11 @@ public class StructDecl extends Decl {
|
|||
visitorDispatchMethods.add(new VisitorDispatchMethod(factory, r, false));
|
||||
}
|
||||
|
||||
public void addDecl(Decl d) { attrs.add(d); }
|
||||
public void addDecl(Decl d) {
|
||||
d.ctx = this;
|
||||
if ( d instanceof ContextGetterDecl ) getters.add(d);
|
||||
else attrs.add(d);
|
||||
}
|
||||
|
||||
public void addDecl(Attribute a) {
|
||||
addDecl(new AttributeDecl(factory, a.name, a.decl));
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package org.antlr.v4.misc;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
/** Count how many of each key we have; not thread safe */
|
||||
public class FrequencySet<T> extends Hashtable<T, MutableInt> {
|
||||
public int count(T key) {
|
||||
MutableInt value = get(key);
|
||||
if (value == null) return 0;
|
||||
return value.v;
|
||||
}
|
||||
public void add(T key) {
|
||||
MutableInt value = get(key);
|
||||
if (value == null) {
|
||||
value = new MutableInt(1);
|
||||
put(key, value);
|
||||
}
|
||||
else {
|
||||
value.v++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.antlr.v4.misc;
|
||||
|
||||
public class MutableInt extends Number implements Comparable<Number> {
|
||||
public int v;
|
||||
|
||||
public MutableInt(int v) { this.v = v; }
|
||||
@Override public int compareTo(Number o) { return v; }
|
||||
@Override public int intValue() { return v; }
|
||||
@Override public long longValue() { return v; }
|
||||
@Override public float floatValue() { return v; }
|
||||
@Override public double doubleValue() { return v; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(v);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.antlr.v4.misc;
|
||||
|
||||
public class Pair<A,B> {
|
||||
public A a;
|
||||
public B b;
|
||||
|
||||
public Pair(A a, B b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.antlr.v4.misc;
|
||||
|
||||
public class Triple<A,B,C> extends Pair<A,B> {
|
||||
public C c;
|
||||
public Triple(A a, B b, C c) {
|
||||
super(a,b);
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
}
|
|
@ -642,8 +642,8 @@ lexerCommands
|
|||
;
|
||||
|
||||
lexerCommand
|
||||
: id LPAREN lexerCommandExpr RPAREN -> ^(LEXER_ACTION_CALL id lexerCommandExpr)
|
||||
| id
|
||||
: lexerCommandName LPAREN lexerCommandExpr RPAREN -> ^(LEXER_ACTION_CALL lexerCommandName lexerCommandExpr)
|
||||
| lexerCommandName
|
||||
;
|
||||
|
||||
lexerCommandExpr
|
||||
|
@ -651,6 +651,11 @@ lexerCommandExpr
|
|||
| INT
|
||||
;
|
||||
|
||||
lexerCommandName
|
||||
: id
|
||||
| MODE ->ID[$MODE]
|
||||
;
|
||||
|
||||
altList
|
||||
: alternative (OR alternative)* -> alternative+
|
||||
;
|
||||
|
|
|
@ -31,6 +31,10 @@ package org.antlr.v4.tool;
|
|||
|
||||
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
|
||||
import org.antlr.v4.misc.OrderedHashMap;
|
||||
import org.antlr.v4.misc.Pair;
|
||||
import org.antlr.v4.misc.Triple;
|
||||
import org.antlr.v4.tool.ast.AltAST;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
import org.antlr.v4.tool.ast.RuleAST;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -40,6 +44,10 @@ public class LeftRecursiveRule extends Rule {
|
|||
public List<LeftRecursiveRuleAltInfo> recPrimaryAlts;
|
||||
public OrderedHashMap<Integer, LeftRecursiveRuleAltInfo> recOpAlts;
|
||||
|
||||
/** Did we delete any labels on direct left-recur refs? Points at ID of ^(= ID el) */
|
||||
public List<Pair<GrammarAST,String>> leftRecursiveRuleRefLabels =
|
||||
new ArrayList<Pair<GrammarAST,String>>();
|
||||
|
||||
public LeftRecursiveRule(Grammar g, String name, RuleAST ast) {
|
||||
super(g, name, ast, 1);
|
||||
alt = new Alternative[numberOfAlts+1]; // always just one
|
||||
|
@ -51,19 +59,46 @@ public class LeftRecursiveRule extends Rule {
|
|||
return super.hasAltSpecificContexts() || getAltLabels()!=null;
|
||||
}
|
||||
|
||||
/** Get -> labels and also those we deleted for left-recursive rules. */
|
||||
@Override
|
||||
public List<String> getAltLabels() {
|
||||
List<String> labels = new ArrayList<String>();
|
||||
List<String> normalAltLabels = super.getAltLabels();
|
||||
if ( normalAltLabels!=null ) labels.addAll(normalAltLabels);
|
||||
public int getOriginalNumberOfAlts() {
|
||||
int n = 0;
|
||||
if ( recPrimaryAlts!=null ) n += recPrimaryAlts.size();
|
||||
if ( recOpAlts!=null ) n += recOpAlts.size();
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AltAST> getUnlabeledAltASTs() {
|
||||
List<AltAST> alts = new ArrayList<AltAST>();
|
||||
for (int i = 0; i < recPrimaryAlts.size(); i++) {
|
||||
LeftRecursiveRuleAltInfo altInfo = recPrimaryAlts.get(i);
|
||||
if ( altInfo.altLabel!=null ) labels.add(altInfo.altLabel);
|
||||
if ( altInfo.altLabel==null ) alts.add(altInfo.altAST);
|
||||
}
|
||||
for (int i = 0; i < recOpAlts.size(); i++) {
|
||||
LeftRecursiveRuleAltInfo altInfo = recOpAlts.getElement(i);
|
||||
if ( altInfo.altLabel!=null ) labels.add(altInfo.altLabel);
|
||||
if ( altInfo.altLabel==null ) alts.add(altInfo.altAST);
|
||||
}
|
||||
if ( alts.size()==0 ) return null;
|
||||
return alts;
|
||||
}
|
||||
|
||||
/** Get -> labels from those alts we deleted for left-recursive rules. */
|
||||
@Override
|
||||
public List<Triple<Integer,AltAST,String>> getAltLabels() {
|
||||
List<Triple<Integer,AltAST,String>> labels = new ArrayList<Triple<Integer,AltAST,String>>();
|
||||
List<Triple<Integer,AltAST,String>> normalAltLabels = super.getAltLabels();
|
||||
if ( normalAltLabels!=null ) labels.addAll(normalAltLabels);
|
||||
for (int i = 0; i < recPrimaryAlts.size(); i++) {
|
||||
LeftRecursiveRuleAltInfo altInfo = recPrimaryAlts.get(i);
|
||||
if ( altInfo.altLabel!=null ) {
|
||||
labels.add(new Triple<Integer,AltAST,String>(altInfo.altNum,altInfo.altAST,altInfo.altLabel));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < recOpAlts.size(); i++) {
|
||||
LeftRecursiveRuleAltInfo altInfo = recOpAlts.getElement(i);
|
||||
if ( altInfo.altLabel!=null ) {
|
||||
labels.add(new Triple<Integer,AltAST,String>(altInfo.altNum,altInfo.altAST,altInfo.altLabel));
|
||||
}
|
||||
}
|
||||
if ( labels.size()==0 ) return null;
|
||||
return labels;
|
||||
|
|
|
@ -29,10 +29,8 @@
|
|||
|
||||
package org.antlr.v4.tool;
|
||||
|
||||
import org.antlr.v4.tool.ast.ActionAST;
|
||||
import org.antlr.v4.tool.ast.GrammarAST;
|
||||
import org.antlr.v4.tool.ast.PredAST;
|
||||
import org.antlr.v4.tool.ast.RuleAST;
|
||||
import org.antlr.v4.misc.Triple;
|
||||
import org.antlr.v4.tool.ast.*;
|
||||
import org.stringtemplate.v4.misc.MultiMap;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -205,18 +203,34 @@ public class Rule implements AttributeResolver {
|
|||
return getAltLabels()!=null;
|
||||
}
|
||||
|
||||
/** Used for recursive rules (subclass), which have 1 alt, but many original alts */
|
||||
public int getOriginalNumberOfAlts() {
|
||||
return numberOfAlts;
|
||||
}
|
||||
|
||||
/** Get -> labels. */
|
||||
public List<String> getAltLabels() {
|
||||
List<String> labels = new ArrayList<String>();
|
||||
public List<Triple<Integer,AltAST,String>> getAltLabels() {
|
||||
List<Triple<Integer,AltAST,String>> labels = new ArrayList<Triple<Integer,AltAST,String>>();
|
||||
for (int i=1; i<=numberOfAlts; i++) {
|
||||
GrammarAST altLabel = alt[i].ast.altLabel;
|
||||
if ( altLabel==null ) break; // all or none
|
||||
labels.add(altLabel.getText());
|
||||
if ( altLabel!=null ) {
|
||||
labels.add(new Triple<Integer,AltAST,String>(i,alt[i].ast,altLabel.getText()));
|
||||
}
|
||||
}
|
||||
if ( labels.size()==0 ) return null;
|
||||
return labels;
|
||||
}
|
||||
|
||||
public List<AltAST> getUnlabeledAltASTs() {
|
||||
List<AltAST> alts = new ArrayList<AltAST>();
|
||||
for (int i=1; i<=numberOfAlts; i++) {
|
||||
GrammarAST altLabel = alt[i].ast.altLabel;
|
||||
if ( altLabel==null ) alts.add(alt[i].ast);
|
||||
}
|
||||
if ( alts.size()==0 ) return null;
|
||||
return alts;
|
||||
}
|
||||
|
||||
/** $x Attribute: rule arguments, return values, predefined rule prop.
|
||||
*/
|
||||
public Attribute resolveToAttribute(String x, ActionAST node) {
|
||||
|
|
|
@ -31,13 +31,17 @@ package org.antlr.v4.tool.ast;
|
|||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.runtime.tree.Tree;
|
||||
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
|
||||
import org.antlr.v4.tool.Alternative;
|
||||
|
||||
/** Any ALT (which can be child of ALT_REWRITE node) */
|
||||
public class AltAST extends GrammarAST {
|
||||
public Alternative alt;
|
||||
|
||||
/** If someone specified an outermost alternative label with #foo.
|
||||
/** If we transformed this alt from a left-recursive one, need info on it */
|
||||
public LeftRecursiveRuleAltInfo leftRecursiveAltInfo;
|
||||
|
||||
/** If someone specified an outermost alternative label with -> foo.
|
||||
* Token type will be ID.
|
||||
*/
|
||||
public GrammarAST altLabel;
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
[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.tool.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
public class DownAST extends TerminalAST {
|
||||
public DownAST(int type, Token t) {
|
||||
super(type, t);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "DOWN";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(GrammarASTVisitor v) { return v.visit(this); }
|
||||
}
|
|
@ -29,14 +29,22 @@
|
|||
|
||||
package org.antlr.v4.tool.ast;
|
||||
|
||||
import org.antlr.runtime.*;
|
||||
import org.antlr.runtime.tree.*;
|
||||
import org.antlr.v4.parse.*;
|
||||
import org.antlr.runtime.CharStream;
|
||||
import org.antlr.runtime.CommonToken;
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.runtime.tree.CommonTree;
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.antlr.runtime.tree.Tree;
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
import org.antlr.v4.parse.GrammarASTAdaptor;
|
||||
import org.antlr.v4.runtime.atn.ATNState;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class GrammarAST extends CommonTree {
|
||||
/** For error msgs, nice to know which grammar this AST lives in */
|
||||
|
@ -108,6 +116,26 @@ public class GrammarAST extends CommonTree {
|
|||
return null;
|
||||
}
|
||||
|
||||
/** Walk ancestors of this node until we find ALT with
|
||||
* alt!=null or leftRecursiveAltInfo!=null. Then grab label if any.
|
||||
* If not a rule element, just returns null.
|
||||
*/
|
||||
public String getAltLabel() {
|
||||
List ancestors = this.getAncestors();
|
||||
if ( ancestors==null ) return null;
|
||||
for (int i=ancestors.size()-1; i>=0; i--) {
|
||||
GrammarAST p = (GrammarAST)ancestors.get(i);
|
||||
if ( p.getType()== ANTLRParser.ALT ) {
|
||||
AltAST a = (AltAST)p;
|
||||
if ( a.altLabel!=null ) return a.altLabel.getText();
|
||||
if ( a.leftRecursiveAltInfo!=null ) {
|
||||
return a.leftRecursiveAltInfo.altLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean deleteChild(org.antlr.runtime.tree.Tree t) {
|
||||
for (int i=0; i<children.size(); i++) {
|
||||
Object c = children.get(i);
|
||||
|
|
|
@ -35,7 +35,4 @@ public interface GrammarASTVisitor {
|
|||
Object visit(SetAST node);
|
||||
Object visit(RuleRefAST node);
|
||||
Object visit(TerminalAST node);
|
||||
Object visit(TreePatternAST node);
|
||||
Object visit(UpAST node);
|
||||
Object visit(DownAST node);
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
[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.tool.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.v4.runtime.atn.ATNState;
|
||||
|
||||
public class TreePatternAST extends GrammarAST implements RuleElementAST {
|
||||
/** Record ATN DN, UP nodes so we can find easily later */
|
||||
public ATNState downState;
|
||||
public ATNState upState;
|
||||
|
||||
public TreePatternAST(Token t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(GrammarASTVisitor v) { return v.visit(this); }
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
[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.tool.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
public class UpAST extends TerminalAST {
|
||||
public UpAST(int type, Token t) {
|
||||
super(type, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "UP";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(GrammarASTVisitor v) { return v.visit(this); }
|
||||
}
|
|
@ -71,7 +71,7 @@ public abstract class BaseTest {
|
|||
public static final String newline = System.getProperty("line.separator");
|
||||
public static final String pathSep = System.getProperty("path.separator");
|
||||
|
||||
public static final boolean TEST_IN_SAME_PROCESS = false;
|
||||
public static final boolean TEST_IN_SAME_PROCESS = Boolean.parseBoolean(System.getProperty("antlr.testinprocess"));
|
||||
|
||||
/**
|
||||
* Build up the full classpath we need, including the surefire path (if present)
|
||||
|
@ -510,7 +510,7 @@ public abstract class BaseTest {
|
|||
}
|
||||
if ( parserName!=null ) {
|
||||
files.add(parserName+".java");
|
||||
files.add("Blank"+grammarFileName.substring(0, grammarFileName.lastIndexOf('.'))+"Listener.java");
|
||||
files.add(grammarFileName.substring(0, grammarFileName.lastIndexOf('.'))+"BaseListener.java");
|
||||
}
|
||||
ok = compile(files.toArray(new String[files.size()]));
|
||||
if ( !ok ) { allIsWell = false; }
|
||||
|
|
|
@ -926,13 +926,13 @@ JavaIDDigit
|
|||
'\u1040'..'\u1049'
|
||||
;
|
||||
|
||||
WS : (' '|'\r'|'\t'|'\u000C'|'\n')+ {$channel=HIDDEN;}//-> channel(HIDDEN)
|
||||
WS : (' '|'\r'|'\t'|'\u000C'|'\n')+ -> channel(HIDDEN)
|
||||
;
|
||||
|
||||
COMMENT
|
||||
: '/*' .* '*/' {$channel=HIDDEN;}//-> channel(HIDDEN)
|
||||
: '/*' .* '*/' -> channel(HIDDEN)
|
||||
;
|
||||
|
||||
LINE_COMMENT
|
||||
: '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}//-> channel(HIDDEN)
|
||||
: '//' ~('\n'|'\r')* '\r'? '\n' -> channel(HIDDEN)
|
||||
;
|
||||
|
|
|
@ -68,8 +68,9 @@ public class TestActionTranslation extends BaseTest {
|
|||
@Test public void testComplicatedArgParsingWithTranslation() throws Exception {
|
||||
String action = "x, $ID.text+\"3242\", (*$ID).foo(21,33), 3.2+1, '\\n', "+
|
||||
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
String expected = "x, (_localctx._tID!=null?_localctx._tID.getText():null)+\"3242\"," +
|
||||
" (*_localctx._tID).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
String expected =
|
||||
"x, (((aContext)_localctx).ID!=null?((aContext)_localctx).ID.getText():null)+\"3242\", " +
|
||||
"(*((aContext)_localctx).ID).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
|
@ -99,39 +100,39 @@ public class TestActionTranslation extends BaseTest {
|
|||
|
||||
@Test public void testReturnValues() throws Exception {
|
||||
String action = "$lab.e; $b.e;";
|
||||
String expected = "_localctx.lab.e; _localctx._rb.e;";
|
||||
String expected = "((aContext)_localctx).lab.e; ((aContext)_localctx).b.e;";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testReturnWithMultipleRuleRefs() throws Exception {
|
||||
String action = "$c.x; $c.y;";
|
||||
String expected = "_localctx._rc.x; _localctx._rc.y;";
|
||||
String expected = "((aContext)_localctx).c.x; ((aContext)_localctx).c.y;";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testTokenRefs() throws Exception {
|
||||
String action = "$id; $ID; $id.text; $id.getText(); $id.line;";
|
||||
String expected = "_localctx.id; _localctx._tID; (_localctx.id!=null?_localctx.id.getText():null); _localctx.id.getText(); (_localctx.id!=null?_localctx.id.getLine():0);";
|
||||
String expected = "((aContext)_localctx).id; ((aContext)_localctx).ID; (((aContext)_localctx).id!=null?((aContext)_localctx).id.getText():null); ((aContext)_localctx).id.getText(); (((aContext)_localctx).id!=null?((aContext)_localctx).id.getLine():0);";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testRuleRefs() throws Exception {
|
||||
String action = "$lab.start;";
|
||||
String expected = "(_localctx.lab!=null?(_localctx.lab.start):null);";
|
||||
String action = "$lab.start; $c.text;";
|
||||
String expected = "(((aContext)_localctx).lab!=null?(((aContext)_localctx).lab.start):null); (((aContext)_localctx).c!=null?_input.toString(((aContext)_localctx).c.start,((aContext)_localctx).c.stop):null);";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testRefToTextAttributeForCurrentRule() throws Exception {
|
||||
String action = "$a.text; $text";
|
||||
String expected =
|
||||
"(_localctx._ra!=null?_input.toString(_localctx._ra.start,_localctx._ra.stop):" +
|
||||
"(_localctx.a!=null?_input.toString(_localctx.a.start,_localctx.a.stop):" +
|
||||
"null); _input.toString(_localctx.start, _input.LT(-1))";
|
||||
testActions(attributeTemplate, "init", action, expected);
|
||||
expected =
|
||||
"_input.toString(_localctx.start, _input.LT(-1)); _input.toString(_localctx.start, _input.LT(-1))";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
expected =
|
||||
"(_localctx._ra!=null?_input.toString(_localctx._ra.start,_localctx._ra.stop):null);" +
|
||||
"(_localctx.a!=null?_input.toString(_localctx.a.start,_localctx.a.stop):null);" +
|
||||
" _input.toString(_localctx.start, _input.LT(-1))";
|
||||
testActions(attributeTemplate, "finally", action, expected);
|
||||
}
|
||||
|
@ -235,10 +236,6 @@ public class TestActionTranslation extends BaseTest {
|
|||
|
||||
@Test public void testRuleLabelWithoutOutputOption() throws Exception {
|
||||
}
|
||||
@Test public void testRuleLabelOnTwoDifferentRulesAST() throws Exception {
|
||||
}
|
||||
@Test public void testRuleLabelOnTwoDifferentRulesTemplate() throws Exception {
|
||||
}
|
||||
@Test public void testMissingArgs() throws Exception {
|
||||
}
|
||||
@Test public void testArgsWhenNoneDefined() throws Exception {
|
||||
|
|
|
@ -42,10 +42,14 @@ public class TestCompositeGrammars extends BaseTest {
|
|||
String grammar =
|
||||
"parser grammar S;\n" +
|
||||
"a : B . C ;\n"; // not qualified ID
|
||||
Grammar g = new Grammar(grammar);
|
||||
mkdir(tmpdir);
|
||||
Grammar g = new Grammar(tmpdir + "/S.g", grammar);
|
||||
g.name = "S";
|
||||
|
||||
ErrorQueue equeue = new ErrorQueue();
|
||||
Tool antlr = new Tool();
|
||||
Tool antlr = g.tool;
|
||||
antlr.outputDirectory = tmpdir;
|
||||
antlr.libDirectory = tmpdir;
|
||||
antlr.addListener(equeue);
|
||||
antlr.process(g,true);
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ public class TestFullContextParsing extends BaseTest {
|
|||
assertEquals(expecting, result);
|
||||
assertEquals("line 1:5 reportAttemptingFullContext d=2: [(30,1,[20 10]), (22,2,[10])], input='34abc'\n" +
|
||||
"line 1:2 reportContextSensitivity d=2: [(22,1,[10])],uniqueAlt=1, input='34'\n" +
|
||||
"line 1:17 reportAttemptingFullContext d=2: [(30,1,[24 14]), (26,2,[14])], input='34abc'\n" +
|
||||
"line 1:14 reportAttemptingFullContext d=2: [(30,1,[24 14]), (26,2,[14])], input='34abc'\n" +
|
||||
"line 1:14 reportContextSensitivity d=2: [(8,2,[18]), (12,2,[18]), (1,2,[])],uniqueAlt=2, input='34abc'\n",
|
||||
this.stderrDuringParse);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue