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
|
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
|
Jan 30, 2012
|
||||||
|
|
||||||
* Moving to github.
|
* Moving to github.
|
||||||
|
|
|
@ -64,8 +64,10 @@ public class CommonToken implements WritableToken, Serializable {
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.stop = stop;
|
this.stop = stop;
|
||||||
this.line = source.getLine();
|
if (source != null) {
|
||||||
this.charPositionInLine = source.getCharPositionInLine();
|
this.line = source.getLine();
|
||||||
|
this.charPositionInLine = source.getCharPositionInLine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommonToken(int type, String text) {
|
public CommonToken(int type, String text) {
|
||||||
|
@ -190,7 +192,7 @@ public class CommonToken implements WritableToken, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharStream getInputStream() {
|
public CharStream getInputStream() {
|
||||||
return source.getInputStream();
|
return source != null ? source.getInputStream() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
@ -88,7 +88,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
|
||||||
/** The token type for the current token */
|
/** The token type for the current token */
|
||||||
public int _type;
|
public int _type;
|
||||||
|
|
||||||
public ArrayDeque<Integer> _modeStack;
|
public ArrayDeque<Integer> _modeStack = new ArrayDeque<Integer>();
|
||||||
public int _mode = Lexer.DEFAULT_MODE;
|
public int _mode = Lexer.DEFAULT_MODE;
|
||||||
|
|
||||||
/** You can set the text for the current token to override what is in
|
/** 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;
|
_hitEOF = false;
|
||||||
_mode = Lexer.DEFAULT_MODE;
|
_mode = Lexer.DEFAULT_MODE;
|
||||||
if (_modeStack != null) {
|
_modeStack.clear();
|
||||||
_modeStack.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
getInterpreter().reset();
|
getInterpreter().reset();
|
||||||
}
|
}
|
||||||
|
@ -184,14 +182,13 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
|
||||||
|
|
||||||
public void pushMode(int m) {
|
public void pushMode(int m) {
|
||||||
if ( LexerATNSimulator.debug ) System.out.println("pushMode "+m);
|
if ( LexerATNSimulator.debug ) System.out.println("pushMode "+m);
|
||||||
if ( _modeStack ==null ) _modeStack = new ArrayDeque<Integer>();
|
|
||||||
getInterpreter().tracePushMode(m);
|
getInterpreter().tracePushMode(m);
|
||||||
_modeStack.push(_mode);
|
_modeStack.push(_mode);
|
||||||
mode(m);
|
mode(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int popMode() {
|
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());
|
if ( LexerATNSimulator.debug ) System.out.println("popMode back to "+ _modeStack.peek());
|
||||||
getInterpreter().tracePopMode();
|
getInterpreter().tracePopMode();
|
||||||
mode( _modeStack.pop() );
|
mode( _modeStack.pop() );
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
package org.antlr.v4.runtime;
|
package org.antlr.v4.runtime;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.atn.ATNConfigSet;
|
import org.antlr.v4.runtime.atn.ATNConfigSet;
|
||||||
|
import org.antlr.v4.runtime.misc.Utils;
|
||||||
|
|
||||||
public class LexerNoViableAltException extends RecognitionException {
|
public class LexerNoViableAltException extends RecognitionException {
|
||||||
/** Matching attempted at what input index? */
|
/** Matching attempted at what input index? */
|
||||||
|
@ -47,7 +48,19 @@ public class LexerNoViableAltException extends RecognitionException {
|
||||||
this.deadEndConfigs = deadEndConfigs;
|
this.deadEndConfigs = deadEndConfigs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharStream getInputStream() {
|
||||||
|
return (CharStream)super.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
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.
|
* satisfy the superclass interface.
|
||||||
*/
|
*/
|
||||||
public class ParserRuleContext<Symbol> extends RuleContext {
|
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,
|
/** If we are debugging or building a parse tree for a visitor,
|
||||||
* we need to track all of the tokens and rule invocations associated
|
* 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);
|
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
|
// Double dispatch methods
|
||||||
|
|
||||||
public void enterRule(ParseTreeListener<Symbol> listener) { }
|
public void enterRule(ParseTreeListener<Symbol> listener) { }
|
||||||
|
@ -187,7 +176,101 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParseTree getChild(int i) {
|
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
|
@Override
|
||||||
|
@ -203,7 +286,7 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
||||||
public String toString(@NotNull Recognizer<?,?> recog, RuleContext stop) {
|
public String toString(@NotNull Recognizer<?,?> recog, RuleContext stop) {
|
||||||
if ( recog==null ) return super.toString(recog, stop);
|
if ( recog==null ) return super.toString(recog, stop);
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
ParserRuleContext p = this;
|
ParserRuleContext<?> p = this;
|
||||||
buf.append("[");
|
buf.append("[");
|
||||||
while ( p != null && p != stop ) {
|
while ( p != null && p != stop ) {
|
||||||
ATN atn = recog.getATN();
|
ATN atn = recog.getATN();
|
||||||
|
@ -214,7 +297,7 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
||||||
// ATNState invoker = atn.states.get(ctx.invokingState);
|
// ATNState invoker = atn.states.get(ctx.invokingState);
|
||||||
// RuleTransition rt = (RuleTransition)invoker.transition(0);
|
// RuleTransition rt = (RuleTransition)invoker.transition(0);
|
||||||
// buf.append(recog.getRuleNames()[rt.target.ruleIndex]);
|
// buf.append(recog.getRuleNames()[rt.target.ruleIndex]);
|
||||||
p = (ParserRuleContext)p.parent;
|
p = (ParserRuleContext<?>)p.parent;
|
||||||
}
|
}
|
||||||
buf.append("]");
|
buf.append("]");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
|
|
|
@ -80,16 +80,6 @@ public class RuleContext implements ParseTree.RuleNode {
|
||||||
|
|
||||||
public RuleContext() {}
|
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) {
|
public RuleContext(RuleContext parent, int invokingState) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
//if ( parent!=null ) System.out.println("invoke "+stateNumber+" from "+parent);
|
//if ( parent!=null ) System.out.println("invoke "+stateNumber+" from "+parent);
|
||||||
|
@ -103,13 +93,6 @@ public class RuleContext implements ParseTree.RuleNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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.
|
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.
|
// TODO: v3 dfa don't do this.
|
||||||
break;
|
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 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 ( 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]);
|
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);
|
throw noViableAlt(input, outerContext, s.configset, startIndex);
|
||||||
}
|
}
|
||||||
s = target;
|
s = target;
|
||||||
input.consume();
|
if (!s.isCtxSensitive && !s.isAcceptState) {
|
||||||
t = input.LA(1);
|
input.consume();
|
||||||
|
t = input.LA(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if ( acceptState==null ) {
|
// if ( acceptState==null ) {
|
||||||
// if ( debug ) System.out.println("!!! no viable alt in dfa");
|
// if ( debug ) System.out.println("!!! no viable alt in dfa");
|
||||||
|
|
|
@ -28,8 +28,7 @@
|
||||||
*/
|
*/
|
||||||
package org.antlr.v4.runtime.misc;
|
package org.antlr.v4.runtime.misc;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.Lexer;
|
import org.antlr.v4.runtime.*;
|
||||||
import org.antlr.v4.runtime.Token;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -56,11 +55,6 @@ public class IntervalSet implements IntSet {
|
||||||
|
|
||||||
protected boolean readonly;
|
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) {
|
public IntervalSet(List<Interval> intervals) {
|
||||||
this.intervals = intervals;
|
this.intervals = intervals;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +64,16 @@ public class IntervalSet implements IntSet {
|
||||||
addAll(set);
|
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. */
|
/** Create a set with a single element, el. */
|
||||||
@NotNull
|
@NotNull
|
||||||
public static IntervalSet of(int a) {
|
public static IntervalSet of(int a) {
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
grammar A;
|
grammar A;
|
||||||
|
|
||||||
s : q=e {System.out.println("result = "+$e.v);} ;
|
s : e ;
|
||||||
|
|
||||||
e returns [int v]
|
e : e '*' e -> Mult
|
||||||
: a=e op='*' b=e {$v = $a.v * $b.v;} -> mult
|
| e '+' e -> Add
|
||||||
| a=e '+' b=e {$v = $a.v + $b.v;} -> add
|
| INT -> Int
|
||||||
| INT {$v = $INT.int;}
|
| '(' e ')' -> Parens
|
||||||
| '(' x=e ')' {$v = $x.v;}
|
|
||||||
| e '++' -> inc
|
|
||||||
| e '--'
|
|
||||||
| ID -> anID
|
|
||||||
;
|
;
|
||||||
|
|
||||||
INT : '0'..'9'+ ;
|
INT : [0-9]+ ;
|
||||||
WS : (' '|'\n')+ {skip();} ;
|
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 | ;
|
//prog : expr_or_assign prog | ;
|
||||||
|
|
||||||
expr_or_assign
|
expr_or_assign
|
||||||
|
@after {System.out.println(getRuleInvocationStack());}
|
||||||
: expr '++'
|
: expr '++'
|
||||||
| expr // match ID a, fall out, reenter, match "(i)<-x" via alt 1
|
| 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
|
// 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.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.antlr.v4.runtime.*;
|
import org.antlr.v4.runtime.ANTLRFileStream;
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
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 org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
public class TestA {
|
public class TestA {
|
||||||
public static class Do extends BlankAListener {
|
/** An example listener that uses a stack to store return values
|
||||||
Parser p;
|
* so that exit methods executed on notes further up the parse tree
|
||||||
public Do(Parser p ) { this.p = p; }
|
* 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
|
@Override
|
||||||
public void exitEveryRule(ParserRuleContext<Token> ctx) {
|
public void exit(AParser.AddContext ctx) {
|
||||||
System.out.println("exit "+ctx.toStringTree(p));
|
results.push( results.pop() + results.pop() );
|
||||||
|
System.out.println("Add: " + results.peek());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enterRule(AParser.eContext ctx) {
|
public void exit(AParser.IntContext ctx) {
|
||||||
System.out.println("enter alt w/o -> label: "+ctx.toInfoString(p));
|
results.push( Integer.valueOf(ctx.INT().getText()) );
|
||||||
|
System.out.println("Int: "+results.peek());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTerminal(ParserRuleContext<Token> ctx, Token symbol) {
|
public void exit(AParser.MultContext ctx) {
|
||||||
if ( ctx instanceof AParser.eContext && symbol.getType()==AParser.INT ) {
|
results.push( results.pop() * results.pop() );
|
||||||
AParser.eContext ectx = (AParser.eContext)ctx;
|
System.out.println("Mult: " + results.peek());
|
||||||
ectx.v = Integer.valueOf(symbol.getText());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exitRule(AParser.multContext ctx) {
|
public void exit(AParser.ParensContext ctx) {
|
||||||
System.out.println("mult "+ctx.a.v+" * "+ctx.b.v);
|
// result already on stack
|
||||||
ctx.v = ctx.a.v * ctx.b.v; // repeat of what parser did--set return value
|
System.out.println("Parens: "+results.peek());
|
||||||
}
|
|
||||||
@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 static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -69,14 +98,13 @@ public class TestA {
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
AParser p = new AParser(tokens);
|
AParser p = new AParser(tokens);
|
||||||
p.setBuildParseTree(true);
|
p.setBuildParseTree(true);
|
||||||
// p.addParseListener(new Do(p));
|
p.addParseListener(new Do());
|
||||||
ParserRuleContext<Token> t = p.s();
|
ParserRuleContext<Token> t = p.s();
|
||||||
System.out.println("tree = "+t.toStringTree(p));
|
System.out.println("tree = "+t.toStringTree(p));
|
||||||
|
|
||||||
ParseTreeWalker walker = new ParseTreeWalker();
|
ParseTreeWalker walker = new ParseTreeWalker();
|
||||||
Do doer = new Do(p);
|
Do doer = new Do();
|
||||||
walker.walk(doer, t);
|
walker.walk(doer, t);
|
||||||
AParser.eContext ectx = (AParser.eContext)t.getChild(0);
|
System.out.println("result from tree walk = "+ doer.results.pop());
|
||||||
System.out.println("result from tree walk = "+ ectx.v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
<target>1.6</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.12</version>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
|
@ -34,21 +34,21 @@ import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
public interface <file.grammarName>Listener extends ParseTreeListener\<<InputSymbolType()>\> {
|
public interface <file.grammarName>Listener extends ParseTreeListener\<<InputSymbolType()>\> {
|
||||||
<file.listenerNames:{lname |
|
<file.listenerNames:{lname |
|
||||||
void enterRule(<file.parserName>.<lname>Context ctx);
|
void enter(<file.parserName>.<lname>Context ctx);
|
||||||
void exitRule(<file.parserName>.<lname>Context ctx);}; separator="\n">
|
void exit(<file.parserName>.<lname>Context ctx);}; separator="\n">
|
||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
||||||
BlankListenerFile(file, header) ::= <<
|
BaseListenerFile(file, header) ::= <<
|
||||||
<header>
|
<header>
|
||||||
|
|
||||||
import org.antlr.v4.runtime.ParserRuleContext;
|
import org.antlr.v4.runtime.ParserRuleContext;
|
||||||
import org.antlr.v4.runtime.Token;
|
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 |
|
<file.listenerNames:{lname |
|
||||||
@Override public void enterRule(<file.parserName>.<lname>Context ctx) { \}
|
@Override public void enter(<file.parserName>.<lname>Context ctx) { \}
|
||||||
@Override public void exitRule(<file.parserName>.<lname>Context ctx) { \}}; separator="\n">
|
@Override public void exit(<file.parserName>.<lname>Context ctx) { \}}; separator="\n">
|
||||||
|
|
||||||
@Override public void enterEveryRule(ParserRuleContext\<<InputSymbolType()>\> ctx) { }
|
@Override public void enterEveryRule(ParserRuleContext\<<InputSymbolType()>\> ctx) { }
|
||||||
@Override public void exitEveryRule(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) ::= <<
|
RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble) ::= <<
|
||||||
|
|
||||||
<ruleCtx>
|
<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 {
|
<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>}>);
|
<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>
|
<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 {
|
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
|
||||||
ParserRuleContext\<Token> _parentctx = _ctx;
|
ParserRuleContext\<Token> _parentctx = _ctx;
|
||||||
|
@ -214,13 +214,13 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
|
||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
||||||
CodeBlockForOuterMostAlt(c, locals, preamble, ops) ::= <<
|
CodeBlockForOuterMostAlt(currentOuterMostAltCodeBlock, locals, preamble, ops) ::= <<
|
||||||
<if(c.altLabel)>_localctx = new <c.altLabel>Context(_localctx);<endif>
|
<if(currentOuterMostAltCodeBlock.altLabel)>_localctx = new <currentOuterMostAltCodeBlock.altLabel>Context(_localctx);<endif>
|
||||||
enterOuterAlt(_localctx, <c.alt.altNum>);
|
enterOuterAlt(_localctx, <currentOuterMostAltCodeBlock.alt.altNum>);
|
||||||
<CodeBlockForAlt(...)>
|
<CodeBlockForAlt(currentAltCodeBlock=currentOuterMostAltCodeBlock, ...)>
|
||||||
>>
|
>>
|
||||||
|
|
||||||
CodeBlockForAlt(c, locals, preamble, ops) ::= <<
|
CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= <<
|
||||||
{
|
{
|
||||||
<locals; separator="\n">
|
<locals; separator="\n">
|
||||||
<preamble; separator="\n">
|
<preamble; separator="\n">
|
||||||
|
@ -425,7 +425,7 @@ setState(<w.stateNumber>);
|
||||||
|
|
||||||
// ACTION STUFF
|
// ACTION STUFF
|
||||||
|
|
||||||
Action(a, chunks) ::= "<chunks>"
|
Action(a, foo, chunks) ::= "<chunks>"
|
||||||
|
|
||||||
ArgAction(a, chunks) ::= "<chunks>"
|
ArgAction(a, chunks) ::= "<chunks>"
|
||||||
|
|
||||||
|
@ -448,32 +448,33 @@ LexerPushModeCommand(arg) ::= "pushMode(<arg>);"
|
||||||
DefaultParserSuperClass(s) ::= "Parser"
|
DefaultParserSuperClass(s) ::= "Parser"
|
||||||
|
|
||||||
ActionText(t) ::= "<t.text>"
|
ActionText(t) ::= "<t.text>"
|
||||||
|
ActionTemplate(t) ::= "<t.st>"
|
||||||
ArgRef(a) ::= "_localctx.<a.name>"
|
ArgRef(a) ::= "_localctx.<a.name>"
|
||||||
LocalRef(a) ::= "_localctx.<a.name>"
|
LocalRef(a) ::= "_localctx.<a.name>"
|
||||||
RetValueRef(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 */
|
/** How to translate $tokenLabel */
|
||||||
TokenRef(t) ::= "_localctx.<t.name>"
|
TokenRef(t) ::= "<ctx(t)>.<t.name>"
|
||||||
LabelRef(t) ::= "_localctx.<t.name>"
|
LabelRef(t) ::= "<ctx(t)>.<t.name>"
|
||||||
ListLabelRef(t) ::= "_localctx.<ListLabelName(t.name)>"
|
ListLabelRef(t) ::= "<ctx(t)>.<ListLabelName(t.name)>"
|
||||||
SetAttr(s,rhsChunks) ::= "_localctx.<s.name> = <rhsChunks>;"
|
SetAttr(s,rhsChunks) ::= "<ctx(s)>.<s.name> = <rhsChunks>;"
|
||||||
LexerSetAttr(s,rhsChunks) ::= "_<s.name> = <rhsChunks>;" // _type etc...
|
LexerSetAttr(s,rhsChunks) ::= "_<s.name> = <rhsChunks>;" // _type etc...
|
||||||
|
|
||||||
TokenLabelType() ::= "<file.TokenLabelType; null={Token}>"
|
TokenLabelType() ::= "<file.TokenLabelType; null={Token}>"
|
||||||
InputSymbolType() ::= "<file.InputSymbolType; null={Token}>"
|
InputSymbolType() ::= "<file.InputSymbolType; null={Token}>"
|
||||||
|
|
||||||
TokenPropertyRef_text(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getText():null)"
|
TokenPropertyRef_text(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getText():null)"
|
||||||
TokenPropertyRef_type(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getType():0)"
|
TokenPropertyRef_type(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getType():0)"
|
||||||
TokenPropertyRef_line(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getLine():0)"
|
TokenPropertyRef_line(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getLine():0)"
|
||||||
TokenPropertyRef_pos(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getCharPositionInLine():0)"
|
TokenPropertyRef_pos(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getCharPositionInLine():0)"
|
||||||
TokenPropertyRef_channel(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getChannel():0)"
|
TokenPropertyRef_channel(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getChannel():0)"
|
||||||
TokenPropertyRef_index(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getTokenIndex():0)"
|
TokenPropertyRef_index(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getTokenIndex():0)"
|
||||||
TokenPropertyRef_int(t) ::= "(_localctx.<t.label>!=null?Integer.valueOf(_localctx.<t.label>.getText()):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_start(r) ::= "(<ctx(r)>.<r.label>!=null?(<ctx(r)>.<r.label>.start):null)"
|
||||||
RulePropertyRef_stop(r) ::= "(_localctx.<r.label>!=null?(_localctx.<r.label>.stop):null)"
|
RulePropertyRef_stop(r) ::= "(<ctx(r)>.<r.label>!=null?(<ctx(r)>.<r.label>.stop):null)"
|
||||||
RulePropertyRef_text(r) ::= "(_localctx.<r.label>!=null?_input.toString(_localctx.<r.label>.start,_localctx.<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) ::= "_localctx.<r.label>"
|
RulePropertyRef_ctx(r) ::= "<ctx(r)>.<r.label>"
|
||||||
|
|
||||||
ThisRulePropertyRef_start(r) ::= "_localctx.start"
|
ThisRulePropertyRef_start(r) ::= "_localctx.start"
|
||||||
ThisRulePropertyRef_stop(r) ::= "_localctx.stop"
|
ThisRulePropertyRef_stop(r) ::= "_localctx.stop"
|
||||||
|
@ -484,13 +485,38 @@ NonLocalAttrRef(s) ::= "((<s.ruleName>Context)getInvokingContext(<s.ruleIndex>
|
||||||
SetNonLocalAttr(s, rhsChunks) ::=
|
SetNonLocalAttr(s, rhsChunks) ::=
|
||||||
"((<s.ruleName>Context)getInvokingContext(<s.ruleIndex>)).<s.name> = <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>;"
|
TokenTypeDecl(t) ::= "int <t.name>;"
|
||||||
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();"
|
TokenListDecl(t) ::= "public List\<Token> <t.name> = new ArrayList\<Token>();"
|
||||||
RuleContextDecl(r) ::= "<r.ctxName> <r.name>;"
|
RuleContextDecl(r) ::= "public <r.ctxName> <r.name>;"
|
||||||
RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
|
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"
|
LexerRuleContext() ::= "RuleContext"
|
||||||
|
|
||||||
|
@ -499,18 +525,19 @@ LexerRuleContext() ::= "RuleContext"
|
||||||
*/
|
*/
|
||||||
RuleContextNameSuffix() ::= "Context"
|
RuleContextNameSuffix() ::= "Context"
|
||||||
|
|
||||||
ImplicitTokenLabel(tokenName) ::= "_t<tokenName>"
|
ImplicitTokenLabel(tokenName) ::= "<tokenName>"
|
||||||
ImplicitRuleLabel(ruleName) ::= "_r<ruleName>"
|
ImplicitRuleLabel(ruleName) ::= "<ruleName>"
|
||||||
ImplicitSetLabel(id) ::= "_tset<id>"
|
ImplicitSetLabel(id) ::= "_tset<id>"
|
||||||
ListLabelName(label) ::= "<label>_list"
|
ListLabelName(label) ::= "<label>"
|
||||||
|
|
||||||
CaptureNextToken(d) ::= "<d.varName> = _input.LT(1);"
|
CaptureNextToken(d) ::= "<d.varName> = _input.LT(1);"
|
||||||
CaptureNextTokenType(d) ::= "<d.varName> = _input.LA(1);"
|
CaptureNextTokenType(d) ::= "<d.varName> = _input.LA(1);"
|
||||||
|
|
||||||
StructDecl(s,attrs,visitorDispatchMethods,interfaces,extensionMembers,
|
StructDecl(s,attrs,getters,visitorDispatchMethods,interfaces,extensionMembers,
|
||||||
superClass={ParserRuleContext\<<InputSymbolType()>>}) ::= <<
|
superClass={ParserRuleContext\<<InputSymbolType()>>}) ::= <<
|
||||||
public static class <s.name> extends <superClass><if(interfaces)> implements <interfaces; separator=", "><endif> {
|
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>
|
<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>}>) {
|
public <s.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state<s.ctorAttrs:{a | , <a>}>) {
|
||||||
super(parent, state);
|
super(parent, state);
|
||||||
|
@ -528,9 +555,11 @@ public static class <s.name> extends <superClass><if(interfaces)> implements <in
|
||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
||||||
AltLabelStructDecl(s,attrs,visitorDispatchMethods) ::= <<
|
AltLabelStructDecl(s,attrs,getters,visitorDispatchMethods) ::= <<
|
||||||
public static class <s.label>Context extends <currentRule.name>Context {
|
public static class <s.name> extends <currentRule.name>Context {
|
||||||
public <s.label>Context(<currentRule.name>Context ctx) { copyFrom(ctx); }
|
<attrs:{a | <a>}; separator="\n">
|
||||||
|
<getters:{g | <g>}; separator="\n">
|
||||||
|
public <s.name>(<currentRule.name>Context ctx) { copyFrom(ctx); }
|
||||||
<visitorDispatchMethods; separator="\n">
|
<visitorDispatchMethods; separator="\n">
|
||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
@ -538,14 +567,17 @@ public static class <s.label>Context extends <currentRule.name>Context {
|
||||||
VisitorDispatchMethod(method) ::= <<
|
VisitorDispatchMethod(method) ::= <<
|
||||||
@Override
|
@Override
|
||||||
public void <if(method.isEnter)>enter<else>exit<endif>Rule(ParseTreeListener\<<InputSymbolType()>\> listener) {
|
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 */
|
/** 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
|
// used for left-recursive rules
|
||||||
recRuleDefArg() ::= "int _p"
|
recRuleDefArg() ::= "int _p"
|
||||||
|
@ -563,10 +595,10 @@ pushNewRecursionContext(_localctx, RULE_<ruleName>);
|
||||||
_localctx.start = _prevctx.start;
|
_localctx.start = _prevctx.start;
|
||||||
>>
|
>>
|
||||||
|
|
||||||
recRuleLabeledAltStartAction(ruleName, ctxName, label) ::= <<
|
recRuleLabeledAltStartAction(ruleName, currentAltLabel, label) ::= <<
|
||||||
_localctx = new <ctxName>Context(new <ruleName>Context(_parentctx, _startState, _p));
|
_localctx = new <currentAltLabel>Context(new <ruleName>Context(_parentctx, _startState, _p));
|
||||||
_localctx.addChild(_prevctx);
|
_localctx.addChild(_prevctx);
|
||||||
<if(label)>_localctx.<label> = _prevctx;<endif>
|
<if(label)>((<currentAltLabel>Context)_localctx).<label> = _prevctx;<endif>
|
||||||
pushNewRecursionContext(_localctx, RULE_<ruleName>);
|
pushNewRecursionContext(_localctx, RULE_<ruleName>);
|
||||||
_localctx.start = _prevctx.start;
|
_localctx.start = _prevctx.start;
|
||||||
>>
|
>>
|
||||||
|
|
|
@ -58,7 +58,7 @@ import java.util.List;
|
||||||
public class Tool {
|
public class Tool {
|
||||||
public String VERSION = "4.0-"+new Date();
|
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 {
|
public static class Option {
|
||||||
String fieldName;
|
String fieldName;
|
||||||
String name;
|
String name;
|
||||||
|
@ -90,11 +90,13 @@ public class Tool {
|
||||||
public String grammarEncoding = null; // use default locale's encoding
|
public String grammarEncoding = null; // use default locale's encoding
|
||||||
public String msgFormat = "antlr";
|
public String msgFormat = "antlr";
|
||||||
public boolean saveLexer = false;
|
public boolean saveLexer = false;
|
||||||
public boolean genListener = true;
|
|
||||||
public boolean launch_ST_inspector = false;
|
public boolean launch_ST_inspector = false;
|
||||||
public boolean force_atn = false;
|
public boolean force_atn = false;
|
||||||
public boolean log = false;
|
public boolean log = false;
|
||||||
public boolean verbose_dfa = 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 = {
|
public static Option[] optionDefs = {
|
||||||
new Option("outputDirectory", "-o", OptionArgType.STRING, "specify output directory where all output is generated"),
|
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("printGrammar", "-print", "print out the grammar without actions"),
|
||||||
new Option("debug", "-debug", "generate a parser that emits debugging events"),
|
new Option("debug", "-debug", "generate a parser that emits debugging events"),
|
||||||
new Option("profile", "-profile", "generate a parser that computes profiling information"),
|
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("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("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("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("launch_ST_inspector", "-XdbgST", "launch StringTemplate visualizer on generated code"),
|
||||||
new Option("force_atn", "-Xforce-atn", "use the ATN simulator for all predictions"),
|
new Option("force_atn", "-Xforce-atn", "use the ATN simulator for all predictions"),
|
||||||
|
@ -182,17 +188,20 @@ public class Tool {
|
||||||
}
|
}
|
||||||
for (Option o : optionDefs) {
|
for (Option o : optionDefs) {
|
||||||
if ( arg.equals(o.name) ) {
|
if ( arg.equals(o.name) ) {
|
||||||
String value = null;
|
String argValue = null;
|
||||||
if ( o.argType==OptionArgType.STRING ) {
|
if ( o.argType==OptionArgType.STRING ) {
|
||||||
value = args[i];
|
argValue = args[i];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
// use reflection to set field
|
// use reflection to set field
|
||||||
Class c = this.getClass();
|
Class c = this.getClass();
|
||||||
try {
|
try {
|
||||||
Field f = c.getField(o.fieldName);
|
Field f = c.getField(o.fieldName);
|
||||||
if ( value==null ) f.setBoolean(this, true);
|
if ( argValue==null ) {
|
||||||
else f.set(this, value);
|
if ( o.fieldName.startsWith("-no-") ) f.setBoolean(this, false);
|
||||||
|
else f.setBoolean(this, true);
|
||||||
|
}
|
||||||
|
else f.set(this, argValue);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
errMgr.toolError(ErrorType.INTERNAL_ERROR, "can't access field "+o.fieldName);
|
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;
|
import org.antlr.v4.tool.ast.AltAST;
|
||||||
|
|
||||||
public class LeftRecursiveRuleAltInfo {
|
public class LeftRecursiveRuleAltInfo {
|
||||||
public int alt;
|
public int altNum; // original alt index (from 1)
|
||||||
public String leftRecursiveRuleRefLabel;
|
public String leftRecursiveRuleRefLabel;
|
||||||
public String altLabel;
|
public String altLabel;
|
||||||
public String altText;
|
public String altText;
|
||||||
public AltAST altAST;
|
public AltAST altAST;
|
||||||
public int nextPrec;
|
public int nextPrec;
|
||||||
|
|
||||||
public LeftRecursiveRuleAltInfo(int alt, String altText) {
|
public LeftRecursiveRuleAltInfo(int altNum, String altText) {
|
||||||
this(alt, altText, null, null);
|
this(altNum, altText, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LeftRecursiveRuleAltInfo(int alt, String altText, String leftRecursiveRuleRefLabel, String altLabel) {
|
public LeftRecursiveRuleAltInfo(int altNum, String altText, String leftRecursiveRuleRefLabel, String altLabel) {
|
||||||
this.alt = alt;
|
this.altNum = altNum;
|
||||||
this.altText = altText;
|
this.altText = altText;
|
||||||
this.leftRecursiveRuleRefLabel = leftRecursiveRuleRefLabel;
|
this.leftRecursiveRuleRefLabel = leftRecursiveRuleRefLabel;
|
||||||
this.altLabel = altLabel;
|
this.altLabel = altLabel;
|
||||||
|
|
|
@ -29,21 +29,15 @@
|
||||||
|
|
||||||
package org.antlr.v4.analysis;
|
package org.antlr.v4.analysis;
|
||||||
|
|
||||||
import org.antlr.runtime.CommonToken;
|
import org.antlr.runtime.*;
|
||||||
import org.antlr.runtime.TokenStream;
|
import org.antlr.runtime.tree.*;
|
||||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
|
||||||
import org.antlr.runtime.tree.Tree;
|
|
||||||
import org.antlr.v4.Tool;
|
import org.antlr.v4.Tool;
|
||||||
import org.antlr.v4.codegen.CodeGenerator;
|
import org.antlr.v4.codegen.CodeGenerator;
|
||||||
import org.antlr.v4.parse.GrammarASTAdaptor;
|
import org.antlr.v4.misc.Pair;
|
||||||
import org.antlr.v4.parse.LeftRecursiveRuleWalker;
|
import org.antlr.v4.parse.*;
|
||||||
import org.antlr.v4.tool.ErrorType;
|
import org.antlr.v4.tool.ErrorType;
|
||||||
import org.antlr.v4.tool.ast.AltAST;
|
import org.antlr.v4.tool.ast.*;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
import org.stringtemplate.v4.*;
|
||||||
import org.antlr.v4.tool.ast.GrammarASTWithOptions;
|
|
||||||
import org.stringtemplate.v4.ST;
|
|
||||||
import org.stringtemplate.v4.STGroup;
|
|
||||||
import org.stringtemplate.v4.STGroupFile;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -62,7 +56,8 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
public List<LeftRecursiveRuleAltInfo> otherAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
|
public List<LeftRecursiveRuleAltInfo> otherAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
|
||||||
|
|
||||||
/** Pointer to ID node of ^(= ID element) */
|
/** 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;
|
public GrammarAST retvals;
|
||||||
|
|
||||||
|
@ -131,10 +126,13 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
@Override
|
@Override
|
||||||
public void binaryAlt(AltAST altTree, int alt) {
|
public void binaryAlt(AltAST altTree, int alt) {
|
||||||
altTree = (AltAST)altTree.dupTree();
|
altTree = (AltAST)altTree.dupTree();
|
||||||
|
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||||
|
|
||||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
||||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
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);
|
stripAssocOptions(altTree);
|
||||||
stripAltLabel(altTree);
|
stripAltLabel(altTree);
|
||||||
|
|
||||||
|
@ -145,7 +143,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
stripAltLabel(altTree);
|
stripAltLabel(altTree);
|
||||||
String altText = text(altTree);
|
String altText = text(altTree);
|
||||||
altText = altText.trim();
|
altText = altText.trim();
|
||||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
|
||||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
||||||
a.nextPrec = nextPrec;
|
a.nextPrec = nextPrec;
|
||||||
binaryAlts.put(alt, a);
|
binaryAlts.put(alt, a);
|
||||||
|
@ -156,10 +153,13 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
@Override
|
@Override
|
||||||
public void ternaryAlt(AltAST altTree, int alt) {
|
public void ternaryAlt(AltAST altTree, int alt) {
|
||||||
altTree = (AltAST)altTree.dupTree();
|
altTree = (AltAST)altTree.dupTree();
|
||||||
|
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||||
|
|
||||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
||||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
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);
|
stripAssocOptions(altTree);
|
||||||
stripAltLabel(altTree);
|
stripAltLabel(altTree);
|
||||||
|
|
||||||
|
@ -168,7 +168,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
|
|
||||||
String altText = text(altTree);
|
String altText = text(altTree);
|
||||||
altText = altText.trim();
|
altText = altText.trim();
|
||||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
|
||||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
||||||
a.nextPrec = nextPrec;
|
a.nextPrec = nextPrec;
|
||||||
ternaryAlts.put(alt, a);
|
ternaryAlts.put(alt, a);
|
||||||
|
@ -195,13 +194,16 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
@Override
|
@Override
|
||||||
public void suffixAlt(AltAST altTree, int alt) {
|
public void suffixAlt(AltAST altTree, int alt) {
|
||||||
altTree = (AltAST)altTree.dupTree();
|
altTree = (AltAST)altTree.dupTree();
|
||||||
|
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||||
|
|
||||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
||||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
String label = lrlabel != null ? lrlabel.getText() : null;
|
||||||
|
if ( lrlabel!=null ) {
|
||||||
|
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST,String>(lrlabel,altLabel));
|
||||||
|
}
|
||||||
stripAltLabel(altTree);
|
stripAltLabel(altTree);
|
||||||
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
|
|
||||||
String altText = text(altTree);
|
String altText = text(altTree);
|
||||||
altText = altText.trim();
|
altText = altText.trim();
|
||||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
|
||||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
||||||
suffixAlts.put(alt, a);
|
suffixAlts.put(alt, a);
|
||||||
// System.out.println("suffixAlt " + alt + ": " + altText + ", rewrite=" + rewriteText);
|
// System.out.println("suffixAlt " + alt + ": " + altText + ", rewrite=" + rewriteText);
|
||||||
|
@ -210,17 +212,10 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
@Override
|
@Override
|
||||||
public void otherAlt(AltAST altTree, int alt) {
|
public void otherAlt(AltAST altTree, int alt) {
|
||||||
altTree = (AltAST)altTree.dupTree();
|
altTree = (AltAST)altTree.dupTree();
|
||||||
GrammarAST lrlabel = stripLeftRecursion(altTree);
|
|
||||||
String label = lrlabel != null ? lrlabel.getText() : null;
|
|
||||||
stripAltLabel(altTree);
|
stripAltLabel(altTree);
|
||||||
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
|
|
||||||
String altText = text(altTree);
|
String altText = text(altTree);
|
||||||
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
|
||||||
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
|
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, null, altLabel);
|
||||||
// if ( altLabel!=null ) {
|
|
||||||
// a.startAction = codegenTemplates.getInstanceOf("recRuleReplaceContext");
|
|
||||||
// a.startAction.add("ctxName", altLabel);
|
|
||||||
// }
|
|
||||||
otherAlts.add(a);
|
otherAlts.add(a);
|
||||||
// System.out.println("otherAlt " + alt + ": " + altText);
|
// System.out.println("otherAlt " + alt + ": " + altText);
|
||||||
}
|
}
|
||||||
|
@ -256,8 +251,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
|
||||||
ruleST.add("primaryAlts", prefixAlts);
|
ruleST.add("primaryAlts", prefixAlts);
|
||||||
ruleST.add("primaryAlts", otherAlts);
|
ruleST.add("primaryAlts", otherAlts);
|
||||||
|
|
||||||
ruleST.add("leftRecursiveRuleRefLabels", leftRecursiveRuleRefLabels);
|
|
||||||
|
|
||||||
tool.log("left-recursion", ruleST.render());
|
tool.log("left-recursion", ruleST.render());
|
||||||
|
|
||||||
return ruleST.render();
|
return ruleST.render();
|
||||||
|
|
|
@ -32,6 +32,7 @@ package org.antlr.v4.analysis;
|
||||||
import org.antlr.runtime.*;
|
import org.antlr.runtime.*;
|
||||||
import org.antlr.v4.Tool;
|
import org.antlr.v4.Tool;
|
||||||
import org.antlr.v4.misc.OrderedHashMap;
|
import org.antlr.v4.misc.OrderedHashMap;
|
||||||
|
import org.antlr.v4.misc.Pair;
|
||||||
import org.antlr.v4.parse.*;
|
import org.antlr.v4.parse.*;
|
||||||
import org.antlr.v4.tool.*;
|
import org.antlr.v4.tool.*;
|
||||||
import org.antlr.v4.tool.ast.*;
|
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
|
// 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 labelOpNode = (GrammarAST)labelNode.getParent();
|
||||||
GrammarAST elementNode = (GrammarAST)labelOpNode.getChild(1);
|
GrammarAST elementNode = (GrammarAST)labelOpNode.getChild(1);
|
||||||
LabelElementPair lp = new LabelElementPair(g, labelNode, elementNode, labelOpNode.getType());
|
LabelElementPair lp = new LabelElementPair(g, labelNode, elementNode, labelOpNode.getType());
|
||||||
r.alt[1].labelDefs.map(labelNode.getText(), lp);
|
r.alt[1].labelDefs.map(labelNode.getText(), lp);
|
||||||
}
|
}
|
||||||
|
// copy to rule from walker
|
||||||
|
r.leftRecursiveRuleRefLabels = leftRecursiveRuleWalker.leftRecursiveRuleRefLabels;
|
||||||
|
|
||||||
tool.log("grammar", "added: "+t.toStringTree());
|
tool.log("grammar", "added: "+t.toStringTree());
|
||||||
return true;
|
return true;
|
||||||
|
@ -189,6 +194,7 @@ public class LeftRecursiveRuleTransformer {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
public void setAltASTPointers(LeftRecursiveRule r, RuleAST t) {
|
public void setAltASTPointers(LeftRecursiveRule r, RuleAST t) {
|
||||||
|
// System.out.println("RULE: "+t.toStringTree());
|
||||||
BlockAST ruleBlk = (BlockAST)t.getFirstChildWithType(ANTLRParser.BLOCK);
|
BlockAST ruleBlk = (BlockAST)t.getFirstChildWithType(ANTLRParser.BLOCK);
|
||||||
AltAST mainAlt = (AltAST)ruleBlk.getChild(0);
|
AltAST mainAlt = (AltAST)ruleBlk.getChild(0);
|
||||||
BlockAST primaryBlk = (BlockAST)mainAlt.getChild(0);
|
BlockAST primaryBlk = (BlockAST)mainAlt.getChild(0);
|
||||||
|
@ -196,11 +202,13 @@ public class LeftRecursiveRuleTransformer {
|
||||||
for (int i = 0; i < r.recPrimaryAlts.size(); i++) {
|
for (int i = 0; i < r.recPrimaryAlts.size(); i++) {
|
||||||
LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i);
|
LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i);
|
||||||
altInfo.altAST = (AltAST)primaryBlk.getChild(i);
|
altInfo.altAST = (AltAST)primaryBlk.getChild(i);
|
||||||
|
altInfo.altAST.leftRecursiveAltInfo = altInfo;
|
||||||
// System.out.println(altInfo.altAST.toStringTree());
|
// System.out.println(altInfo.altAST.toStringTree());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < r.recOpAlts.size(); i++) {
|
for (int i = 0; i < r.recOpAlts.size(); i++) {
|
||||||
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
|
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
|
||||||
altInfo.altAST = (AltAST)opsBlk.getChild(i);
|
altInfo.altAST = (AltAST)opsBlk.getChild(i);
|
||||||
|
altInfo.altAST.leftRecursiveAltInfo = altInfo;
|
||||||
// System.out.println(altInfo.altAST.toStringTree());
|
// System.out.println(altInfo.altAST.toStringTree());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.antlr.runtime.ANTLRStringStream;
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.antlr.v4.codegen.model.RuleFunction;
|
import org.antlr.v4.codegen.model.RuleFunction;
|
||||||
import org.antlr.v4.codegen.model.chunk.*;
|
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.ActionSplitter;
|
||||||
import org.antlr.v4.parse.ActionSplitterListener;
|
import org.antlr.v4.parse.ActionSplitterListener;
|
||||||
import org.antlr.v4.tool.Attribute;
|
import org.antlr.v4.tool.Attribute;
|
||||||
|
@ -78,6 +79,7 @@ public class ActionTranslator implements ActionSplitterListener {
|
||||||
RuleFunction rf;
|
RuleFunction rf;
|
||||||
List<ActionChunk> chunks = new ArrayList<ActionChunk>();
|
List<ActionChunk> chunks = new ArrayList<ActionChunk>();
|
||||||
OutputModelFactory factory;
|
OutputModelFactory factory;
|
||||||
|
StructDecl nodeContext;
|
||||||
|
|
||||||
public ActionTranslator(OutputModelFactory factory, ActionAST node) {
|
public ActionTranslator(OutputModelFactory factory, ActionAST node) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
|
@ -116,6 +118,9 @@ public class ActionTranslator implements ActionSplitterListener {
|
||||||
ActionTranslator translator = new ActionTranslator(factory, node);
|
ActionTranslator translator = new ActionTranslator(factory, node);
|
||||||
translator.rf = rf;
|
translator.rf = rf;
|
||||||
factory.getGrammar().tool.log("action-translator", "translate " + action);
|
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);
|
ANTLRStringStream in = new ANTLRStringStream(action);
|
||||||
in.setLine(tokenWithinAction.getLine());
|
in.setLine(tokenWithinAction.getLine());
|
||||||
in.setCharPositionInLine(tokenWithinAction.getCharPositionInLine());
|
in.setCharPositionInLine(tokenWithinAction.getCharPositionInLine());
|
||||||
|
@ -130,27 +135,27 @@ public class ActionTranslator implements ActionSplitterListener {
|
||||||
Attribute a = node.resolver.resolveToAttribute(x.getText(), node);
|
Attribute a = node.resolver.resolveToAttribute(x.getText(), node);
|
||||||
if ( a!=null ) {
|
if ( a!=null ) {
|
||||||
switch ( a.dict.type ) {
|
switch ( a.dict.type ) {
|
||||||
case ARG: chunks.add(new ArgRef(x.getText())); break;
|
case ARG: chunks.add(new ArgRef(nodeContext,x.getText())); break;
|
||||||
case RET: chunks.add(new RetValueRef(x.getText())); break;
|
case RET: chunks.add(new RetValueRef(rf.ruleCtx, x.getText())); break;
|
||||||
case LOCAL: chunks.add(new LocalRef(x.getText())); break;
|
case LOCAL: chunks.add(new LocalRef(nodeContext,x.getText())); break;
|
||||||
case PREDEFINED_RULE: chunks.add(getRulePropertyRef(x)); break;
|
case PREDEFINED_RULE: chunks.add(getRulePropertyRef(x)); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( node.resolver.resolvesToToken(x.getText(), node) ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if ( node.resolver.resolvesToLabel(x.getText(), node) ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if ( node.resolver.resolvesToListLabel(x.getText(), node) ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
Rule r = factory.getGrammar().getRule(x.getText());
|
Rule r = factory.getGrammar().getRule(x.getText());
|
||||||
if ( r!=null ) {
|
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);
|
gen.g.tool.log("action-translator", "setQAttr "+x+"."+y+"="+rhs);
|
||||||
// x has to be current rule; just set y attr
|
// x has to be current rule; just set y attr
|
||||||
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
|
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) {
|
public void qualifiedAttr(String expr, Token x, Token y) {
|
||||||
gen.g.tool.log("action-translator", "qattr "+x+"."+y);
|
gen.g.tool.log("action-translator", "qattr "+x+"."+y);
|
||||||
Attribute a = node.resolver.resolveToAttribute(x.getText(), y.getText(), node);
|
Attribute a = node.resolver.resolveToAttribute(x.getText(), y.getText(), node);
|
||||||
switch ( a.dict.type ) {
|
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:
|
case RET:
|
||||||
if ( factory.getCurrentRuleFunction()!=null &&
|
if ( factory.getCurrentRuleFunction()!=null &&
|
||||||
factory.getCurrentRuleFunction().name.equals(x.getText()) )
|
factory.getCurrentRuleFunction().name.equals(x.getText()) )
|
||||||
{
|
{
|
||||||
chunks.add(new RetValueRef(y.getText())); break;
|
chunks.add(new RetValueRef(rf.ruleCtx, y.getText())); break;
|
||||||
}
|
}
|
||||||
else {
|
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:
|
case PREDEFINED_RULE:
|
||||||
if ( factory.getCurrentRuleFunction()!=null &&
|
if ( factory.getCurrentRuleFunction()!=null &&
|
||||||
|
@ -195,22 +200,22 @@ public class ActionTranslator implements ActionSplitterListener {
|
||||||
public void setAttr(String expr, Token x, Token rhs) {
|
public void setAttr(String expr, Token x, Token rhs) {
|
||||||
gen.g.tool.log("action-translator", "setAttr "+x+" "+rhs);
|
gen.g.tool.log("action-translator", "setAttr "+x+" "+rhs);
|
||||||
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
|
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
|
||||||
SetAttr s = new SetAttr(x.getText(), rhsChunks);
|
SetAttr s = new SetAttr(nodeContext, x.getText(), rhsChunks);
|
||||||
if ( factory.getGrammar().isLexer() ) s = new LexerSetAttr(x.getText(), rhsChunks);
|
if ( factory.getGrammar().isLexer() ) s = new LexerSetAttr(nodeContext, x.getText(), rhsChunks);
|
||||||
chunks.add(s);
|
chunks.add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void nonLocalAttr(String expr, Token x, Token y) {
|
public void nonLocalAttr(String expr, Token x, Token y) {
|
||||||
gen.g.tool.log("action-translator", "nonLocalAttr "+x+"::"+y);
|
gen.g.tool.log("action-translator", "nonLocalAttr "+x+"::"+y);
|
||||||
Rule r = factory.getGrammar().getRule(x.getText());
|
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) {
|
public void setNonLocalAttr(String expr, Token x, Token y, Token rhs) {
|
||||||
gen.g.tool.log("action-translator", "setNonLocalAttr "+x+"::"+y+"="+rhs);
|
gen.g.tool.log("action-translator", "setNonLocalAttr "+x+"::"+y+"="+rhs);
|
||||||
Rule r = factory.getGrammar().getRule(x.getText());
|
Rule r = factory.getGrammar().getRule(x.getText());
|
||||||
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
|
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);
|
chunks.add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,15 +223,15 @@ public class ActionTranslator implements ActionSplitterListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void text(String text) {
|
public void text(String text) {
|
||||||
chunks.add(new ActionText(text));
|
chunks.add(new ActionText(nodeContext,text));
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenPropertyRef getTokenPropertyRef(Token x, Token y) {
|
TokenPropertyRef getTokenPropertyRef(Token x, Token y) {
|
||||||
try {
|
try {
|
||||||
Class c = tokenPropToModelMap.get(y.getText());
|
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 ref =
|
||||||
(TokenPropertyRef)ctor.newInstance(getTokenLabel(x.getText()));
|
(TokenPropertyRef)ctor.newInstance(nodeContext, getTokenLabel(x.getText()));
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
@ -239,9 +244,9 @@ public class ActionTranslator implements ActionSplitterListener {
|
||||||
RulePropertyRef getRulePropertyRef(Token prop) {
|
RulePropertyRef getRulePropertyRef(Token prop) {
|
||||||
try {
|
try {
|
||||||
Class c = thisRulePropToModelMap.get(prop.getText());
|
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 ref =
|
||||||
(RulePropertyRef)ctor.newInstance(getRuleLabel(prop.getText()));
|
(RulePropertyRef)ctor.newInstance(nodeContext, getRuleLabel(prop.getText()));
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
@ -254,9 +259,9 @@ public class ActionTranslator implements ActionSplitterListener {
|
||||||
Grammar g = factory.getGrammar();
|
Grammar g = factory.getGrammar();
|
||||||
try {
|
try {
|
||||||
Class c = rulePropToModelMap.get(prop.getText());
|
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 ref =
|
||||||
(RulePropertyRef)ctor.newInstance(getRuleLabel(x.getText()));
|
(RulePropertyRef)ctor.newInstance(nodeContext, getRuleLabel(x.getText()));
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class CodeGenPipeline {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gen.writeRecognizer(gen.generateParser());
|
gen.writeRecognizer(gen.generateParser());
|
||||||
if ( g.tool.genListener) {
|
if ( g.tool.gen_listener) {
|
||||||
gen.writeListener(gen.generateListener());
|
gen.writeListener(gen.generateListener());
|
||||||
gen.writeBlankListener(gen.generateBlankListener());
|
gen.writeBlankListener(gen.generateBlankListener());
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,6 +303,7 @@ public class CodeGenerator {
|
||||||
* TListener.java, if we're using the Java target.
|
* TListener.java, if we're using the Java target.
|
||||||
*/
|
*/
|
||||||
public String getListenerFileName() {
|
public String getListenerFileName() {
|
||||||
|
assert g.name != null;
|
||||||
ST extST = templates.getInstanceOf("codeFileExtension");
|
ST extST = templates.getInstanceOf("codeFileExtension");
|
||||||
String listenerName = g.name + "Listener";
|
String listenerName = g.name + "Listener";
|
||||||
return listenerName+extST.render();
|
return listenerName+extST.render();
|
||||||
|
@ -312,8 +313,9 @@ public class CodeGenerator {
|
||||||
* such as BlankTListener.java, if we're using the Java target.
|
* such as BlankTListener.java, if we're using the Java target.
|
||||||
*/
|
*/
|
||||||
public String getBlankListenerFileName() {
|
public String getBlankListenerFileName() {
|
||||||
|
assert g.name != null;
|
||||||
ST extST = templates.getInstanceOf("codeFileExtension");
|
ST extST = templates.getInstanceOf("codeFileExtension");
|
||||||
String listenerName = "Blank" + g.name + "Listener";
|
String listenerName = g.name + "BaseListener";
|
||||||
return listenerName+extST.render();
|
return listenerName+extST.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,18 +29,12 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen;
|
package org.antlr.v4.codegen;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.model.OutputModelObject;
|
import org.antlr.v4.codegen.model.*;
|
||||||
import org.antlr.v4.codegen.model.RuleFunction;
|
import org.antlr.v4.codegen.model.decl.*;
|
||||||
import org.antlr.v4.codegen.model.SrcOp;
|
import org.antlr.v4.runtime.misc.*;
|
||||||
import org.antlr.v4.codegen.model.decl.CodeBlock;
|
import org.antlr.v4.tool.*;
|
||||||
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 java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/** Create output objects for elements *within* rule functions except
|
/** Create output objects for elements *within* rule functions except
|
||||||
* buildOutputModel() which builds outer/root model object and any
|
* buildOutputModel() which builds outer/root model object and any
|
||||||
|
@ -66,6 +60,11 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputModelController getController() {
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
|
||||||
// Convenience methods
|
// Convenience methods
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -87,7 +86,7 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
|
||||||
public CodeBlock getCurrentBlock() { return controller.getCurrentBlock(); }
|
public CodeBlock getCurrentBlock() { return controller.getCurrentBlock(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CodeBlock getCurrentOuterMostAlternativeBlock() { return controller.getCurrentOuterMostAlternativeBlock(); }
|
public CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock() { return controller.getCurrentOuterMostAlternativeBlock(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCodeBlockLevel() { return controller.codeBlockLevel; }
|
public int getCodeBlockLevel() { return controller.codeBlockLevel; }
|
||||||
|
|
|
@ -72,8 +72,7 @@ public class OutputModelController {
|
||||||
public Stack<RuleFunction> currentRule = new Stack<RuleFunction>();
|
public Stack<RuleFunction> currentRule = new Stack<RuleFunction>();
|
||||||
public Alternative currentOuterMostAlt;
|
public Alternative currentOuterMostAlt;
|
||||||
public CodeBlock currentBlock;
|
public CodeBlock currentBlock;
|
||||||
public CodeBlock currentOuterMostAlternativeBlock;
|
public CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock;
|
||||||
|
|
||||||
|
|
||||||
public OutputModelController(OutputModelFactory factory) {
|
public OutputModelController(OutputModelFactory factory) {
|
||||||
this.delegate = factory;
|
this.delegate = factory;
|
||||||
|
@ -121,7 +120,7 @@ public class OutputModelController {
|
||||||
|
|
||||||
public OutputModelObject buildBlankListenerOutputModel() {
|
public OutputModelObject buildBlankListenerOutputModel() {
|
||||||
CodeGenerator gen = delegate.getGenerator();
|
CodeGenerator gen = delegate.getGenerator();
|
||||||
return new BlankListenerFile(delegate, gen.getBlankListenerFileName());
|
return new BaseListenerFile(delegate, gen.getBlankListenerFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParserFile parserFile(String fileName) {
|
public ParserFile parserFile(String fileName) {
|
||||||
|
@ -151,6 +150,7 @@ public class OutputModelController {
|
||||||
RuleFunction function = rule(r);
|
RuleFunction function = rule(r);
|
||||||
parser.funcs.add(function);
|
parser.funcs.add(function);
|
||||||
pushCurrentRule(function);
|
pushCurrentRule(function);
|
||||||
|
function.fillNamedActions(delegate, r);
|
||||||
|
|
||||||
if ( r instanceof LeftRecursiveRule ) {
|
if ( r instanceof LeftRecursiveRule ) {
|
||||||
buildLeftRecursiveRuleFunction((LeftRecursiveRule)r,
|
buildLeftRecursiveRuleFunction((LeftRecursiveRule)r,
|
||||||
|
@ -214,36 +214,39 @@ public class OutputModelController {
|
||||||
if ( altInfo.altLabel==null ) continue;
|
if ( altInfo.altLabel==null ) continue;
|
||||||
ST altActionST = codegenTemplates.getInstanceOf("recRuleReplaceContext");
|
ST altActionST = codegenTemplates.getInstanceOf("recRuleReplaceContext");
|
||||||
altActionST.add("ctxName", altInfo.altLabel);
|
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);
|
CodeBlockForAlt alt = primaryAltsCode.get(i);
|
||||||
alt.insertOp(0, altAction);
|
alt.insertOp(0, altAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert code to set ctx.stop after primary block and before op * loop
|
// Insert code to set ctx.stop after primary block and before op * loop
|
||||||
ST setStopTokenAST = codegenTemplates.getInstanceOf("recRuleSetStopToken");
|
ST setStopTokenAST = codegenTemplates.getInstanceOf("recRuleSetStopToken");
|
||||||
Action setStopTokenAction = new Action(delegate, setStopTokenAST.render());
|
Action setStopTokenAction = new Action(delegate, function.ruleCtx, setStopTokenAST);
|
||||||
outerAlt.insertOp(1, setStopTokenAction);
|
outerAlt.insertOp(1, setStopTokenAction);
|
||||||
|
|
||||||
// Insert code to set _prevctx at start of * loop
|
// Insert code to set _prevctx at start of * loop
|
||||||
ST setPrevCtx = codegenTemplates.getInstanceOf("recRuleSetPrevCtx");
|
ST setPrevCtx = codegenTemplates.getInstanceOf("recRuleSetPrevCtx");
|
||||||
Action setPrevCtxAction = new Action(delegate, setPrevCtx.render());
|
Action setPrevCtxAction = new Action(delegate, function.ruleCtx, setPrevCtx);
|
||||||
opAltStarBlock.addIterationOp(setPrevCtxAction);
|
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++) {
|
for (int i = 0; i < opAltsCode.size(); i++) {
|
||||||
ST altActionST;
|
ST altActionST;
|
||||||
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
|
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
|
||||||
if ( altInfo.altLabel!=null ) {
|
if ( altInfo.altLabel!=null ) {
|
||||||
altActionST = codegenTemplates.getInstanceOf("recRuleLabeledAltStartAction");
|
altActionST = codegenTemplates.getInstanceOf("recRuleLabeledAltStartAction");
|
||||||
altActionST.add("ctxName", altInfo.altLabel);
|
altActionST.add("currentAltLabel", altInfo.altLabel);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
altActionST = codegenTemplates.getInstanceOf("recRuleAltStartAction");
|
altActionST = codegenTemplates.getInstanceOf("recRuleAltStartAction");
|
||||||
altActionST.add("ctxName", r.name);
|
altActionST.add("ctxName", r.name);
|
||||||
}
|
}
|
||||||
altActionST.add("ruleName", r.name);
|
altActionST.add("ruleName", r.name);
|
||||||
|
// add label of any lr ref we deleted
|
||||||
altActionST.add("label", altInfo.leftRecursiveRuleRefLabel);
|
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);
|
CodeBlockForAlt alt = opAltsCode.get(i);
|
||||||
alt.insertOp(0, altAction);
|
alt.insertOp(0, altAction);
|
||||||
}
|
}
|
||||||
|
@ -312,7 +315,9 @@ public class OutputModelController {
|
||||||
|
|
||||||
public CodeBlockForAlt alternative(Alternative alt, boolean outerMost) {
|
public CodeBlockForAlt alternative(Alternative alt, boolean outerMost) {
|
||||||
CodeBlockForAlt blk = delegate.alternative(alt, 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);
|
for (CodeGeneratorExtension ext : extensions) blk = ext.alternative(blk, outerMost);
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
@ -431,15 +436,13 @@ public class OutputModelController {
|
||||||
return currentBlock;
|
return currentBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentOuterMostAlternativeBlock(CodeBlock currentOuterMostAlternativeBlock) {
|
public void setCurrentOuterMostAlternativeBlock(CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock) {
|
||||||
this.currentOuterMostAlternativeBlock = currentOuterMostAlternativeBlock;
|
this.currentOuterMostAlternativeBlock = currentOuterMostAlternativeBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeBlock getCurrentOuterMostAlternativeBlock() {
|
public CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock() {
|
||||||
return currentOuterMostAlternativeBlock;
|
return currentOuterMostAlternativeBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCodeBlockLevel() { return codeBlockLevel; }
|
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.*;
|
||||||
import org.antlr.v4.codegen.model.decl.CodeBlock;
|
import org.antlr.v4.codegen.model.decl.CodeBlock;
|
||||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||||
import org.antlr.v4.tool.Alternative;
|
import org.antlr.v4.tool.*;
|
||||||
import org.antlr.v4.tool.Grammar;
|
import org.antlr.v4.tool.ast.*;
|
||||||
import org.antlr.v4.tool.Rule;
|
|
||||||
import org.antlr.v4.tool.ast.BlockAST;
|
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -47,6 +44,8 @@ public interface OutputModelFactory {
|
||||||
|
|
||||||
void setController(OutputModelController controller);
|
void setController(OutputModelController controller);
|
||||||
|
|
||||||
|
OutputModelController getController();
|
||||||
|
|
||||||
ParserFile parserFile(String fileName);
|
ParserFile parserFile(String fileName);
|
||||||
|
|
||||||
Parser parser(ParserFile file);
|
Parser parser(ParserFile file);
|
||||||
|
@ -109,7 +108,7 @@ public interface OutputModelFactory {
|
||||||
|
|
||||||
CodeBlock getCurrentBlock();
|
CodeBlock getCurrentBlock();
|
||||||
|
|
||||||
CodeBlock getCurrentOuterMostAlternativeBlock();
|
CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock();
|
||||||
|
|
||||||
int getCodeBlockLevel();
|
int getCodeBlockLevel();
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,8 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
||||||
return new LeftRecursiveRuleFunction(this, (LeftRecursiveRule)r);
|
return new LeftRecursiveRuleFunction(this, (LeftRecursiveRule)r);
|
||||||
}
|
}
|
||||||
else {
|
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);
|
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 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);
|
if ( controller.needsImplicitLabel(ID, invokeOp) ) defineImplicitLabel(ID, invokeOp);
|
||||||
AddToLabelList listLabelOp = getListLabelIfPresent(invokeOp, label);
|
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(invokeOp, label);
|
||||||
return list(invokeOp, listLabelOp);
|
return list(invokeOp, listLabelOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,16 +100,29 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
||||||
LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID);
|
LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID);
|
||||||
if ( labelAST!=null ) {
|
if ( labelAST!=null ) {
|
||||||
String label = labelAST.getText();
|
String label = labelAST.getText();
|
||||||
Decl d = getTokenLabelDecl(label);
|
RuleFunction rf = getCurrentRuleFunction();
|
||||||
((MatchToken)matchOp).labels.add(d);
|
|
||||||
getCurrentRuleFunction().addContextDecl(d);
|
|
||||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||||
|
// add Token _X and List<Token> X decls
|
||||||
|
defineImplicitLabel(ID, matchOp); // adds _X
|
||||||
TokenListDecl l = getTokenListLabelDecl(label);
|
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);
|
if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp);
|
||||||
AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, labelAST);
|
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(matchOp, labelAST);
|
||||||
return list(matchOp, listLabelOp);
|
return list(matchOp, listLabelOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,14 +143,14 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
||||||
String label = labelAST.getText();
|
String label = labelAST.getText();
|
||||||
Decl d = getTokenLabelDecl(label);
|
Decl d = getTokenLabelDecl(label);
|
||||||
((MatchSet)matchOp).labels.add(d);
|
((MatchSet)matchOp).labels.add(d);
|
||||||
getCurrentRuleFunction().addContextDecl(d);
|
getCurrentRuleFunction().addContextDecl(setAST.getAltLabel(), d);
|
||||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||||
TokenListDecl l = getTokenListLabelDecl(label);
|
TokenListDecl l = getTokenListLabelDecl(label);
|
||||||
getCurrentRuleFunction().addContextDecl(l);
|
getCurrentRuleFunction().addContextDecl(setAST.getAltLabel(), l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( controller.needsImplicitLabel(setAST, matchOp) ) defineImplicitLabel(setAST, matchOp);
|
if ( controller.needsImplicitLabel(setAST, matchOp) ) defineImplicitLabel(setAST, matchOp);
|
||||||
AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, labelAST);
|
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(matchOp, labelAST);
|
||||||
return list(matchOp, listLabelOp);
|
return list(matchOp, listLabelOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,14 +162,14 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
||||||
String label = labelAST.getText();
|
String label = labelAST.getText();
|
||||||
Decl d = getTokenLabelDecl(label);
|
Decl d = getTokenLabelDecl(label);
|
||||||
wild.labels.add(d);
|
wild.labels.add(d);
|
||||||
getCurrentRuleFunction().addContextDecl(d);
|
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d);
|
||||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||||
TokenListDecl l = getTokenListLabelDecl(label);
|
TokenListDecl l = getTokenListLabelDecl(label);
|
||||||
getCurrentRuleFunction().addContextDecl(l);
|
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( controller.needsImplicitLabel(ast, wild) ) defineImplicitLabel(ast, wild);
|
if ( controller.needsImplicitLabel(ast, wild) ) defineImplicitLabel(ast, wild);
|
||||||
AddToLabelList listLabelOp = getListLabelIfPresent(wild, labelAST);
|
AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(wild, labelAST);
|
||||||
return list(wild, listLabelOp);
|
return list(wild, listLabelOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,11 +187,11 @@ public class ParserFactory extends DefaultOutputModelFactory {
|
||||||
String label = labelAST.getText();
|
String label = labelAST.getText();
|
||||||
Decl d = getTokenLabelDecl(label);
|
Decl d = getTokenLabelDecl(label);
|
||||||
c.label = d;
|
c.label = d;
|
||||||
getCurrentRuleFunction().addContextDecl(d);
|
getCurrentRuleFunction().addContextDecl(labelAST.getAltLabel(), d);
|
||||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||||
String listLabel = gen.target.getListLabel(label);
|
String listLabel = gen.target.getListLabel(label);
|
||||||
TokenListDecl l = new TokenListDecl(this, listLabel);
|
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);
|
op.getLabels().add(d);
|
||||||
// all labels must be in scope struct in case we exec action out of context
|
// 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;
|
AddToLabelList labelOp = null;
|
||||||
if ( label!=null && label.parent.getType()==ANTLRParser.PLUS_ASSIGN ) {
|
if ( label!=null && label.parent.getType()==ANTLRParser.PLUS_ASSIGN ) {
|
||||||
String listLabel = gen.target.getListLabel(label.getText());
|
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]
|
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)
|
// set alt if outer ALT only (the only ones with alt field set to Alternative object)
|
||||||
if ( outerMost ) controller.setCurrentOuterMostAlt(((AltAST)$start).alt);
|
AltAST altAST = (AltAST)retval.start;
|
||||||
List<SrcOp> elems = new ArrayList<SrcOp>();
|
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 = controller.alternative(controller.getCurrentOuterMostAlt(), outerMost);
|
||||||
$altCodeBlock.ops = $ops = elems;
|
$altCodeBlock.ops = $ops = elems;
|
||||||
controller.setCurrentBlock($altCodeBlock);
|
controller.setCurrentBlock($altCodeBlock);
|
||||||
|
|
|
@ -30,16 +30,14 @@
|
||||||
package org.antlr.v4.codegen.model;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.runtime.CommonToken;
|
import org.antlr.runtime.CommonToken;
|
||||||
import org.antlr.v4.codegen.ActionTranslator;
|
import org.antlr.v4.codegen.*;
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.model.chunk.*;
|
||||||
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
import org.antlr.v4.codegen.model.chunk.ActionText;
|
|
||||||
import org.antlr.v4.parse.ANTLRParser;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.tool.ast.ActionAST;
|
import org.antlr.v4.tool.ast.*;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
import org.stringtemplate.v4.ST;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class Action extends RuleElement {
|
public class Action extends RuleElement {
|
||||||
|
@ -57,7 +55,7 @@ public class Action extends RuleElement {
|
||||||
//System.out.println("actions="+chunks);
|
//System.out.println("actions="+chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action(OutputModelFactory factory, String action) {
|
public Action(OutputModelFactory factory, StructDecl ctx, String action) {
|
||||||
super(factory,null);
|
super(factory,null);
|
||||||
ActionAST ast = new ActionAST(new CommonToken(ANTLRParser.ACTION, action));
|
ActionAST ast = new ActionAST(new CommonToken(ANTLRParser.ACTION, action));
|
||||||
RuleFunction rf = factory.getCurrentRuleFunction();
|
RuleFunction rf = factory.getCurrentRuleFunction();
|
||||||
|
@ -67,7 +65,14 @@ public class Action extends RuleElement {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
chunks = new ArrayList<ActionChunk>();
|
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) */
|
/** Contains Rewrite block (usually as last op) */
|
||||||
public class CodeBlockForAlt extends CodeBlock {
|
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;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.ActionTranslator;
|
import org.antlr.v4.codegen.*;
|
||||||
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.ActionChunk;
|
||||||
import org.antlr.v4.codegen.model.decl.Decl;
|
import org.antlr.v4.codegen.model.decl.*;
|
||||||
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
|
|
||||||
import org.antlr.v4.codegen.model.decl.RuleContextListDecl;
|
|
||||||
import org.antlr.v4.parse.ANTLRParser;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.runtime.atn.RuleTransition;
|
import org.antlr.v4.runtime.atn.RuleTransition;
|
||||||
import org.antlr.v4.runtime.misc.OrderedHashSet;
|
import org.antlr.v4.runtime.misc.OrderedHashSet;
|
||||||
import org.antlr.v4.tool.Rule;
|
import org.antlr.v4.tool.Rule;
|
||||||
import org.antlr.v4.tool.ast.ActionAST;
|
import org.antlr.v4.tool.ast.*;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -72,11 +67,11 @@ public class InvokeRule extends RuleElement implements LabeledOp {
|
||||||
String label = labelAST.getText();
|
String label = labelAST.getText();
|
||||||
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
||||||
labels.add(d);
|
labels.add(d);
|
||||||
rf.addContextDecl(d);
|
rf.addContextDecl(ast.getAltLabel(), d);
|
||||||
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
|
||||||
String listLabel = gen.target.getListLabel(label);
|
String listLabel = gen.target.getListLabel(label);
|
||||||
RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, ctxName);
|
RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, ctxName);
|
||||||
rf.addContextDecl(l);
|
rf.addContextDecl(ast.getAltLabel(), l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ast.getChildCount()>0 ) {
|
if ( ast.getChildCount()>0 ) {
|
||||||
|
@ -89,15 +84,8 @@ public class InvokeRule extends RuleElement implements LabeledOp {
|
||||||
String label = gen.target.getImplicitRuleLabel(ast.getText());
|
String label = gen.target.getImplicitRuleLabel(ast.getText());
|
||||||
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
||||||
labels.add(d);
|
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() {
|
public List<Decl> getLabels() {
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.antlr.v4.codegen.model.decl.Decl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** */
|
/** All the rule elements we can label like tokens, rules, sets, wildcard. */
|
||||||
public interface LabeledOp {
|
public interface LabeledOp {
|
||||||
public List<Decl> getLabels();
|
public List<Decl> getLabels();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,34 +29,35 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.CodeGenerator;
|
import org.antlr.v4.codegen.*;
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.model.decl.*;
|
||||||
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
|
import org.antlr.v4.misc.Pair;
|
||||||
import org.antlr.v4.tool.LabelElementPair;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.tool.LabelType;
|
import org.antlr.v4.tool.*;
|
||||||
import org.antlr.v4.tool.LeftRecursiveRule;
|
import org.antlr.v4.tool.ast.GrammarAST;
|
||||||
import org.antlr.v4.tool.Rule;
|
|
||||||
import org.stringtemplate.v4.misc.MultiMap;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class LeftRecursiveRuleFunction extends RuleFunction {
|
public class LeftRecursiveRuleFunction extends RuleFunction {
|
||||||
public LeftRecursiveRuleFunction(OutputModelFactory factory, LeftRecursiveRule r) {
|
public LeftRecursiveRuleFunction(OutputModelFactory factory, LeftRecursiveRule r) {
|
||||||
super(factory, 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();
|
CodeGenerator gen = factory.getGenerator();
|
||||||
MultiMap<String,LabelElementPair> labelDefs = r.alt[1].labelDefs;
|
// Since we delete x=lr, we have to manually add decls for all labels
|
||||||
Set<String> labels = labelDefs.keySet();
|
// on left-recur refs to proper structs
|
||||||
for (Iterator<String> iterator = labels.iterator(); iterator.hasNext(); ) {
|
for (Pair<GrammarAST,String> pair : r.leftRecursiveRuleRefLabels) {
|
||||||
String label = iterator.next();
|
GrammarAST idAST = pair.a;
|
||||||
LabelElementPair l = r.getAnyLabelDef(label);
|
String altLabel = pair.b;
|
||||||
Rule targetRule = factory.getGrammar().getRule(l.element.getText());
|
String label = idAST.getText();
|
||||||
if ( l.type == LabelType.RULE_LABEL ) {
|
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);
|
String ctxName = gen.target.getRuleFunctionContextStructName(targetRule);
|
||||||
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
|
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;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
import org.antlr.v4.tool.Grammar;
|
import org.antlr.v4.misc.Triple;
|
||||||
import org.antlr.v4.tool.Rule;
|
import org.antlr.v4.tool.*;
|
||||||
import org.antlr.v4.tool.ast.ActionAST;
|
import org.antlr.v4.tool.ast.*;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/** A model object representing a parse tree listener file.
|
/** A model object representing a parse tree listener file.
|
||||||
* These are the rules specific events triggered by a parse tree visitor.
|
* These are the rules specific events triggered by a parse tree visitor.
|
||||||
|
@ -26,11 +24,11 @@ public class ListenerFile extends OutputFile {
|
||||||
parserName = g.getRecognizerName();
|
parserName = g.getRecognizerName();
|
||||||
grammarName = g.name;
|
grammarName = g.name;
|
||||||
for (Rule r : g.rules.values()) {
|
for (Rule r : g.rules.values()) {
|
||||||
List<String> labels = r.getAltLabels();
|
List<Triple<Integer,AltAST,String>> labels = r.getAltLabels();
|
||||||
listenerNames.add(r.name);
|
listenerNames.add(r.name);
|
||||||
if ( labels!=null ) {
|
if ( labels!=null ) {
|
||||||
for (String label : labels) {
|
for (Triple<Integer,AltAST,String> pair : labels) {
|
||||||
listenerNames.add(label);
|
listenerNames.add(pair.c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,9 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.CodeGenerator;
|
import org.antlr.v4.codegen.*;
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.model.chunk.*;
|
||||||
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
import org.antlr.v4.tool.*;
|
||||||
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 java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -86,7 +82,7 @@ public class Parser extends OutputModelObject {
|
||||||
rules = g.rules.values();
|
rules = g.rules.values();
|
||||||
atn = new SerializedATN(factory, g.atn);
|
atn = new SerializedATN(factory, g.atn);
|
||||||
if (g.getOptionString("superClass") != null) {
|
if (g.getOptionString("superClass") != null) {
|
||||||
superclass = new ActionText(g.getOptionString("superClass"));
|
superclass = new ActionText(null, g.getOptionString("superClass"));
|
||||||
} else {
|
} else {
|
||||||
superclass = new DefaultParserSuperClass();
|
superclass = new DefaultParserSuperClass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,18 +30,22 @@
|
||||||
package org.antlr.v4.codegen.model;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
import org.antlr.v4.codegen.model.decl.AltLabelStructDecl;
|
import org.antlr.v4.codegen.model.decl.*;
|
||||||
import org.antlr.v4.codegen.model.decl.Decl;
|
import org.antlr.v4.misc.FrequencySet;
|
||||||
import org.antlr.v4.codegen.model.decl.StructDecl;
|
import org.antlr.v4.misc.Triple;
|
||||||
import org.antlr.v4.misc.Utils;
|
import org.antlr.v4.misc.Utils;
|
||||||
import org.antlr.v4.runtime.atn.ATNState;
|
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.runtime.misc.OrderedHashSet;
|
||||||
import org.antlr.v4.tool.Attribute;
|
import org.antlr.v4.tool.Attribute;
|
||||||
import org.antlr.v4.tool.Rule;
|
import org.antlr.v4.tool.Rule;
|
||||||
|
import org.antlr.v4.tool.ast.AltAST;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
import org.antlr.v4.tool.ast.GrammarAST;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.antlr.v4.parse.ANTLRParser.*;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RuleFunction extends OutputModelObject {
|
public class RuleFunction extends OutputModelObject {
|
||||||
public String name;
|
public String name;
|
||||||
|
@ -54,12 +58,13 @@ public class RuleFunction extends OutputModelObject {
|
||||||
public int index;
|
public int index;
|
||||||
public Collection<Attribute> args = null;
|
public Collection<Attribute> args = null;
|
||||||
public Rule rule;
|
public Rule rule;
|
||||||
|
public AltLabelStructDecl[] altToContext;
|
||||||
|
|
||||||
@ModelElement public List<SrcOp> code;
|
@ModelElement public List<SrcOp> code;
|
||||||
@ModelElement public OrderedHashSet<Decl> locals; // TODO: move into ctx?
|
@ModelElement public OrderedHashSet<Decl> locals; // TODO: move into ctx?
|
||||||
@ModelElement public StructDecl ruleCtx;
|
@ModelElement public StructDecl ruleCtx;
|
||||||
@ModelElement public Set<AltLabelStructDecl> altLabelCtxs;
|
@ModelElement public Map<String,AltLabelStructDecl> altLabelCtxs;
|
||||||
@ModelElement public Map<String, Action> namedActions;
|
@ModelElement public Map<String,Action> namedActions;
|
||||||
@ModelElement public Action finallyAction;
|
@ModelElement public Action finallyAction;
|
||||||
@ModelElement public List<SrcOp> postamble;
|
@ModelElement public List<SrcOp> postamble;
|
||||||
|
|
||||||
|
@ -76,12 +81,33 @@ public class RuleFunction extends OutputModelObject {
|
||||||
index = r.index;
|
index = r.index;
|
||||||
|
|
||||||
ruleCtx = new StructDecl(factory, r);
|
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 ) {
|
if ( labels!=null ) {
|
||||||
altLabelCtxs = new HashSet<AltLabelStructDecl>();
|
for (Triple<Integer,AltAST,String> pair : labels) {
|
||||||
for (String label : labels) {
|
Integer altNum = pair.a;
|
||||||
altLabelCtxs.add(new AltLabelStructDecl(factory, r, label));
|
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);
|
exceptions = Utils.nodesToStrings(r.exceptionActions);
|
||||||
if ( r.finallyAction!=null ) finallyAction = new Action(factory, r.finallyAction);
|
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>();
|
namedActions = new HashMap<String, Action>();
|
||||||
for (String name : r.namedActions.keySet()) {
|
for (String name : r.namedActions.keySet()) {
|
||||||
GrammarAST ast = r.namedActions.get(name);
|
GrammarAST ast = r.namedActions.get(name);
|
||||||
namedActions.put(name, new Action(factory, ast));
|
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 */
|
/** Add local var decl */
|
||||||
|
@ -118,8 +231,19 @@ public class RuleFunction extends OutputModelObject {
|
||||||
d.isLocal = true;
|
d.isLocal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add decl to struct ctx */
|
/** Add decl to struct ctx for rule or alt if labeled */
|
||||||
public void addContextDecl(Decl d) {
|
public void addContextDecl(String altLabel, Decl d) {
|
||||||
ruleCtx.addDecl(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;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
|
import org.antlr.v4.codegen.model.decl.CodeBlock;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
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:
|
/** All operations know in which block they live:
|
||||||
*
|
*
|
||||||
* CodeBlockForAlt, TreeRewrite, STRewrite
|
* CodeBlock, CodeBlockForAlt
|
||||||
*
|
*
|
||||||
* Templates might need to know block nesting level or find
|
* Templates might need to know block nesting level or find
|
||||||
* a specific declaration, etc...
|
* a specific declaration, etc...
|
||||||
*/
|
*/
|
||||||
public SrcOp enclosingBlock;
|
public CodeBlock enclosingBlock;
|
||||||
|
|
||||||
|
public RuleFunction enclosingRuleRunction;
|
||||||
|
|
||||||
public SrcOp(OutputModelFactory factory) { this(factory,null); }
|
public SrcOp(OutputModelFactory factory) { this(factory,null); }
|
||||||
public SrcOp(OutputModelFactory factory, GrammarAST ast) {
|
public SrcOp(OutputModelFactory factory, GrammarAST ast) {
|
||||||
super(factory,ast);
|
super(factory,ast);
|
||||||
if ( ast!=null ) uniqueID = ast.token.getTokenIndex();
|
if ( ast!=null ) uniqueID = ast.token.getTokenIndex();
|
||||||
enclosingBlock = factory.getCurrentBlock();
|
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;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
|
import org.antlr.v4.misc.Triple;
|
||||||
import org.antlr.v4.tool.Rule;
|
import org.antlr.v4.tool.Rule;
|
||||||
|
import org.antlr.v4.tool.ast.AltAST;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -12,7 +14,7 @@ public class VisitorDispatchMethod extends OutputModelObject {
|
||||||
public VisitorDispatchMethod(OutputModelFactory factory, Rule r, boolean isEnter) {
|
public VisitorDispatchMethod(OutputModelFactory factory, Rule r, boolean isEnter) {
|
||||||
super(factory);
|
super(factory);
|
||||||
this.isEnter = isEnter;
|
this.isEnter = isEnter;
|
||||||
List<String> label = r.getAltLabels();
|
List<Triple<Integer,AltAST,String>> label = r.getAltLabels();
|
||||||
if ( label!=null ) listenerName = label.get(0);
|
if ( label!=null ) listenerName = label.get(0).c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,14 @@
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.model.OutputModelObject;
|
import org.antlr.v4.codegen.model.OutputModelObject;
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ActionChunk extends OutputModelObject {
|
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;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ActionText extends ActionChunk {
|
public class ActionText extends ActionChunk {
|
||||||
public String text;
|
public String text;
|
||||||
|
|
||||||
public ActionText(String text) {
|
public ActionText(StructDecl ctx, String text) {
|
||||||
|
super(ctx);
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ArgRef extends LocalRef {
|
public class ArgRef extends LocalRef {
|
||||||
public ArgRef(String name) {
|
public ArgRef(StructDecl ctx, String name) {
|
||||||
super(name);
|
super(ctx, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,5 @@
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class DefaultParserSuperClass extends ActionChunk {
|
public class DefaultParserSuperClass extends ActionChunk {
|
||||||
|
public DefaultParserSuperClass() { super(null); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,13 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
public class LabelRef extends ActionChunk {
|
public class LabelRef extends ActionChunk {
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
public LabelRef(String name) {
|
public LabelRef(StructDecl ctx, String name) {
|
||||||
|
super(ctx);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,12 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class LexerSetAttr extends SetAttr {
|
public class LexerSetAttr extends SetAttr {
|
||||||
public LexerSetAttr(String name, List<ActionChunk> rhsChunks) {
|
public LexerSetAttr(StructDecl ctx, String name, List<ActionChunk> rhsChunks) {
|
||||||
super(name, rhsChunks);
|
super(ctx, name, rhsChunks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
public class ListLabelRef extends LabelRef {
|
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;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
public class LocalRef extends ActionChunk {
|
public class LocalRef extends ActionChunk {
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
public LocalRef(String name) {
|
public LocalRef(StructDecl ctx, String name) {
|
||||||
|
super(ctx);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,15 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
public class NonLocalAttrRef extends ActionChunk {
|
public class NonLocalAttrRef extends ActionChunk {
|
||||||
public String ruleName;
|
public String ruleName;
|
||||||
public String name;
|
public String name;
|
||||||
public int ruleIndex;
|
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.name = name;
|
||||||
this.ruleName = ruleName;
|
this.ruleName = ruleName;
|
||||||
this.ruleIndex = ruleIndex;
|
this.ruleIndex = ruleIndex;
|
||||||
|
|
|
@ -29,11 +29,13 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class QRetValueRef extends RetValueRef {
|
public class QRetValueRef extends RetValueRef {
|
||||||
public String dict;
|
public String dict;
|
||||||
public QRetValueRef(String dict, String name) {
|
public QRetValueRef(StructDecl ctx, String dict, String name) {
|
||||||
super(name);
|
super(ctx,name);
|
||||||
this.dict = dict;
|
this.dict = dict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,14 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RetValueRef extends ActionChunk {
|
public class RetValueRef extends ActionChunk {
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
public RetValueRef(String name) {
|
public RetValueRef(StructDecl ctx, String name) {
|
||||||
|
super(ctx);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,14 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef extends ActionChunk {
|
public class RulePropertyRef extends ActionChunk {
|
||||||
public String label;
|
public String label;
|
||||||
|
|
||||||
public RulePropertyRef(String label) {
|
public RulePropertyRef(StructDecl ctx, String label) {
|
||||||
|
super(ctx);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,10 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
public class RulePropertyRef_ctx extends RulePropertyRef {
|
public class RulePropertyRef_ctx extends RulePropertyRef {
|
||||||
public RulePropertyRef_ctx(String label) {
|
public RulePropertyRef_ctx(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef_start extends RulePropertyRef {
|
public class RulePropertyRef_start extends RulePropertyRef {
|
||||||
public RulePropertyRef_start(String label) {
|
public RulePropertyRef_start(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef_stop extends RulePropertyRef {
|
public class RulePropertyRef_stop extends RulePropertyRef {
|
||||||
public RulePropertyRef_stop(String label) {
|
public RulePropertyRef_stop(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef_text extends RulePropertyRef {
|
public class RulePropertyRef_text extends RulePropertyRef {
|
||||||
public RulePropertyRef_text(String label) {
|
public RulePropertyRef_text(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.model.ModelElement;
|
import org.antlr.v4.codegen.model.ModelElement;
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -38,17 +39,9 @@ public class SetAttr extends ActionChunk {
|
||||||
public String name;
|
public String name;
|
||||||
@ModelElement public List<ActionChunk> rhsChunks;
|
@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.name = name;
|
||||||
this.rhsChunks = rhsChunks;
|
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;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SetNonLocalAttr extends SetAttr {
|
public class SetNonLocalAttr extends SetAttr {
|
||||||
public String ruleName;
|
public String ruleName;
|
||||||
public int ruleIndex;
|
public int ruleIndex;
|
||||||
|
|
||||||
public SetNonLocalAttr(String ruleName, String name, int ruleIndex,
|
public SetNonLocalAttr(StructDecl ctx,
|
||||||
|
String ruleName, String name, int ruleIndex,
|
||||||
List<ActionChunk> rhsChunks)
|
List<ActionChunk> rhsChunks)
|
||||||
{
|
{
|
||||||
super(name, rhsChunks);
|
super(ctx, name, rhsChunks);
|
||||||
this.ruleName = ruleName;
|
this.ruleName = ruleName;
|
||||||
this.ruleIndex = ruleIndex;
|
this.ruleIndex = ruleIndex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,10 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
public class ThisRulePropertyRef_ctx extends RulePropertyRef {
|
public class ThisRulePropertyRef_ctx extends RulePropertyRef {
|
||||||
public ThisRulePropertyRef_ctx(String label) {
|
public ThisRulePropertyRef_ctx(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ThisRulePropertyRef_start extends RulePropertyRef {
|
public class ThisRulePropertyRef_start extends RulePropertyRef {
|
||||||
public ThisRulePropertyRef_start(String label) {
|
public ThisRulePropertyRef_start(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ThisRulePropertyRef_stop extends RulePropertyRef {
|
public class ThisRulePropertyRef_stop extends RulePropertyRef {
|
||||||
public ThisRulePropertyRef_stop(String label) {
|
public ThisRulePropertyRef_stop(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ThisRulePropertyRef_text extends RulePropertyRef {
|
public class ThisRulePropertyRef_text extends RulePropertyRef {
|
||||||
public ThisRulePropertyRef_text(String label) {
|
public ThisRulePropertyRef_text(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,14 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef extends ActionChunk {
|
public class TokenPropertyRef extends ActionChunk {
|
||||||
public String label;
|
public String label;
|
||||||
|
|
||||||
public TokenPropertyRef(String label) {
|
public TokenPropertyRef(StructDecl ctx, String label) {
|
||||||
|
super(ctx);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_channel extends TokenPropertyRef {
|
public class TokenPropertyRef_channel extends TokenPropertyRef {
|
||||||
public TokenPropertyRef_channel(String label) {
|
public TokenPropertyRef_channel(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_index extends TokenPropertyRef {
|
public class TokenPropertyRef_index extends TokenPropertyRef {
|
||||||
public TokenPropertyRef_index(String label) {
|
public TokenPropertyRef_index(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_int extends TokenPropertyRef {
|
public class TokenPropertyRef_int extends TokenPropertyRef {
|
||||||
public TokenPropertyRef_int(String label) {
|
public TokenPropertyRef_int(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_line extends TokenPropertyRef {
|
public class TokenPropertyRef_line extends TokenPropertyRef {
|
||||||
public TokenPropertyRef_line(String label) {
|
public TokenPropertyRef_line(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_pos extends TokenPropertyRef {
|
public class TokenPropertyRef_pos extends TokenPropertyRef {
|
||||||
public TokenPropertyRef_pos(String label) {
|
public TokenPropertyRef_pos(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_text extends TokenPropertyRef {
|
public class TokenPropertyRef_text extends TokenPropertyRef {
|
||||||
public TokenPropertyRef_text(String label) {
|
public TokenPropertyRef_text(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_type extends TokenPropertyRef {
|
public class TokenPropertyRef_type extends TokenPropertyRef {
|
||||||
public TokenPropertyRef_type(String label) {
|
public TokenPropertyRef_type(StructDecl ctx, String label) {
|
||||||
super(label);
|
super(ctx, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,14 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.chunk;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
|
import org.antlr.v4.codegen.model.decl.StructDecl;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenRef extends ActionChunk {
|
public class TokenRef extends ActionChunk {
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
public TokenRef(String name) {
|
public TokenRef(StructDecl ctx, String name) {
|
||||||
|
super(ctx);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,15 +34,21 @@ import org.antlr.v4.tool.Rule;
|
||||||
|
|
||||||
/** A StructDecl to handle a -> label on alt */
|
/** A StructDecl to handle a -> label on alt */
|
||||||
public class AltLabelStructDecl extends StructDecl {
|
public class AltLabelStructDecl extends StructDecl {
|
||||||
public String label;
|
public int altNum;
|
||||||
public AltLabelStructDecl(OutputModelFactory factory, Rule r, String label) {
|
public AltLabelStructDecl(OutputModelFactory factory, Rule r,
|
||||||
|
int altNum, String label)
|
||||||
|
{
|
||||||
super(factory, r);
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return label.hashCode();
|
return name.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,7 +56,7 @@ public class AltLabelStructDecl extends StructDecl {
|
||||||
if ( obj == this ) return true;
|
if ( obj == this ) return true;
|
||||||
if ( obj.hashCode() != this.hashCode() ) return false;
|
if ( obj.hashCode() != this.hashCode() ) return false;
|
||||||
if ( obj instanceof AltLabelStructDecl ) {
|
if ( obj instanceof AltLabelStructDecl ) {
|
||||||
return label.equals(((AltLabelStructDecl)obj).label);
|
return name.equals(((AltLabelStructDecl)obj).name);
|
||||||
}
|
}
|
||||||
return false;
|
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 name;
|
||||||
public String decl; // whole thing if copied from action
|
public String decl; // whole thing if copied from action
|
||||||
public boolean isLocal; // if local var (not in RuleContext struct)
|
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) {
|
public Decl(OutputModelFactory factory, String name, String decl) {
|
||||||
this(factory, name);
|
this(factory, name);
|
||||||
|
@ -53,8 +54,14 @@ public class Decl extends SrcOp {
|
||||||
return name.hashCode();
|
return name.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** If same name, can't redefine, unless it's a getter */
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
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 String superClass;
|
||||||
public boolean provideCopyFrom;
|
public boolean provideCopyFrom;
|
||||||
@ModelElement public OrderedHashSet<Decl> attrs = new OrderedHashSet<Decl>();
|
@ModelElement public OrderedHashSet<Decl> attrs = new OrderedHashSet<Decl>();
|
||||||
|
@ModelElement public OrderedHashSet<Decl> getters = new OrderedHashSet<Decl>();
|
||||||
@ModelElement public Collection<Attribute> ctorAttrs;
|
@ModelElement public Collection<Attribute> ctorAttrs;
|
||||||
@ModelElement public List<VisitorDispatchMethod> visitorDispatchMethods;
|
@ModelElement public List<VisitorDispatchMethod> visitorDispatchMethods;
|
||||||
@ModelElement public List<OutputModelObject> interfaces;
|
@ModelElement public List<OutputModelObject> interfaces;
|
||||||
|
@ -65,7 +66,11 @@ public class StructDecl extends Decl {
|
||||||
visitorDispatchMethods.add(new VisitorDispatchMethod(factory, r, false));
|
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) {
|
public void addDecl(Attribute a) {
|
||||||
addDecl(new AttributeDecl(factory, a.name, a.decl));
|
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
|
lexerCommand
|
||||||
: id LPAREN lexerCommandExpr RPAREN -> ^(LEXER_ACTION_CALL id lexerCommandExpr)
|
: lexerCommandName LPAREN lexerCommandExpr RPAREN -> ^(LEXER_ACTION_CALL lexerCommandName lexerCommandExpr)
|
||||||
| id
|
| lexerCommandName
|
||||||
;
|
;
|
||||||
|
|
||||||
lexerCommandExpr
|
lexerCommandExpr
|
||||||
|
@ -651,6 +651,11 @@ lexerCommandExpr
|
||||||
| INT
|
| INT
|
||||||
;
|
;
|
||||||
|
|
||||||
|
lexerCommandName
|
||||||
|
: id
|
||||||
|
| MODE ->ID[$MODE]
|
||||||
|
;
|
||||||
|
|
||||||
altList
|
altList
|
||||||
: alternative (OR alternative)* -> alternative+
|
: alternative (OR alternative)* -> alternative+
|
||||||
;
|
;
|
||||||
|
|
|
@ -31,6 +31,10 @@ package org.antlr.v4.tool;
|
||||||
|
|
||||||
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
|
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
|
||||||
import org.antlr.v4.misc.OrderedHashMap;
|
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 org.antlr.v4.tool.ast.RuleAST;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -40,6 +44,10 @@ public class LeftRecursiveRule extends Rule {
|
||||||
public List<LeftRecursiveRuleAltInfo> recPrimaryAlts;
|
public List<LeftRecursiveRuleAltInfo> recPrimaryAlts;
|
||||||
public OrderedHashMap<Integer, LeftRecursiveRuleAltInfo> recOpAlts;
|
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) {
|
public LeftRecursiveRule(Grammar g, String name, RuleAST ast) {
|
||||||
super(g, name, ast, 1);
|
super(g, name, ast, 1);
|
||||||
alt = new Alternative[numberOfAlts+1]; // always just one
|
alt = new Alternative[numberOfAlts+1]; // always just one
|
||||||
|
@ -51,19 +59,46 @@ public class LeftRecursiveRule extends Rule {
|
||||||
return super.hasAltSpecificContexts() || getAltLabels()!=null;
|
return super.hasAltSpecificContexts() || getAltLabels()!=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get -> labels and also those we deleted for left-recursive rules. */
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAltLabels() {
|
public int getOriginalNumberOfAlts() {
|
||||||
List<String> labels = new ArrayList<String>();
|
int n = 0;
|
||||||
List<String> normalAltLabels = super.getAltLabels();
|
if ( recPrimaryAlts!=null ) n += recPrimaryAlts.size();
|
||||||
if ( normalAltLabels!=null ) labels.addAll(normalAltLabels);
|
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++) {
|
for (int i = 0; i < recPrimaryAlts.size(); i++) {
|
||||||
LeftRecursiveRuleAltInfo altInfo = recPrimaryAlts.get(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++) {
|
for (int i = 0; i < recOpAlts.size(); i++) {
|
||||||
LeftRecursiveRuleAltInfo altInfo = recOpAlts.getElement(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;
|
if ( labels.size()==0 ) return null;
|
||||||
return labels;
|
return labels;
|
||||||
|
|
|
@ -29,10 +29,8 @@
|
||||||
|
|
||||||
package org.antlr.v4.tool;
|
package org.antlr.v4.tool;
|
||||||
|
|
||||||
import org.antlr.v4.tool.ast.ActionAST;
|
import org.antlr.v4.misc.Triple;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
import org.antlr.v4.tool.ast.*;
|
||||||
import org.antlr.v4.tool.ast.PredAST;
|
|
||||||
import org.antlr.v4.tool.ast.RuleAST;
|
|
||||||
import org.stringtemplate.v4.misc.MultiMap;
|
import org.stringtemplate.v4.misc.MultiMap;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -205,18 +203,34 @@ public class Rule implements AttributeResolver {
|
||||||
return getAltLabels()!=null;
|
return getAltLabels()!=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Used for recursive rules (subclass), which have 1 alt, but many original alts */
|
||||||
|
public int getOriginalNumberOfAlts() {
|
||||||
|
return numberOfAlts;
|
||||||
|
}
|
||||||
|
|
||||||
/** Get -> labels. */
|
/** Get -> labels. */
|
||||||
public List<String> getAltLabels() {
|
public List<Triple<Integer,AltAST,String>> getAltLabels() {
|
||||||
List<String> labels = new ArrayList<String>();
|
List<Triple<Integer,AltAST,String>> labels = new ArrayList<Triple<Integer,AltAST,String>>();
|
||||||
for (int i=1; i<=numberOfAlts; i++) {
|
for (int i=1; i<=numberOfAlts; i++) {
|
||||||
GrammarAST altLabel = alt[i].ast.altLabel;
|
GrammarAST altLabel = alt[i].ast.altLabel;
|
||||||
if ( altLabel==null ) break; // all or none
|
if ( altLabel!=null ) {
|
||||||
labels.add(altLabel.getText());
|
labels.add(new Triple<Integer,AltAST,String>(i,alt[i].ast,altLabel.getText()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( labels.size()==0 ) return null;
|
if ( labels.size()==0 ) return null;
|
||||||
return labels;
|
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.
|
/** $x Attribute: rule arguments, return values, predefined rule prop.
|
||||||
*/
|
*/
|
||||||
public Attribute resolveToAttribute(String x, ActionAST node) {
|
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.Token;
|
||||||
import org.antlr.runtime.tree.Tree;
|
import org.antlr.runtime.tree.Tree;
|
||||||
|
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
|
||||||
import org.antlr.v4.tool.Alternative;
|
import org.antlr.v4.tool.Alternative;
|
||||||
|
|
||||||
/** Any ALT (which can be child of ALT_REWRITE node) */
|
/** Any ALT (which can be child of ALT_REWRITE node) */
|
||||||
public class AltAST extends GrammarAST {
|
public class AltAST extends GrammarAST {
|
||||||
public Alternative alt;
|
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.
|
* Token type will be ID.
|
||||||
*/
|
*/
|
||||||
public GrammarAST altLabel;
|
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;
|
package org.antlr.v4.tool.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.*;
|
import org.antlr.runtime.CharStream;
|
||||||
import org.antlr.runtime.tree.*;
|
import org.antlr.runtime.CommonToken;
|
||||||
import org.antlr.v4.parse.*;
|
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.atn.ATNState;
|
||||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||||
import org.antlr.v4.tool.Grammar;
|
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 {
|
public class GrammarAST extends CommonTree {
|
||||||
/** For error msgs, nice to know which grammar this AST lives in */
|
/** For error msgs, nice to know which grammar this AST lives in */
|
||||||
|
@ -108,6 +116,26 @@ public class GrammarAST extends CommonTree {
|
||||||
return null;
|
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) {
|
public boolean deleteChild(org.antlr.runtime.tree.Tree t) {
|
||||||
for (int i=0; i<children.size(); i++) {
|
for (int i=0; i<children.size(); i++) {
|
||||||
Object c = children.get(i);
|
Object c = children.get(i);
|
||||||
|
|
|
@ -35,7 +35,4 @@ public interface GrammarASTVisitor {
|
||||||
Object visit(SetAST node);
|
Object visit(SetAST node);
|
||||||
Object visit(RuleRefAST node);
|
Object visit(RuleRefAST node);
|
||||||
Object visit(TerminalAST 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 newline = System.getProperty("line.separator");
|
||||||
public static final String pathSep = System.getProperty("path.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)
|
* Build up the full classpath we need, including the surefire path (if present)
|
||||||
|
@ -510,7 +510,7 @@ public abstract class BaseTest {
|
||||||
}
|
}
|
||||||
if ( parserName!=null ) {
|
if ( parserName!=null ) {
|
||||||
files.add(parserName+".java");
|
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()]));
|
ok = compile(files.toArray(new String[files.size()]));
|
||||||
if ( !ok ) { allIsWell = false; }
|
if ( !ok ) { allIsWell = false; }
|
||||||
|
|
|
@ -926,13 +926,13 @@ JavaIDDigit
|
||||||
'\u1040'..'\u1049'
|
'\u1040'..'\u1049'
|
||||||
;
|
;
|
||||||
|
|
||||||
WS : (' '|'\r'|'\t'|'\u000C'|'\n')+ {$channel=HIDDEN;}//-> channel(HIDDEN)
|
WS : (' '|'\r'|'\t'|'\u000C'|'\n')+ -> channel(HIDDEN)
|
||||||
;
|
;
|
||||||
|
|
||||||
COMMENT
|
COMMENT
|
||||||
: '/*' .* '*/' {$channel=HIDDEN;}//-> channel(HIDDEN)
|
: '/*' .* '*/' -> channel(HIDDEN)
|
||||||
;
|
;
|
||||||
|
|
||||||
LINE_COMMENT
|
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 {
|
@Test public void testComplicatedArgParsingWithTranslation() throws Exception {
|
||||||
String action = "x, $ID.text+\"3242\", (*$ID).foo(21,33), 3.2+1, '\\n', "+
|
String action = "x, $ID.text+\"3242\", (*$ID).foo(21,33), 3.2+1, '\\n', "+
|
||||||
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||||
String expected = "x, (_localctx._tID!=null?_localctx._tID.getText():null)+\"3242\"," +
|
String expected =
|
||||||
" (*_localctx._tID).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
"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);
|
testActions(attributeTemplate, "inline", action, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,39 +100,39 @@ public class TestActionTranslation extends BaseTest {
|
||||||
|
|
||||||
@Test public void testReturnValues() throws Exception {
|
@Test public void testReturnValues() throws Exception {
|
||||||
String action = "$lab.e; $b.e;";
|
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);
|
testActions(attributeTemplate, "inline", action, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testReturnWithMultipleRuleRefs() throws Exception {
|
@Test public void testReturnWithMultipleRuleRefs() throws Exception {
|
||||||
String action = "$c.x; $c.y;";
|
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);
|
testActions(attributeTemplate, "inline", action, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testTokenRefs() throws Exception {
|
@Test public void testTokenRefs() throws Exception {
|
||||||
String action = "$id; $ID; $id.text; $id.getText(); $id.line;";
|
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);
|
testActions(attributeTemplate, "inline", action, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testRuleRefs() throws Exception {
|
@Test public void testRuleRefs() throws Exception {
|
||||||
String action = "$lab.start;";
|
String action = "$lab.start; $c.text;";
|
||||||
String expected = "(_localctx.lab!=null?(_localctx.lab.start):null);";
|
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);
|
testActions(attributeTemplate, "inline", action, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testRefToTextAttributeForCurrentRule() throws Exception {
|
@Test public void testRefToTextAttributeForCurrentRule() throws Exception {
|
||||||
String action = "$a.text; $text";
|
String action = "$a.text; $text";
|
||||||
String expected =
|
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))";
|
"null); _input.toString(_localctx.start, _input.LT(-1))";
|
||||||
testActions(attributeTemplate, "init", action, expected);
|
testActions(attributeTemplate, "init", action, expected);
|
||||||
expected =
|
expected =
|
||||||
"_input.toString(_localctx.start, _input.LT(-1)); _input.toString(_localctx.start, _input.LT(-1))";
|
"_input.toString(_localctx.start, _input.LT(-1)); _input.toString(_localctx.start, _input.LT(-1))";
|
||||||
testActions(attributeTemplate, "inline", action, expected);
|
testActions(attributeTemplate, "inline", action, expected);
|
||||||
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))";
|
" _input.toString(_localctx.start, _input.LT(-1))";
|
||||||
testActions(attributeTemplate, "finally", action, expected);
|
testActions(attributeTemplate, "finally", action, expected);
|
||||||
}
|
}
|
||||||
|
@ -235,10 +236,6 @@ public class TestActionTranslation extends BaseTest {
|
||||||
|
|
||||||
@Test public void testRuleLabelWithoutOutputOption() throws Exception {
|
@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 testMissingArgs() throws Exception {
|
||||||
}
|
}
|
||||||
@Test public void testArgsWhenNoneDefined() throws Exception {
|
@Test public void testArgsWhenNoneDefined() throws Exception {
|
||||||
|
|
|
@ -42,10 +42,14 @@ public class TestCompositeGrammars extends BaseTest {
|
||||||
String grammar =
|
String grammar =
|
||||||
"parser grammar S;\n" +
|
"parser grammar S;\n" +
|
||||||
"a : B . C ;\n"; // not qualified ID
|
"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();
|
ErrorQueue equeue = new ErrorQueue();
|
||||||
Tool antlr = new Tool();
|
Tool antlr = g.tool;
|
||||||
|
antlr.outputDirectory = tmpdir;
|
||||||
|
antlr.libDirectory = tmpdir;
|
||||||
antlr.addListener(equeue);
|
antlr.addListener(equeue);
|
||||||
antlr.process(g,true);
|
antlr.process(g,true);
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ public class TestFullContextParsing extends BaseTest {
|
||||||
assertEquals(expecting, result);
|
assertEquals(expecting, result);
|
||||||
assertEquals("line 1:5 reportAttemptingFullContext d=2: [(30,1,[20 10]), (22,2,[10])], input='34abc'\n" +
|
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: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",
|
"line 1:14 reportContextSensitivity d=2: [(8,2,[18]), (12,2,[18]), (1,2,[])],uniqueAlt=2, input='34abc'\n",
|
||||||
this.stderrDuringParse);
|
this.stderrDuringParse);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue