forked from jasder/antlr
Summary: we can have lexer commands like -> skip now.
moved model.actions package to chunk type(foo) didn't match. ATNBuilder.g now tracks the outer alternative number and calls new factory commands on the lexer commands. Removed unnecessary resolveWithPredicate field from ATNConfig Added lexerActionIndex field to ATNConfig since we need to track whether we passed an action in an alternative will rule in the lexer. Renamed ruleIndex in DFAState and added the lexer action index so that we can execute lexer actions from the DFA. added functions to the grammar tree visitor for the lexer commands. Added templates for the lexer commands. Augmented the lexer ATN factory so that it constructs plain old actions from the lexer commands it finds. That way, the code generator doesn't know any different and generates an action. Augmented the lexer ATN simulator so that it fires a proper action index now. previously it only used the rule index, which of course doesn't work when you have more than one action in a rule. rm'd dup code from OutputModelController altered the epsilon edge removal optimization so that it could not remove actions in lexer rules. Added list of valid lexer commands in Rule. [git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9877]
This commit is contained in:
parent
d321bb7854
commit
dc82edad02
|
@ -129,7 +129,6 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** In lexer, both indexes are same; one action per rule. */
|
|
||||||
public void action(@Nullable RuleContext _localctx, int ruleIndex, int actionIndex) {
|
public void action(@Nullable RuleContext _localctx, int ruleIndex, int actionIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,18 +57,6 @@ public class ATNConfig {
|
||||||
@Nullable
|
@Nullable
|
||||||
public RuleContext context;
|
public RuleContext context;
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that we have reached this ATN configuration after
|
|
||||||
* traversing a predicate transition. This is important because we
|
|
||||||
* cannot cache DFA states derived from such configurations
|
|
||||||
* otherwise predicates would not get executed again (DFAs don't
|
|
||||||
* have predicated edges in v4).
|
|
||||||
*/
|
|
||||||
//public boolean traversedPredicate; // TODO: don't need
|
|
||||||
|
|
||||||
/** Ignore this config when examining config sets */
|
|
||||||
// public boolean resolved;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We cannot execute predicates dependent upon local context unless
|
* We cannot execute predicates dependent upon local context unless
|
||||||
* we know for sure we are in the correct context. Because there is
|
* we know for sure we are in the correct context. Because there is
|
||||||
|
@ -82,18 +70,12 @@ public class ATNConfig {
|
||||||
*/
|
*/
|
||||||
public int reachesIntoOuterContext;
|
public int reachesIntoOuterContext;
|
||||||
|
|
||||||
|
/** Capture lexer action we traverse */
|
||||||
|
public int lexerActionIndex = -1; // TOOD: move to subclass
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public SemanticContext semanticContext = SemanticContext.NONE;
|
public SemanticContext semanticContext = SemanticContext.NONE;
|
||||||
|
|
||||||
/** This bit is used to indicate a semantic predicate will be
|
|
||||||
* used to resolve the conflict. Essentially, this is used
|
|
||||||
* as an "ignore" bit so that upon a set of conflicting configurations,
|
|
||||||
* such as (s|2|p) and (s|3|q), I can set (s|3) to resolved=true (and any
|
|
||||||
* other configuration associated with alt 3) to make it look like that set
|
|
||||||
* uniquely predicts an alt.
|
|
||||||
*/
|
|
||||||
protected boolean resolveWithPredicate;
|
|
||||||
|
|
||||||
public ATNConfig(@NotNull ATNState state,
|
public ATNConfig(@NotNull ATNState state,
|
||||||
int alt,
|
int alt,
|
||||||
@Nullable RuleContext context)
|
@Nullable RuleContext context)
|
||||||
|
@ -134,6 +116,7 @@ public class ATNConfig {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.reachesIntoOuterContext = c.reachesIntoOuterContext;
|
this.reachesIntoOuterContext = c.reachesIntoOuterContext;
|
||||||
this.semanticContext = semanticContext;
|
this.semanticContext = semanticContext;
|
||||||
|
this.lexerActionIndex = c.lexerActionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public ATNConfig(@NotNull ATNConfig c, @Nullable RuleContext context) {
|
// public ATNConfig(@NotNull ATNConfig c, @Nullable RuleContext context) {
|
||||||
|
|
|
@ -259,8 +259,10 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
throw new LexerNoViableAltException(recog, input, startIndex, s.configset);
|
throw new LexerNoViableAltException(recog, input, startIndex, s.configset);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ruleIndex = dfaPrevAccept.state.ruleIndex;
|
int ruleIndex = dfaPrevAccept.state.lexerRuleIndex;
|
||||||
accept(input, ruleIndex, dfaPrevAccept);
|
int actionIndex = dfaPrevAccept.state.lexerActionIndex;
|
||||||
|
accept(input, ruleIndex, actionIndex,
|
||||||
|
dfaPrevAccept.index, dfaPrevAccept.line, dfaPrevAccept.charPos);
|
||||||
tracePredict(dfaPrevAccept.state.prediction);
|
tracePredict(dfaPrevAccept.state.prediction);
|
||||||
return dfaPrevAccept.state.prediction;
|
return dfaPrevAccept.state.prediction;
|
||||||
}
|
}
|
||||||
|
@ -342,7 +344,8 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ruleIndex = atnPrevAccept.config.state.ruleIndex;
|
int ruleIndex = atnPrevAccept.config.state.ruleIndex;
|
||||||
accept(input, ruleIndex, atnPrevAccept);
|
accept(input, ruleIndex, atnPrevAccept.config.lexerActionIndex,
|
||||||
|
atnPrevAccept.index, atnPrevAccept.line, atnPrevAccept.charPos);
|
||||||
return atn.ruleToTokenType[ruleIndex];
|
return atn.ruleToTokenType[ruleIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,19 +380,20 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void accept(@NotNull CharStream input, int ruleIndex, @NotNull ExecState prevAccept) {
|
protected void accept(@NotNull CharStream input, int ruleIndex, int actionIndex,
|
||||||
|
int index, int line, int charPos)
|
||||||
|
{
|
||||||
if ( debug ) {
|
if ( debug ) {
|
||||||
System.out.format("ACTION %s:%d\n", recog != null ? recog.getRuleNames()[ruleIndex] : ruleIndex, ruleIndex);
|
System.out.format("ACTION %s:%d\n", recog != null ? recog.getRuleNames()[ruleIndex] : ruleIndex, actionIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int actionIndex = atn.ruleToActionIndex[ruleIndex];
|
|
||||||
if ( actionIndex>=0 && recog!=null ) recog.action(null, ruleIndex, actionIndex);
|
if ( actionIndex>=0 && recog!=null ) recog.action(null, ruleIndex, actionIndex);
|
||||||
|
|
||||||
// seek to after last char in token
|
// seek to after last char in token
|
||||||
traceSeek(prevAccept.index);
|
traceSeek(index);
|
||||||
input.seek(prevAccept.index);
|
input.seek(index);
|
||||||
line = prevAccept.line;
|
this.line = line;
|
||||||
charPositionInLine = prevAccept.charPos;
|
this.charPositionInLine = charPos;
|
||||||
consume(input);
|
consume(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,6 +534,7 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
// ignore actions; just exec one per rule upon accept
|
// ignore actions; just exec one per rule upon accept
|
||||||
else if ( t.getClass() == ActionTransition.class ) {
|
else if ( t.getClass() == ActionTransition.class ) {
|
||||||
c = new ATNConfig(config, t.target);
|
c = new ATNConfig(config, t.target);
|
||||||
|
c.lexerActionIndex = ((ActionTransition)t).actionIndex;
|
||||||
}
|
}
|
||||||
else if ( t.isEpsilon() ) {
|
else if ( t.isEpsilon() ) {
|
||||||
c = new ATNConfig(config, t.target);
|
c = new ATNConfig(config, t.target);
|
||||||
|
@ -611,7 +616,7 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
future. Rather than creating collections of semantic predicates
|
future. Rather than creating collections of semantic predicates
|
||||||
like v3 and testing them on prediction, v4 will test them on the
|
like v3 and testing them on prediction, v4 will test them on the
|
||||||
fly all the time using the ATN not the DFA. This is slower but
|
fly all the time using the ATN not the DFA. This is slower but
|
||||||
semantically it's not use that often. One of the key elements to
|
semantically it's not used that often. One of the key elements to
|
||||||
this predicate mechanism is not adding DFA states that see
|
this predicate mechanism is not adding DFA states that see
|
||||||
predicates immediately afterwards in the ATN. For example,
|
predicates immediately afterwards in the ATN. For example,
|
||||||
|
|
||||||
|
@ -639,14 +644,16 @@ public class LexerATNSimulator extends ATNSimulator {
|
||||||
{
|
{
|
||||||
firstConfigWithRuleStopState = c;
|
firstConfigWithRuleStopState = c;
|
||||||
}
|
}
|
||||||
if ( c.semanticContext!=null && c.semanticContext!=SemanticContext.NONE ) traversedPredicate = true;
|
if ( c.semanticContext!=null && c.semanticContext!=SemanticContext.NONE ) {
|
||||||
// if ( c.traversedPredicate ) traversedPredicate = true;
|
traversedPredicate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( firstConfigWithRuleStopState!=null ) {
|
if ( firstConfigWithRuleStopState!=null ) {
|
||||||
newState.isAcceptState = true;
|
newState.isAcceptState = true;
|
||||||
newState.ruleIndex = firstConfigWithRuleStopState.state.ruleIndex;
|
newState.lexerRuleIndex = firstConfigWithRuleStopState.state.ruleIndex;
|
||||||
newState.prediction = atn.ruleToTokenType[newState.ruleIndex];
|
newState.lexerActionIndex = firstConfigWithRuleStopState.lexerActionIndex;
|
||||||
|
newState.prediction = atn.ruleToTokenType[newState.lexerRuleIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( traversedPredicate ) return null; // cannot cache
|
if ( traversedPredicate ) return null; // cannot cache
|
||||||
|
|
|
@ -759,7 +759,6 @@ public class v2ParserATNSimulator<Symbol> extends ATNSimulator {
|
||||||
for (ATNConfig c : configs) {
|
for (ATNConfig c : configs) {
|
||||||
if ( c.semanticContext!=SemanticContext.NONE && ambigAlts.contains(c.alt) ) {
|
if ( c.semanticContext!=SemanticContext.NONE && ambigAlts.contains(c.alt) ) {
|
||||||
altToPred[c.alt] = SemanticContext.or(altToPred[c.alt], c.semanticContext);
|
altToPred[c.alt] = SemanticContext.or(altToPred[c.alt], c.semanticContext);
|
||||||
c.resolveWithPredicate = true;
|
|
||||||
nPredAlts++;
|
nPredAlts++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,8 @@ public class DFAState {
|
||||||
|
|
||||||
public int prediction; // if accept state, what ttype do we match? is "else" clause if predicated
|
public int prediction; // if accept state, what ttype do we match? is "else" clause if predicated
|
||||||
|
|
||||||
public int ruleIndex; // if accept, exec what action?
|
public int lexerRuleIndex = -1; // if accept, exec action in what rule?
|
||||||
|
public int lexerActionIndex = -1; // if accept, exec what action?
|
||||||
|
|
||||||
// todo: rename as unique?
|
// todo: rename as unique?
|
||||||
public boolean complete; // all alts predict "prediction"
|
public boolean complete; // all alts predict "prediction"
|
||||||
|
|
|
@ -434,6 +434,17 @@ setState(<p.stateNumber>);
|
||||||
if (!(<chunks>)) throw new FailedPredicateException(this, <if(p.msg)><p.msg><else><failChunks><endif>);
|
if (!(<chunks>)) throw new FailedPredicateException(this, <if(p.msg)><p.msg><else><failChunks><endif>);
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
// lexer actions are not associated with model objects
|
||||||
|
|
||||||
|
LexerSkipCommand() ::= "skip();"
|
||||||
|
LexerMoreCommand() ::= "more();"
|
||||||
|
LexerPopMode() ::= "popMode();"
|
||||||
|
|
||||||
|
LexerTypeCommand(arg) ::= "type = <arg>;"
|
||||||
|
LexerChannelCommand(arg) ::= "channel = <arg>;"
|
||||||
|
LexerModeCommand(arg) ::= "mode = <arg>;"
|
||||||
|
LexerPushModeCommand(arg) ::= "pushMode(<arg>);"
|
||||||
|
|
||||||
DefaultParserSuperClass(s) ::= "Parser"
|
DefaultParserSuperClass(s) ::= "Parser"
|
||||||
|
|
||||||
ActionText(t) ::= "<t.text>"
|
ActionText(t) ::= "<t.text>"
|
||||||
|
@ -482,8 +493,7 @@ TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();"
|
||||||
RuleContextDecl(r) ::= "<r.ctxName> <r.name>;"
|
RuleContextDecl(r) ::= "<r.ctxName> <r.name>;"
|
||||||
RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
|
RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
|
||||||
|
|
||||||
/** Default RuleContext type name for a Parser rule */
|
LexerRuleContext() ::= "RuleContext"
|
||||||
ParserRuleContext() ::= "ParserRuleContext\<?>"
|
|
||||||
|
|
||||||
/** The rule context name is the rule followed by a suffix; e.g.,
|
/** The rule context name is the rule followed by a suffix; e.g.,
|
||||||
* r becomes rContext.
|
* r becomes rContext.
|
||||||
|
@ -538,7 +548,7 @@ AttributeDecl(d) ::= "<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)>_localctx.<endif><x.name>"
|
||||||
|
|
||||||
// used for left-recursive rules
|
// used for left-recursive rules
|
||||||
recRuleDefArg() ::= "int _p"
|
recRuleDefArg() ::= "int _p"
|
||||||
recRuleArg() ::= "$_p"
|
recRuleArg() ::= "$_p"
|
||||||
recRuleAltPredicate(ruleName,opPrec) ::= "<opPrec> >= <recRuleArg()>"
|
recRuleAltPredicate(ruleName,opPrec) ::= "<opPrec> >= <recRuleArg()>"
|
||||||
|
@ -592,7 +602,6 @@ Lexer(lexer, atn, actionFuncs, sempredFuncs) ::= <<
|
||||||
public class <lexer.name> extends Lexer {
|
public class <lexer.name> extends Lexer {
|
||||||
public static final int
|
public static final int
|
||||||
<lexer.tokens:{k | <k>=<lexer.tokens.(k)>}; separator=", ", wrap, anchor>;
|
<lexer.tokens:{k | <k>=<lexer.tokens.(k)>}; separator=", ", wrap, anchor>;
|
||||||
// Lexer modes
|
|
||||||
<rest(lexer.modes):{m| public static final int <m> = <i>;}; separator="\n">
|
<rest(lexer.modes):{m| public static final int <m> = <i>;}; separator="\n">
|
||||||
|
|
||||||
public static final String[] tokenNames = {
|
public static final String[] tokenNames = {
|
||||||
|
|
|
@ -58,6 +58,8 @@ public interface ATNFactory {
|
||||||
|
|
||||||
void setCurrentRuleName(String name);
|
void setCurrentRuleName(String name);
|
||||||
|
|
||||||
|
void setCurrentOuterAlt(int alt);
|
||||||
|
|
||||||
Handle rule(GrammarAST ruleAST, String name, Handle blk);
|
Handle rule(GrammarAST ruleAST, String name, Handle blk);
|
||||||
|
|
||||||
ATNState newState();
|
ATNState newState();
|
||||||
|
@ -77,8 +79,6 @@ public interface ATNFactory {
|
||||||
|
|
||||||
Handle range(GrammarAST a, GrammarAST b);
|
Handle range(GrammarAST a, GrammarAST b);
|
||||||
|
|
||||||
// Handle not(GrammarAST a);
|
|
||||||
|
|
||||||
/** For a non-lexer, just build a simple token reference atom.
|
/** For a non-lexer, just build a simple token reference atom.
|
||||||
* For a lexer, a string is a sequence of char to match. That is,
|
* For a lexer, a string is a sequence of char to match. That is,
|
||||||
* "fog" is treated as 'f' 'o' 'g' not as a single transition in
|
* "fog" is treated as 'f' 'o' 'g' not as a single transition in
|
||||||
|
@ -116,11 +116,11 @@ public interface ATNFactory {
|
||||||
|
|
||||||
/** Build what amounts to an epsilon transition with an action.
|
/** Build what amounts to an epsilon transition with an action.
|
||||||
* The action goes into ATN though it is ignored during analysis.
|
* The action goes into ATN though it is ignored during analysis.
|
||||||
* It slows things down a bit, but I must ignore predicates after
|
|
||||||
* having seen an action (5-5-2008).
|
|
||||||
*/
|
*/
|
||||||
Handle action(ActionAST action);
|
Handle action(ActionAST action);
|
||||||
|
|
||||||
|
Handle action(String action);
|
||||||
|
|
||||||
Handle alt(List<Handle> els);
|
Handle alt(List<Handle> els);
|
||||||
|
|
||||||
/** From A|B|..|Z alternative block build
|
/** From A|B|..|Z alternative block build
|
||||||
|
@ -214,4 +214,10 @@ public interface ATNFactory {
|
||||||
* (^(. .+) | .) to be safe.
|
* (^(. .+) | .) to be safe.
|
||||||
*/
|
*/
|
||||||
Handle wildcardTree(GrammarAST associatedAST);
|
Handle wildcardTree(GrammarAST associatedAST);
|
||||||
|
|
||||||
|
Handle lexerAltCommands(ATNFactory.Handle alt, ATNFactory.Handle cmds);
|
||||||
|
|
||||||
|
String lexerCallCommand(GrammarAST ID, GrammarAST arg);
|
||||||
|
|
||||||
|
String lexerCommand(GrammarAST ID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,23 +29,35 @@
|
||||||
|
|
||||||
package org.antlr.v4.automata;
|
package org.antlr.v4.automata;
|
||||||
|
|
||||||
|
import org.antlr.runtime.CommonToken;
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
import org.antlr.v4.codegen.CodeGenerator;
|
||||||
import org.antlr.v4.misc.CharSupport;
|
import org.antlr.v4.misc.CharSupport;
|
||||||
import org.antlr.v4.parse.ANTLRParser;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.atn.*;
|
import org.antlr.v4.runtime.atn.*;
|
||||||
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.LexerGrammar;
|
import org.antlr.v4.tool.LexerGrammar;
|
||||||
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.ActionAST;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
import org.antlr.v4.tool.ast.GrammarAST;
|
||||||
import org.antlr.v4.tool.ast.TerminalAST;
|
import org.antlr.v4.tool.ast.TerminalAST;
|
||||||
|
import org.stringtemplate.v4.ST;
|
||||||
|
import org.stringtemplate.v4.STGroup;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class LexerATNFactory extends ParserATNFactory {
|
public class LexerATNFactory extends ParserATNFactory {
|
||||||
public LexerATNFactory(LexerGrammar g) { super(g); }
|
public STGroup codegenTemplates;
|
||||||
|
public LexerATNFactory(LexerGrammar g) {
|
||||||
|
super(g);
|
||||||
|
// use codegen to get correct language templates for lexer commands
|
||||||
|
String language = Grammar.getLanguageOption(g.ast);
|
||||||
|
CodeGenerator gen = new CodeGenerator(g.tool, null, language);
|
||||||
|
codegenTemplates = gen.templates;
|
||||||
|
}
|
||||||
|
|
||||||
public ATN createATN() {
|
public ATN createATN() {
|
||||||
// BUILD ALL START STATES (ONE PER MODE)
|
// BUILD ALL START STATES (ONE PER MODE)
|
||||||
|
@ -87,13 +99,48 @@ public class LexerATNFactory extends ParserATNFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Handle action(ActionAST action) {
|
public Handle action(ActionAST action) {
|
||||||
// Handle h = super.action(action);
|
ATNState left = newState(action);
|
||||||
// ActionTransition a = (ActionTransition)h.left.transition(0);
|
ATNState right = newState(action);
|
||||||
// a.actionIndex = g.actions.get(action);
|
boolean isCtxDependent = false;
|
||||||
// return h;
|
int actionIndex = g.lexerActions.get(action);
|
||||||
// no actions in lexer ATN; just one on end and we exec via action number
|
ActionTransition a =
|
||||||
ATNState x = newState(action);
|
new ActionTransition(right, currentRule.index, actionIndex, isCtxDependent);
|
||||||
return new Handle(x, x); // return just one blank state
|
left.addTransition(a);
|
||||||
|
action.atnState = left;
|
||||||
|
Handle h = new Handle(left, right);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Handle action(String action) {
|
||||||
|
// define action AST for this rule as if we had found in grammar
|
||||||
|
ActionAST ast = new ActionAST(new CommonToken(ANTLRParser.ACTION, action));
|
||||||
|
currentRule.defineActionInAlt(currentOuterAlt, ast);
|
||||||
|
return action(ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Handle lexerAltCommands(Handle alt, Handle cmds) {
|
||||||
|
Handle h = new Handle(alt.left, cmds.right);
|
||||||
|
epsilon(alt.right, cmds.left);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lexerCallCommand(GrammarAST ID, GrammarAST arg) {
|
||||||
|
ST cmdST = codegenTemplates.getInstanceOf("Lexer" +
|
||||||
|
CharSupport.capitalize(ID.getText())+
|
||||||
|
"Command");
|
||||||
|
cmdST.add("arg", arg.getText());
|
||||||
|
return cmdST.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lexerCommand(GrammarAST ID) {
|
||||||
|
ST cmdST = codegenTemplates.getInstanceOf("Lexer" +
|
||||||
|
CharSupport.capitalize(ID.getText())+
|
||||||
|
"Command");
|
||||||
|
return cmdST.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -126,7 +173,7 @@ public class LexerATNFactory extends ParserATNFactory {
|
||||||
}
|
}
|
||||||
if ( invert ) {
|
if ( invert ) {
|
||||||
// TODO: what? should be chars not token types
|
// TODO: what? should be chars not token types
|
||||||
IntervalSet notSet = (IntervalSet)set.complement(Token.MIN_TOKEN_TYPE, g.getMaxTokenType());
|
IntervalSet notSet = set.complement(Token.MIN_TOKEN_TYPE, g.getMaxTokenType());
|
||||||
left.addTransition(new NotSetTransition(right, set, notSet));
|
left.addTransition(new NotSetTransition(right, set, notSet));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -70,8 +70,10 @@ public class ParserATNFactory implements ATNFactory {
|
||||||
// we have p-x->q for x in {rule, action, pred, token, ...}
|
// we have p-x->q for x in {rule, action, pred, token, ...}
|
||||||
// if edge out of q is single epsilon to block end
|
// if edge out of q is single epsilon to block end
|
||||||
// we can strip epsilon p-x->q-eps->r
|
// we can strip epsilon p-x->q-eps->r
|
||||||
if ( q.getNumberOfTransitions()==1 && q.transition(0).isEpsilon() ) {
|
Transition trans = q.transition(0);
|
||||||
ATNState r = q.transition(0).target;
|
if ( q.getNumberOfTransitions()==1 && trans.isEpsilon() &&
|
||||||
|
!(trans instanceof ActionTransition) ) {
|
||||||
|
ATNState r = trans.target;
|
||||||
if ( r instanceof BlockEndState ||
|
if ( r instanceof BlockEndState ||
|
||||||
r instanceof PlusLoopbackState ||
|
r instanceof PlusLoopbackState ||
|
||||||
r instanceof StarLoopbackState )
|
r instanceof StarLoopbackState )
|
||||||
|
@ -99,6 +101,8 @@ public class ParserATNFactory implements ATNFactory {
|
||||||
|
|
||||||
public Rule currentRule;
|
public Rule currentRule;
|
||||||
|
|
||||||
|
public int currentOuterAlt;
|
||||||
|
|
||||||
public ParserATNFactory(@NotNull Grammar g) { this.g = g; atn = new ATN(); }
|
public ParserATNFactory(@NotNull Grammar g) { this.g = g; atn = new ATN(); }
|
||||||
|
|
||||||
public ATN createATN() {
|
public ATN createATN() {
|
||||||
|
@ -120,7 +124,7 @@ public class ParserATNFactory implements ATNFactory {
|
||||||
ATNBuilder b = new ATNBuilder(nodes,this);
|
ATNBuilder b = new ATNBuilder(nodes,this);
|
||||||
try {
|
try {
|
||||||
setCurrentRuleName(r.name);
|
setCurrentRuleName(r.name);
|
||||||
Handle h = b.block(null);
|
Handle h = b.ruleBlock(null);
|
||||||
rule(r.ast, r.name, h);
|
rule(r.ast, r.name, h);
|
||||||
}
|
}
|
||||||
catch (RecognitionException re) {
|
catch (RecognitionException re) {
|
||||||
|
@ -133,6 +137,11 @@ public class ParserATNFactory implements ATNFactory {
|
||||||
this.currentRule = g.getRule(name);
|
this.currentRule = g.getRule(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCurrentOuterAlt(int alt) {
|
||||||
|
currentOuterAlt = alt;
|
||||||
|
}
|
||||||
|
|
||||||
/* start->ruleblock->end */
|
/* start->ruleblock->end */
|
||||||
public Handle rule(GrammarAST ruleAST, String name, Handle blk) {
|
public Handle rule(GrammarAST ruleAST, String name, Handle blk) {
|
||||||
Rule r = g.getRule(name);
|
Rule r = g.getRule(name);
|
||||||
|
@ -170,7 +179,7 @@ public class ParserATNFactory implements ATNFactory {
|
||||||
set.add(ttype);
|
set.add(ttype);
|
||||||
}
|
}
|
||||||
if ( invert ) {
|
if ( invert ) {
|
||||||
IntervalSet notSet = (IntervalSet)set.complement(Token.MIN_TOKEN_TYPE, g.getMaxTokenType());
|
IntervalSet notSet = set.complement(Token.MIN_TOKEN_TYPE, g.getMaxTokenType());
|
||||||
left.addTransition(new NotSetTransition(right, set, notSet));
|
left.addTransition(new NotSetTransition(right, set, notSet));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -286,6 +295,11 @@ public class ParserATNFactory implements ATNFactory {
|
||||||
return new Handle(left, right);
|
return new Handle(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Handle action(String action) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/** From A|B|..|Z alternative block build
|
/** From A|B|..|Z alternative block build
|
||||||
*
|
*
|
||||||
* o->o-A->o->o (last ATNState is BlockEndState pointed to by all alts)
|
* o->o-A->o->o (last ATNState is BlockEndState pointed to by all alts)
|
||||||
|
@ -619,4 +633,18 @@ public class ParserATNFactory implements ATNFactory {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Handle lexerAltCommands(Handle alt, Handle cmds) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lexerCallCommand(GrammarAST ID, GrammarAST arg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lexerCommand(GrammarAST ID) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ package org.antlr.v4.codegen;
|
||||||
import org.antlr.runtime.ANTLRStringStream;
|
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.actions.*;
|
import org.antlr.v4.codegen.model.chunk.*;
|
||||||
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;
|
||||||
|
|
|
@ -269,10 +269,15 @@ public class OutputModelController {
|
||||||
function.postamble = rulePostamble(function, r);
|
function.postamble = rulePostamble(function, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildLexerRuleActions(Lexer lexer, Rule r) {
|
public void buildLexerRuleActions(Lexer lexer, final Rule r) {
|
||||||
CodeGenerator gen = delegate.getGenerator();
|
CodeGenerator gen = delegate.getGenerator();
|
||||||
Grammar g = delegate.getGrammar();
|
Grammar g = delegate.getGrammar();
|
||||||
String ctxType = gen.target.getRuleFunctionContextStructName(r);
|
String ctxType = gen.target.getRuleFunctionContextStructName(r);
|
||||||
|
RuleActionFunction raf = lexer.actionFuncs.get(r);
|
||||||
|
if ( raf==null ) {
|
||||||
|
raf = new RuleActionFunction(delegate, r, ctxType);
|
||||||
|
lexer.actionFuncs.put(r, raf);
|
||||||
|
}
|
||||||
for (ActionAST a : r.actions) {
|
for (ActionAST a : r.actions) {
|
||||||
if ( a instanceof PredAST ) {
|
if ( a instanceof PredAST ) {
|
||||||
PredAST p = (PredAST)a;
|
PredAST p = (PredAST)a;
|
||||||
|
@ -284,24 +289,6 @@ public class OutputModelController {
|
||||||
rsf.actions.put(g.sempreds.get(p), new Action(delegate, p));
|
rsf.actions.put(g.sempreds.get(p), new Action(delegate, p));
|
||||||
}
|
}
|
||||||
else if ( a.getType()== ANTLRParser.ACTION ) {
|
else if ( a.getType()== ANTLRParser.ACTION ) {
|
||||||
RuleActionFunction raf = lexer.sempredFuncs.get(r);
|
|
||||||
if ( raf==null ) {
|
|
||||||
raf = new RuleActionFunction(delegate, r, ctxType);
|
|
||||||
lexer.actionFuncs.put(r, raf);
|
|
||||||
}
|
|
||||||
raf.actions.put(g.lexerActions.get(a), new Action(delegate, a));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( a instanceof PredAST ) {
|
|
||||||
PredAST p = (PredAST)a;
|
|
||||||
RuleSempredFunction rsf = new RuleSempredFunction(delegate, r, ctxType);
|
|
||||||
lexer.sempredFuncs.put(r, rsf);
|
|
||||||
rsf.actions.put(g.sempreds.get(p), new Action(delegate, p));
|
|
||||||
}
|
|
||||||
else if ( a.getType()==ANTLRParser.ACTION ) {
|
|
||||||
// lexer sees {{...}} and {..} as same; neither are done until accept
|
|
||||||
RuleActionFunction raf = new RuleActionFunction(delegate, r, ctxType);
|
|
||||||
lexer.actionFuncs.put(r, raf);
|
|
||||||
raf.actions.put(g.lexerActions.get(a), new Action(delegate, a));
|
raf.actions.put(g.lexerActions.get(a), new Action(delegate, a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -339,15 +339,9 @@ public class Target {
|
||||||
|
|
||||||
public String getRuleFunctionContextStructName(Rule r) {
|
public String getRuleFunctionContextStructName(Rule r) {
|
||||||
if ( r.g.isLexer() ) {
|
if ( r.g.isLexer() ) {
|
||||||
return gen.templates.getInstanceOf("ParserRuleContext").render();
|
return gen.templates.getInstanceOf("LexerRuleContext").render();
|
||||||
}
|
}
|
||||||
return r.name+gen.templates.getInstanceOf("RuleContextNameSuffix").render();
|
return r.name+gen.templates.getInstanceOf("RuleContextNameSuffix").render();
|
||||||
// boolean hasNoExternallyVisibleElements =
|
|
||||||
// r.args==null && r.retvals==null && r.scope==null && r.getLabelNames()==null;
|
|
||||||
// if ( hasNoExternallyVisibleElements ) {
|
|
||||||
// return gen.templates.getInstanceOf("ParserRuleContext").render();
|
|
||||||
// }
|
|
||||||
// return r.name+"_ctx";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If we know which actual function, we can provide the actual ctx type.
|
/** If we know which actual function, we can provide the actual ctx type.
|
||||||
|
@ -358,16 +352,9 @@ public class Target {
|
||||||
public String getRuleFunctionContextStructName(RuleFunction function) {
|
public String getRuleFunctionContextStructName(RuleFunction function) {
|
||||||
Rule r = function.rule;
|
Rule r = function.rule;
|
||||||
if ( r.g.isLexer() ) {
|
if ( r.g.isLexer() ) {
|
||||||
return gen.templates.getInstanceOf("ParserRuleContext").render();
|
return gen.templates.getInstanceOf("LexerRuleContext").render();
|
||||||
}
|
}
|
||||||
return r.name+gen.templates.getInstanceOf("RuleContextNameSuffix").render();
|
return r.name+gen.templates.getInstanceOf("RuleContextNameSuffix").render();
|
||||||
// boolean hasNoExternallyVisibleElements =
|
|
||||||
// r.args==null && r.retvals==null && r.scope==null && r.getLabelNames()==null;
|
|
||||||
//
|
|
||||||
// if ( hasNoExternallyVisibleElements && function.ruleCtx.isEmpty() ) {
|
|
||||||
// return gen.templates.getInstanceOf("ParserRuleContext").render();
|
|
||||||
// }
|
|
||||||
// return r.name+"_ctx";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// should be same for all refs to same token like $ID within single rule function
|
// should be same for all refs to same token like $ID within single rule function
|
||||||
|
|
|
@ -32,7 +32,8 @@ 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.ActionTranslator;
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
import org.antlr.v4.codegen.model.actions.ActionChunk;
|
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
||||||
|
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.ActionAST;
|
||||||
import org.antlr.v4.tool.ast.GrammarAST;
|
import org.antlr.v4.tool.ast.GrammarAST;
|
||||||
|
@ -57,9 +58,15 @@ public class Action extends RuleElement {
|
||||||
|
|
||||||
public Action(OutputModelFactory factory, String action) {
|
public Action(OutputModelFactory factory, String action) {
|
||||||
super(factory,null);
|
super(factory,null);
|
||||||
RuleFunction rf = factory.getCurrentRuleFunction();
|
|
||||||
ActionAST ast = new ActionAST(new CommonToken(ANTLRParser.ACTION, action));
|
ActionAST ast = new ActionAST(new CommonToken(ANTLRParser.ACTION, action));
|
||||||
ast.resolver = rf.rule;
|
RuleFunction rf = factory.getCurrentRuleFunction();
|
||||||
chunks = ActionTranslator.translateActionChunk(factory, rf, action, ast);
|
if ( rf!=null ) { // we can translate
|
||||||
|
ast.resolver = rf.rule;
|
||||||
|
chunks = ActionTranslator.translateActionChunk(factory, rf, action, ast);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chunks = new ArrayList<ActionChunk>();
|
||||||
|
chunks.add(new ActionText(action));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ package org.antlr.v4.codegen.model;
|
||||||
import org.antlr.v4.codegen.ActionTranslator;
|
import org.antlr.v4.codegen.ActionTranslator;
|
||||||
import org.antlr.v4.codegen.CodeGenerator;
|
import org.antlr.v4.codegen.CodeGenerator;
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
import org.antlr.v4.codegen.model.actions.ActionChunk;
|
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
||||||
import org.antlr.v4.codegen.model.decl.Decl;
|
import org.antlr.v4.codegen.model.decl.Decl;
|
||||||
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
|
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
|
||||||
import org.antlr.v4.codegen.model.decl.RuleContextListDecl;
|
import org.antlr.v4.codegen.model.decl.RuleContextListDecl;
|
||||||
|
|
|
@ -31,10 +31,11 @@ package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.CodeGenerator;
|
import org.antlr.v4.codegen.CodeGenerator;
|
||||||
import org.antlr.v4.codegen.OutputModelFactory;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
import org.antlr.v4.codegen.model.actions.ActionChunk;
|
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
||||||
import org.antlr.v4.codegen.model.actions.ActionText;
|
import org.antlr.v4.codegen.model.chunk.ActionText;
|
||||||
import org.antlr.v4.codegen.model.actions.DefaultParserSuperClass;
|
import org.antlr.v4.codegen.model.chunk.DefaultParserSuperClass;
|
||||||
import org.antlr.v4.tool.*;
|
import org.antlr.v4.tool.Grammar;
|
||||||
|
import org.antlr.v4.tool.Rule;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class RuleActionFunction extends OutputModelObject {
|
||||||
public String ctxType;
|
public String ctxType;
|
||||||
public int ruleIndex;
|
public int ruleIndex;
|
||||||
|
|
||||||
|
/** Map actionIndex to Action */
|
||||||
@ModelElement public LinkedHashMap<Integer, Action> actions =
|
@ModelElement public LinkedHashMap<Integer, Action> actions =
|
||||||
new LinkedHashMap<Integer, Action>();
|
new LinkedHashMap<Integer, Action>();
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,13 @@
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model;
|
package org.antlr.v4.codegen.model;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.*;
|
import org.antlr.v4.codegen.ActionTranslator;
|
||||||
import org.antlr.v4.codegen.model.actions.ActionChunk;
|
import org.antlr.v4.codegen.CodeGenerator;
|
||||||
import org.antlr.v4.tool.ast.*;
|
import org.antlr.v4.codegen.OutputModelFactory;
|
||||||
|
import org.antlr.v4.codegen.model.chunk.ActionChunk;
|
||||||
|
import org.antlr.v4.tool.ast.ActionAST;
|
||||||
|
import org.antlr.v4.tool.ast.GrammarAST;
|
||||||
|
import org.antlr.v4.tool.ast.PredAST;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.model.OutputModelObject;
|
import org.antlr.v4.codegen.model.OutputModelObject;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ActionText extends ActionChunk {
|
public class ActionText extends ActionChunk {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ArgRef extends LocalRef {
|
public class ArgRef extends LocalRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class DefaultParserSuperClass extends ActionChunk {
|
public class DefaultParserSuperClass extends ActionChunk {
|
||||||
}
|
}
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class LabelRef extends ActionChunk {
|
public class LabelRef extends ActionChunk {
|
||||||
public String name;
|
public String name;
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class ListLabelRef extends LabelRef {
|
public class ListLabelRef extends LabelRef {
|
||||||
public ListLabelRef(String name) { super(name); }
|
public ListLabelRef(String name) { super(name); }
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class LocalRef extends ActionChunk {
|
public class LocalRef extends ActionChunk {
|
||||||
public String name;
|
public String name;
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class NonLocalAttrRef extends ActionChunk {
|
public class NonLocalAttrRef extends ActionChunk {
|
||||||
public String ruleName;
|
public String ruleName;
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class QRetValueRef extends RetValueRef {
|
public class QRetValueRef extends RetValueRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RetValueRef extends ActionChunk {
|
public class RetValueRef extends ActionChunk {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef extends ActionChunk {
|
public class RulePropertyRef extends ActionChunk {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class RulePropertyRef_ctx extends RulePropertyRef {
|
public class RulePropertyRef_ctx extends RulePropertyRef {
|
||||||
public RulePropertyRef_ctx(String label) {
|
public RulePropertyRef_ctx(String label) {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef_start extends RulePropertyRef {
|
public class RulePropertyRef_start extends RulePropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef_stop extends RulePropertyRef {
|
public class RulePropertyRef_stop extends RulePropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class RulePropertyRef_text extends RulePropertyRef {
|
public class RulePropertyRef_text extends RulePropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.model.ModelElement;
|
import org.antlr.v4.codegen.model.ModelElement;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
public class ThisRulePropertyRef_ctx extends RulePropertyRef {
|
public class ThisRulePropertyRef_ctx extends RulePropertyRef {
|
||||||
public ThisRulePropertyRef_ctx(String label) {
|
public ThisRulePropertyRef_ctx(String label) {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ThisRulePropertyRef_start extends RulePropertyRef {
|
public class ThisRulePropertyRef_start extends RulePropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ThisRulePropertyRef_stop extends RulePropertyRef {
|
public class ThisRulePropertyRef_stop extends RulePropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class ThisRulePropertyRef_text extends RulePropertyRef {
|
public class ThisRulePropertyRef_text extends RulePropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef extends ActionChunk {
|
public class TokenPropertyRef extends ActionChunk {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_channel extends TokenPropertyRef {
|
public class TokenPropertyRef_channel extends TokenPropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_index extends TokenPropertyRef {
|
public class TokenPropertyRef_index extends TokenPropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_int extends TokenPropertyRef {
|
public class TokenPropertyRef_int extends TokenPropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_line extends TokenPropertyRef {
|
public class TokenPropertyRef_line extends TokenPropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_pos extends TokenPropertyRef {
|
public class TokenPropertyRef_pos extends TokenPropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_text extends TokenPropertyRef {
|
public class TokenPropertyRef_text extends TokenPropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenPropertyRef_type extends TokenPropertyRef {
|
public class TokenPropertyRef_type extends TokenPropertyRef {
|
|
@ -27,7 +27,7 @@
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.antlr.v4.codegen.model.actions;
|
package org.antlr.v4.codegen.model.chunk;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class TokenRef extends ActionChunk {
|
public class TokenRef extends ActionChunk {
|
|
@ -648,7 +648,7 @@ lexerAction
|
||||||
;
|
;
|
||||||
|
|
||||||
lexerActionExpr
|
lexerActionExpr
|
||||||
: ID
|
: id
|
||||||
| INT
|
| INT
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,21 @@ import org.antlr.v4.automata.ATNFactory;
|
||||||
|
|
||||||
dummy : block[null] ; // avoid error about no start rule
|
dummy : block[null] ; // avoid error about no start rule
|
||||||
|
|
||||||
|
ruleBlock[GrammarAST ebnfRoot] returns [ATNFactory.Handle p]
|
||||||
|
@init {
|
||||||
|
List<ATNFactory.Handle> alts = new ArrayList<ATNFactory.Handle>();
|
||||||
|
int alt = 1;
|
||||||
|
factory.setCurrentOuterAlt(alt);
|
||||||
|
}
|
||||||
|
: ^(BLOCK
|
||||||
|
(^(OPTIONS .+))?
|
||||||
|
( a=alternative
|
||||||
|
{alts.add($a.p); factory.setCurrentOuterAlt(++alt);}
|
||||||
|
)+
|
||||||
|
)
|
||||||
|
{$p = factory.block((BlockAST)$BLOCK, ebnfRoot, alts);}
|
||||||
|
;
|
||||||
|
|
||||||
block[GrammarAST ebnfRoot] returns [ATNFactory.Handle p]
|
block[GrammarAST ebnfRoot] returns [ATNFactory.Handle p]
|
||||||
@init {List<ATNFactory.Handle> alts = new ArrayList<ATNFactory.Handle>();}
|
@init {List<ATNFactory.Handle> alts = new ArrayList<ATNFactory.Handle>();}
|
||||||
: ^(BLOCK (^(OPTIONS .+))? (a=alternative {alts.add($a.p);})+)
|
: ^(BLOCK (^(OPTIONS .+))? (a=alternative {alts.add($a.p);})+)
|
||||||
|
@ -83,11 +98,32 @@ block[GrammarAST ebnfRoot] returns [ATNFactory.Handle p]
|
||||||
|
|
||||||
alternative returns [ATNFactory.Handle p]
|
alternative returns [ATNFactory.Handle p]
|
||||||
@init {List<ATNFactory.Handle> els = new ArrayList<ATNFactory.Handle>();}
|
@init {List<ATNFactory.Handle> els = new ArrayList<ATNFactory.Handle>();}
|
||||||
: ^(LEXER_ALT_ACTION a=alternative .*) {$p = $a.p;}
|
: ^(LEXER_ALT_ACTION a=alternative lexerCommands)
|
||||||
|
{$p = factory.lexerAltCommands($a.p,$lexerCommands.p);}
|
||||||
| ^(ALT EPSILON) {$p = factory.epsilon($EPSILON);}
|
| ^(ALT EPSILON) {$p = factory.epsilon($EPSILON);}
|
||||||
| ^(ALT (e=element {els.add($e.p);})+) {$p = factory.alt(els);}
|
| ^(ALT (e=element {els.add($e.p);})+) {$p = factory.alt(els);}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
lexerCommands returns [ATNFactory.Handle p]
|
||||||
|
@init {StringBuilder cmds = new StringBuilder();}
|
||||||
|
: (c=lexerCommand {cmds.append($c.cmd+" ");})+
|
||||||
|
{
|
||||||
|
$p = factory.action(cmds.toString());
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
lexerCommand returns [String cmd]
|
||||||
|
: ^(LEXER_ACTION_CALL ID lexerCommandExpr)
|
||||||
|
{$cmd = factory.lexerCallCommand($ID, $lexerCommandExpr.start);}
|
||||||
|
| ID
|
||||||
|
{$cmd = factory.lexerCommand($ID);}
|
||||||
|
;
|
||||||
|
|
||||||
|
lexerCommandExpr
|
||||||
|
: ID
|
||||||
|
| INT
|
||||||
|
;
|
||||||
|
|
||||||
element returns [ATNFactory.Handle p]
|
element returns [ATNFactory.Handle p]
|
||||||
: labeledElement {$p = $labeledElement.p;}
|
: labeledElement {$p = $labeledElement.p;}
|
||||||
| atom {$p = $atom.p;}
|
| atom {$p = $atom.p;}
|
||||||
|
|
|
@ -153,6 +153,8 @@ public void wildcardRef(GrammarAST ref) { }
|
||||||
public void actionInAlt(ActionAST action) { }
|
public void actionInAlt(ActionAST action) { }
|
||||||
public void sempredInAlt(PredAST pred) { }
|
public void sempredInAlt(PredAST pred) { }
|
||||||
public void label(GrammarAST op, GrammarAST ID, GrammarAST element) { }
|
public void label(GrammarAST op, GrammarAST ID, GrammarAST element) { }
|
||||||
|
public void lexerCallCommand(int outerAltNumber, GrammarAST ID, GrammarAST arg) { }
|
||||||
|
public void lexerCommand(int outerAltNumber, GrammarAST ID) { }
|
||||||
|
|
||||||
public void traceIn(String ruleName, int ruleIndex) {
|
public void traceIn(String ruleName, int ruleIndex) {
|
||||||
System.err.println("enter "+ruleName+": "+input.LT(1));
|
System.err.println("enter "+ruleName+": "+input.LT(1));
|
||||||
|
@ -357,7 +359,7 @@ outerAlternative
|
||||||
;
|
;
|
||||||
|
|
||||||
lexerAlternative
|
lexerAlternative
|
||||||
: ^(LEXER_ALT_ACTION lexerElements lexerAction+)
|
: ^(LEXER_ALT_ACTION lexerElements lexerCommand+)
|
||||||
| lexerElements
|
| lexerElements
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -404,12 +406,14 @@ alternative
|
||||||
| ^(ALT EPSILON)
|
| ^(ALT EPSILON)
|
||||||
;
|
;
|
||||||
|
|
||||||
lexerAction
|
lexerCommand
|
||||||
: ^(LEXER_ACTION_CALL lexerActionExpr)
|
: ^(LEXER_ACTION_CALL ID lexerCommandExpr)
|
||||||
|
{lexerCallCommand(currentOuterAltNumber, $ID, $lexerCommandExpr.start);}
|
||||||
| ID
|
| ID
|
||||||
|
{lexerCommand(currentOuterAltNumber, $ID);}
|
||||||
;
|
;
|
||||||
|
|
||||||
lexerActionExpr
|
lexerCommandExpr
|
||||||
: ID
|
: ID
|
||||||
| INT
|
| INT
|
||||||
;
|
;
|
||||||
|
|
|
@ -75,12 +75,25 @@ public class Rule implements AttributeResolver {
|
||||||
add(new Attribute("int"));
|
add(new Attribute("int"));
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public String name;
|
public static Set<String> validLexerCommands = new HashSet<String>() {{
|
||||||
|
// CALLS
|
||||||
|
add("mode");
|
||||||
|
add("pushMode");
|
||||||
|
add("type");
|
||||||
|
add("channel");
|
||||||
|
|
||||||
|
// ACTIONS
|
||||||
|
add("popMode");
|
||||||
|
add("skip");
|
||||||
|
add("more");
|
||||||
|
}};
|
||||||
|
|
||||||
|
public String name;
|
||||||
public List<GrammarAST> modifiers;
|
public List<GrammarAST> modifiers;
|
||||||
|
|
||||||
public RuleAST ast;
|
public RuleAST ast;
|
||||||
public AttributeDict args;
|
public AttributeDict args;
|
||||||
public AttributeDict retvals;
|
public AttributeDict retvals;
|
||||||
public AttributeDict locals;
|
public AttributeDict locals;
|
||||||
|
|
||||||
/** In which grammar does this rule live? */
|
/** In which grammar does this rule live? */
|
||||||
|
@ -123,7 +136,7 @@ public class Rule implements AttributeResolver {
|
||||||
/** All rules have unique index 0..n-1 */
|
/** All rules have unique index 0..n-1 */
|
||||||
public int index;
|
public int index;
|
||||||
|
|
||||||
public int actionIndex = -1; // if lexer; 0..n-1
|
public int actionIndex = -1; // if lexer; 0..n-1 for n actions in a rule
|
||||||
|
|
||||||
public Rule(Grammar g, String name, RuleAST ast, int numberOfAlts) {
|
public Rule(Grammar g, String name, RuleAST ast, int numberOfAlts) {
|
||||||
this.g = g;
|
this.g = g;
|
||||||
|
@ -138,10 +151,15 @@ public class Rule implements AttributeResolver {
|
||||||
actions.add(actionAST);
|
actions.add(actionAST);
|
||||||
alt[currentAlt].actions.add(actionAST);
|
alt[currentAlt].actions.add(actionAST);
|
||||||
if ( g.isLexer() ) {
|
if ( g.isLexer() ) {
|
||||||
actionIndex = g.lexerActions.size();
|
defineLexerAction(actionAST);
|
||||||
if ( g.lexerActions.get(actionAST)==null ) {
|
}
|
||||||
g.lexerActions.put(actionAST, actionIndex);
|
}
|
||||||
}
|
|
||||||
|
/** Lexer actions are numbered across rules 0..n-1 */
|
||||||
|
public void defineLexerAction(ActionAST actionAST) {
|
||||||
|
actionIndex = g.lexerActions.size();
|
||||||
|
if ( g.lexerActions.get(actionAST)==null ) {
|
||||||
|
g.lexerActions.put(actionAST, actionIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,70 @@ public class TestLexerExec extends BaseTest {
|
||||||
assertEquals(expecting, found);
|
assertEquals(expecting, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void testSkipCommand() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"lexer grammar L;\n"+
|
||||||
|
"I : '0'..'9'+ {System.out.println(\"I\");} ;\n"+
|
||||||
|
"WS : (' '|'\\n') -> skip ;";
|
||||||
|
String found = execLexer("L.g", grammar, "L", "34 34");
|
||||||
|
String expecting =
|
||||||
|
"I\n" +
|
||||||
|
"I\n" +
|
||||||
|
"[@0,0:1='34',<3>,1:0]\n" +
|
||||||
|
"[@1,3:4='34',<3>,1:3]\n" +
|
||||||
|
"[@2,5:4='<EOF>',<-1>,1:5]\n";
|
||||||
|
assertEquals(expecting, found);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testMoreCommand() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"lexer grammar L;\n"+
|
||||||
|
"I : '0'..'9'+ {System.out.println(\"I\");} ;\n"+
|
||||||
|
"WS : '#' -> more ;";
|
||||||
|
String found = execLexer("L.g", grammar, "L", "34#10");
|
||||||
|
String expecting =
|
||||||
|
"I\n" +
|
||||||
|
"I\n" +
|
||||||
|
"[@0,0:1='34',<3>,1:0]\n" +
|
||||||
|
"[@1,2:4='#10',<3>,1:2]\n" +
|
||||||
|
"[@2,5:4='<EOF>',<-1>,1:5]\n";
|
||||||
|
assertEquals(expecting, found);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testTypeCommand() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"lexer grammar L;\n"+
|
||||||
|
"I : '0'..'9'+ {System.out.println(\"I\");} ;\n"+
|
||||||
|
"HASH : '#' -> type(HASH) ;";
|
||||||
|
String found = execLexer("L.g", grammar, "L", "34#");
|
||||||
|
String expecting =
|
||||||
|
"I\n" +
|
||||||
|
"[@0,0:1='34',<3>,1:0]\n" +
|
||||||
|
"[@1,2:2='#',<4>,1:2]\n" +
|
||||||
|
"[@2,3:2='<EOF>',<-1>,1:3]\n";
|
||||||
|
assertEquals(expecting, found);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testCombinedCommand() throws Exception {
|
||||||
|
String grammar =
|
||||||
|
"lexer grammar L;\n"+
|
||||||
|
"I : '0'..'9'+ {System.out.println(\"I\");} ;\n"+
|
||||||
|
"HASH : '#' -> type(HASH), skip, more ;";
|
||||||
|
String found = execLexer("L.g", grammar, "L", "34#11");
|
||||||
|
String expecting =
|
||||||
|
"I\n" +
|
||||||
|
"I\n" +
|
||||||
|
"[@0,0:1='34',<3>,1:0]\n" +
|
||||||
|
"[@1,2:4='#11',<3>,1:2]\n" +
|
||||||
|
"[@2,5:4='<EOF>',<-1>,1:5]\n";
|
||||||
|
assertEquals(expecting, found);
|
||||||
|
}
|
||||||
|
|
||||||
@Test public void testLexerMode() throws Exception {
|
@Test public void testLexerMode() throws Exception {
|
||||||
String grammar =
|
String grammar =
|
||||||
"lexer grammar L;\n" +
|
"lexer grammar L;\n" +
|
||||||
"STRING_START : '\"' {pushMode(STRING_MODE); more();} ;\n" +
|
"STRING_START : '\"' {pushMode(STRING_MODE); more();} ;\n" +
|
||||||
"WS : ' '|'\n' {skip();} ;\n"+
|
"WS : (' '|'\n') {skip();} ;\n"+
|
||||||
"mode STRING_MODE;\n"+
|
"mode STRING_MODE;\n"+
|
||||||
"STRING : '\"' {popMode();} ;\n"+
|
"STRING : '\"' {popMode();} ;\n"+
|
||||||
"ANY : . {more();} ;\n";
|
"ANY : . {more();} ;\n";
|
||||||
|
|
Loading…
Reference in New Issue