Search in sources :

Example 21 with Action

use of org.antlr.v4.codegen.model.Action in project antlr4 by antlr.

the class ATNDeserializer method deserialize.

@SuppressWarnings("deprecation")
public ATN deserialize(char[] data) {
    data = data.clone();
    // was implemented.
    for (int i = 1; i < data.length; i++) {
        data[i] = (char) (data[i] - 2);
    }
    int p = 0;
    int version = toInt(data[p++]);
    if (version != SERIALIZED_VERSION) {
        String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with version %d (expected %d).", version, SERIALIZED_VERSION);
        throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
    }
    UUID uuid = toUUID(data, p);
    p += 8;
    if (!SUPPORTED_UUIDS.contains(uuid)) {
        String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with UUID %s (expected %s or a legacy UUID).", uuid, SERIALIZED_UUID);
        throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
    }
    boolean supportsPrecedencePredicates = isFeatureSupported(ADDED_PRECEDENCE_TRANSITIONS, uuid);
    boolean supportsLexerActions = isFeatureSupported(ADDED_LEXER_ACTIONS, uuid);
    ATNType grammarType = ATNType.values()[toInt(data[p++])];
    int maxTokenType = toInt(data[p++]);
    ATN atn = new ATN(grammarType, maxTokenType);
    //
    // STATES
    //
    List<Pair<LoopEndState, Integer>> loopBackStateNumbers = new ArrayList<Pair<LoopEndState, Integer>>();
    List<Pair<BlockStartState, Integer>> endStateNumbers = new ArrayList<Pair<BlockStartState, Integer>>();
    int nstates = toInt(data[p++]);
    for (int i = 0; i < nstates; i++) {
        int stype = toInt(data[p++]);
        // ignore bad type of states
        if (stype == ATNState.INVALID_TYPE) {
            atn.addState(null);
            continue;
        }
        int ruleIndex = toInt(data[p++]);
        if (ruleIndex == Character.MAX_VALUE) {
            ruleIndex = -1;
        }
        ATNState s = stateFactory(stype, ruleIndex);
        if (stype == ATNState.LOOP_END) {
            // special case
            int loopBackStateNumber = toInt(data[p++]);
            loopBackStateNumbers.add(new Pair<LoopEndState, Integer>((LoopEndState) s, loopBackStateNumber));
        } else if (s instanceof BlockStartState) {
            int endStateNumber = toInt(data[p++]);
            endStateNumbers.add(new Pair<BlockStartState, Integer>((BlockStartState) s, endStateNumber));
        }
        atn.addState(s);
    }
    // delay the assignment of loop back and end states until we know all the state instances have been initialized
    for (Pair<LoopEndState, Integer> pair : loopBackStateNumbers) {
        pair.a.loopBackState = atn.states.get(pair.b);
    }
    for (Pair<BlockStartState, Integer> pair : endStateNumbers) {
        pair.a.endState = (BlockEndState) atn.states.get(pair.b);
    }
    int numNonGreedyStates = toInt(data[p++]);
    for (int i = 0; i < numNonGreedyStates; i++) {
        int stateNumber = toInt(data[p++]);
        ((DecisionState) atn.states.get(stateNumber)).nonGreedy = true;
    }
    if (supportsPrecedencePredicates) {
        int numPrecedenceStates = toInt(data[p++]);
        for (int i = 0; i < numPrecedenceStates; i++) {
            int stateNumber = toInt(data[p++]);
            ((RuleStartState) atn.states.get(stateNumber)).isLeftRecursiveRule = true;
        }
    }
    //
    // RULES
    //
    int nrules = toInt(data[p++]);
    if (atn.grammarType == ATNType.LEXER) {
        atn.ruleToTokenType = new int[nrules];
    }
    atn.ruleToStartState = new RuleStartState[nrules];
    for (int i = 0; i < nrules; i++) {
        int s = toInt(data[p++]);
        RuleStartState startState = (RuleStartState) atn.states.get(s);
        atn.ruleToStartState[i] = startState;
        if (atn.grammarType == ATNType.LEXER) {
            int tokenType = toInt(data[p++]);
            if (tokenType == 0xFFFF) {
                tokenType = Token.EOF;
            }
            atn.ruleToTokenType[i] = tokenType;
            if (!isFeatureSupported(ADDED_LEXER_ACTIONS, uuid)) {
                // this piece of unused metadata was serialized prior to the
                // addition of LexerAction
                int actionIndexIgnored = toInt(data[p++]);
            }
        }
    }
    atn.ruleToStopState = new RuleStopState[nrules];
    for (ATNState state : atn.states) {
        if (!(state instanceof RuleStopState)) {
            continue;
        }
        RuleStopState stopState = (RuleStopState) state;
        atn.ruleToStopState[state.ruleIndex] = stopState;
        atn.ruleToStartState[state.ruleIndex].stopState = stopState;
    }
    //
    // MODES
    //
    int nmodes = toInt(data[p++]);
    for (int i = 0; i < nmodes; i++) {
        int s = toInt(data[p++]);
        atn.modeToStartState.add((TokensStartState) atn.states.get(s));
    }
    //
    // SETS
    //
    List<IntervalSet> sets = new ArrayList<IntervalSet>();
    // First, read all sets with 16-bit Unicode code points <= U+FFFF.
    p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_BMP));
    // deserialize sets with 32-bit arguments <= U+10FFFF.
    if (isFeatureSupported(ADDED_UNICODE_SMP, uuid)) {
        p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_SMP));
    }
    //
    // EDGES
    //
    int nedges = toInt(data[p++]);
    for (int i = 0; i < nedges; i++) {
        int src = toInt(data[p]);
        int trg = toInt(data[p + 1]);
        int ttype = toInt(data[p + 2]);
        int arg1 = toInt(data[p + 3]);
        int arg2 = toInt(data[p + 4]);
        int arg3 = toInt(data[p + 5]);
        Transition trans = edgeFactory(atn, ttype, src, trg, arg1, arg2, arg3, sets);
        //			System.out.println("EDGE "+trans.getClass().getSimpleName()+" "+
        //							   src+"->"+trg+
        //					   " "+Transition.serializationNames[ttype]+
        //					   " "+arg1+","+arg2+","+arg3);
        ATNState srcState = atn.states.get(src);
        srcState.addTransition(trans);
        p += 6;
    }
    // edges for rule stop states can be derived, so they aren't serialized
    for (ATNState state : atn.states) {
        for (int i = 0; i < state.getNumberOfTransitions(); i++) {
            Transition t = state.transition(i);
            if (!(t instanceof RuleTransition)) {
                continue;
            }
            RuleTransition ruleTransition = (RuleTransition) t;
            int outermostPrecedenceReturn = -1;
            if (atn.ruleToStartState[ruleTransition.target.ruleIndex].isLeftRecursiveRule) {
                if (ruleTransition.precedence == 0) {
                    outermostPrecedenceReturn = ruleTransition.target.ruleIndex;
                }
            }
            EpsilonTransition returnTransition = new EpsilonTransition(ruleTransition.followState, outermostPrecedenceReturn);
            atn.ruleToStopState[ruleTransition.target.ruleIndex].addTransition(returnTransition);
        }
    }
    for (ATNState state : atn.states) {
        if (state instanceof BlockStartState) {
            // we need to know the end state to set its start state
            if (((BlockStartState) state).endState == null) {
                throw new IllegalStateException();
            }
            // block end states can only be associated to a single block start state
            if (((BlockStartState) state).endState.startState != null) {
                throw new IllegalStateException();
            }
            ((BlockStartState) state).endState.startState = (BlockStartState) state;
        }
        if (state instanceof PlusLoopbackState) {
            PlusLoopbackState loopbackState = (PlusLoopbackState) state;
            for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
                ATNState target = loopbackState.transition(i).target;
                if (target instanceof PlusBlockStartState) {
                    ((PlusBlockStartState) target).loopBackState = loopbackState;
                }
            }
        } else if (state instanceof StarLoopbackState) {
            StarLoopbackState loopbackState = (StarLoopbackState) state;
            for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
                ATNState target = loopbackState.transition(i).target;
                if (target instanceof StarLoopEntryState) {
                    ((StarLoopEntryState) target).loopBackState = loopbackState;
                }
            }
        }
    }
    //
    // DECISIONS
    //
    int ndecisions = toInt(data[p++]);
    for (int i = 1; i <= ndecisions; i++) {
        int s = toInt(data[p++]);
        DecisionState decState = (DecisionState) atn.states.get(s);
        atn.decisionToState.add(decState);
        decState.decision = i - 1;
    }
    //
    if (atn.grammarType == ATNType.LEXER) {
        if (supportsLexerActions) {
            atn.lexerActions = new LexerAction[toInt(data[p++])];
            for (int i = 0; i < atn.lexerActions.length; i++) {
                LexerActionType actionType = LexerActionType.values()[toInt(data[p++])];
                int data1 = toInt(data[p++]);
                if (data1 == 0xFFFF) {
                    data1 = -1;
                }
                int data2 = toInt(data[p++]);
                if (data2 == 0xFFFF) {
                    data2 = -1;
                }
                LexerAction lexerAction = lexerActionFactory(actionType, data1, data2);
                atn.lexerActions[i] = lexerAction;
            }
        } else {
            // for compatibility with older serialized ATNs, convert the old
            // serialized action index for action transitions to the new
            // form, which is the index of a LexerCustomAction
            List<LexerAction> legacyLexerActions = new ArrayList<LexerAction>();
            for (ATNState state : atn.states) {
                for (int i = 0; i < state.getNumberOfTransitions(); i++) {
                    Transition transition = state.transition(i);
                    if (!(transition instanceof ActionTransition)) {
                        continue;
                    }
                    int ruleIndex = ((ActionTransition) transition).ruleIndex;
                    int actionIndex = ((ActionTransition) transition).actionIndex;
                    LexerCustomAction lexerAction = new LexerCustomAction(ruleIndex, actionIndex);
                    state.setTransition(i, new ActionTransition(transition.target, ruleIndex, legacyLexerActions.size(), false));
                    legacyLexerActions.add(lexerAction);
                }
            }
            atn.lexerActions = legacyLexerActions.toArray(new LexerAction[legacyLexerActions.size()]);
        }
    }
    markPrecedenceDecisions(atn);
    if (deserializationOptions.isVerifyATN()) {
        verifyATN(atn);
    }
    if (deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType.PARSER) {
        atn.ruleToTokenType = new int[atn.ruleToStartState.length];
        for (int i = 0; i < atn.ruleToStartState.length; i++) {
            atn.ruleToTokenType[i] = atn.maxTokenType + i + 1;
        }
        for (int i = 0; i < atn.ruleToStartState.length; i++) {
            BasicBlockStartState bypassStart = new BasicBlockStartState();
            bypassStart.ruleIndex = i;
            atn.addState(bypassStart);
            BlockEndState bypassStop = new BlockEndState();
            bypassStop.ruleIndex = i;
            atn.addState(bypassStop);
            bypassStart.endState = bypassStop;
            atn.defineDecisionState(bypassStart);
            bypassStop.startState = bypassStart;
            ATNState endState;
            Transition excludeTransition = null;
            if (atn.ruleToStartState[i].isLeftRecursiveRule) {
                // wrap from the beginning of the rule to the StarLoopEntryState
                endState = null;
                for (ATNState state : atn.states) {
                    if (state.ruleIndex != i) {
                        continue;
                    }
                    if (!(state instanceof StarLoopEntryState)) {
                        continue;
                    }
                    ATNState maybeLoopEndState = state.transition(state.getNumberOfTransitions() - 1).target;
                    if (!(maybeLoopEndState instanceof LoopEndState)) {
                        continue;
                    }
                    if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target instanceof RuleStopState) {
                        endState = state;
                        break;
                    }
                }
                if (endState == null) {
                    throw new UnsupportedOperationException("Couldn't identify final state of the precedence rule prefix section.");
                }
                excludeTransition = ((StarLoopEntryState) endState).loopBackState.transition(0);
            } else {
                endState = atn.ruleToStopState[i];
            }
            // all non-excluded transitions that currently target end state need to target blockEnd instead
            for (ATNState state : atn.states) {
                for (Transition transition : state.transitions) {
                    if (transition == excludeTransition) {
                        continue;
                    }
                    if (transition.target == endState) {
                        transition.target = bypassStop;
                    }
                }
            }
            // all transitions leaving the rule start state need to leave blockStart instead
            while (atn.ruleToStartState[i].getNumberOfTransitions() > 0) {
                Transition transition = atn.ruleToStartState[i].removeTransition(atn.ruleToStartState[i].getNumberOfTransitions() - 1);
                bypassStart.addTransition(transition);
            }
            // link the new states
            atn.ruleToStartState[i].addTransition(new EpsilonTransition(bypassStart));
            bypassStop.addTransition(new EpsilonTransition(endState));
            ATNState matchState = new BasicState();
            atn.addState(matchState);
            matchState.addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i]));
            bypassStart.addTransition(new EpsilonTransition(matchState));
        }
        if (deserializationOptions.isVerifyATN()) {
            // reverify after modification
            verifyATN(atn);
        }
    }
    return atn;
}
Also used : ArrayList(java.util.ArrayList) UUID(java.util.UUID) Pair(org.antlr.v4.runtime.misc.Pair) InvalidClassException(java.io.InvalidClassException) IntervalSet(org.antlr.v4.runtime.misc.IntervalSet)

Example 22 with Action

use of org.antlr.v4.codegen.model.Action in project antlr4 by antlr.

the class LeftRecursiveRuleTransformer method translateLeftRecursiveRule.

/** Return true if successful */
public boolean translateLeftRecursiveRule(GrammarRootAST ast, LeftRecursiveRule r, String language) {
    //tool.log("grammar", ruleAST.toStringTree());
    GrammarAST prevRuleAST = r.ast;
    String ruleName = prevRuleAST.getChild(0).getText();
    LeftRecursiveRuleAnalyzer leftRecursiveRuleWalker = new LeftRecursiveRuleAnalyzer(prevRuleAST, tool, ruleName, language);
    boolean isLeftRec;
    try {
        //			System.out.println("TESTING ---------------\n"+
        //							   leftRecursiveRuleWalker.text(ruleAST));
        isLeftRec = leftRecursiveRuleWalker.rec_rule();
    } catch (RecognitionException re) {
        // didn't match; oh well
        isLeftRec = false;
    }
    if (!isLeftRec)
        return false;
    // replace old rule's AST; first create text of altered rule
    GrammarAST RULES = (GrammarAST) ast.getFirstChildWithType(ANTLRParser.RULES);
    String newRuleText = leftRecursiveRuleWalker.getArtificialOpPrecRule();
    //		System.out.println("created: "+newRuleText);
    // now parse within the context of the grammar that originally created
    // the AST we are transforming. This could be an imported grammar so
    // we cannot just reference this.g because the role might come from
    // the imported grammar and not the root grammar (this.g)
    RuleAST t = parseArtificialRule(prevRuleAST.g, newRuleText);
    // reuse the name token from the original AST since it refers to the proper source location in the original grammar
    ((GrammarAST) t.getChild(0)).token = ((GrammarAST) prevRuleAST.getChild(0)).getToken();
    // update grammar AST and set rule's AST.
    RULES.setChild(prevRuleAST.getChildIndex(), t);
    r.ast = t;
    // Reduce sets in newly created rule tree
    GrammarTransformPipeline transform = new GrammarTransformPipeline(g, g.tool);
    transform.reduceBlocksToSets(r.ast);
    transform.expandParameterizedLoops(r.ast);
    // Rerun semantic checks on the new rule
    RuleCollector ruleCollector = new RuleCollector(g);
    ruleCollector.visit(t, "rule");
    BasicSemanticChecks basics = new BasicSemanticChecks(g, ruleCollector);
    // disable the assoc element option checks because they are already
    // handled for the pre-transformed rule.
    basics.checkAssocElementOption = false;
    basics.visit(t, "rule");
    // track recursive alt info for codegen
    r.recPrimaryAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
    r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.prefixAndOtherAlts);
    if (r.recPrimaryAlts.isEmpty()) {
        tool.errMgr.grammarError(ErrorType.NO_NON_LR_ALTS, g.fileName, ((GrammarAST) r.ast.getChild(0)).getToken(), r.name);
    }
    r.recOpAlts = new OrderedHashMap<Integer, LeftRecursiveRuleAltInfo>();
    r.recOpAlts.putAll(leftRecursiveRuleWalker.binaryAlts);
    r.recOpAlts.putAll(leftRecursiveRuleWalker.ternaryAlts);
    r.recOpAlts.putAll(leftRecursiveRuleWalker.suffixAlts);
    // walk alt info records and set their altAST to point to appropriate ALT subtree
    // from freshly created AST
    setAltASTPointers(r, t);
    // update Rule to just one alt and add prec alt
    ActionAST arg = (ActionAST) r.ast.getFirstChildWithType(ANTLRParser.ARG_ACTION);
    if (arg != null) {
        r.args = ScopeParser.parseTypedArgList(arg, arg.getText(), g);
        r.args.type = AttributeDict.DictType.ARG;
        r.args.ast = arg;
        // todo: isn't this Rule or something?
        arg.resolver = r.alt[1];
    }
    // these are so $label in action translation works
    for (Pair<GrammarAST, String> pair : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
        GrammarAST labelNode = pair.a;
        GrammarAST labelOpNode = (GrammarAST) labelNode.getParent();
        GrammarAST elementNode = (GrammarAST) labelOpNode.getChild(1);
        LabelElementPair lp = new LabelElementPair(g, labelNode, elementNode, labelOpNode.getType());
        r.alt[1].labelDefs.map(labelNode.getText(), lp);
    }
    // copy to rule from walker
    r.leftRecursiveRuleRefLabels = leftRecursiveRuleWalker.leftRecursiveRuleRefLabels;
    tool.log("grammar", "added: " + t.toStringTree());
    return true;
}
Also used : RuleAST(org.antlr.v4.tool.ast.RuleAST) RuleCollector(org.antlr.v4.semantics.RuleCollector) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) LabelElementPair(org.antlr.v4.tool.LabelElementPair) ActionAST(org.antlr.v4.tool.ast.ActionAST) GrammarTransformPipeline(org.antlr.v4.tool.GrammarTransformPipeline) BasicSemanticChecks(org.antlr.v4.semantics.BasicSemanticChecks) RecognitionException(org.antlr.runtime.RecognitionException)

Example 23 with Action

use of org.antlr.v4.codegen.model.Action in project antlr4 by antlr.

the class LexerATNFactory method action.

@Override
public Handle action(String action) {
    if (action.trim().isEmpty()) {
        ATNState left = newState(null);
        ATNState right = newState(null);
        epsilon(left, right);
        return new Handle(left, right);
    }
    // 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);
}
Also used : CommonToken(org.antlr.runtime.CommonToken) ATNState(org.antlr.v4.runtime.atn.ATNState) ActionAST(org.antlr.v4.tool.ast.ActionAST)

Example 24 with Action

use of org.antlr.v4.codegen.model.Action in project antlr4 by antlr.

the class LexerATNFactory method action.

@Override
public Handle action(ActionAST action) {
    int ruleIndex = currentRule.index;
    int actionIndex = g.lexerActions.get(action);
    LexerCustomAction lexerAction = new LexerCustomAction(ruleIndex, actionIndex);
    return action(action, lexerAction);
}
Also used : LexerCustomAction(org.antlr.v4.runtime.atn.LexerCustomAction)

Example 25 with Action

use of org.antlr.v4.codegen.model.Action in project antlr4 by antlr.

the class LexerATNFactory method createATN.

@Override
public ATN createATN() {
    // BUILD ALL START STATES (ONE PER MODE)
    Set<String> modes = ((LexerGrammar) g).modes.keySet();
    for (String modeName : modes) {
        // create s0, start state; implied Tokens rule node
        TokensStartState startState = newState(TokensStartState.class, null);
        atn.modeNameToStartState.put(modeName, startState);
        atn.modeToStartState.add(startState);
        atn.defineDecisionState(startState);
    }
    // INIT ACTION, RULE->TOKEN_TYPE MAP
    atn.ruleToTokenType = new int[g.rules.size()];
    for (Rule r : g.rules.values()) {
        atn.ruleToTokenType[r.index] = g.getTokenType(r.name);
    }
    // CREATE ATN FOR EACH RULE
    _createATN(g.rules.values());
    atn.lexerActions = new LexerAction[indexToActionMap.size()];
    for (Map.Entry<Integer, LexerAction> entry : indexToActionMap.entrySet()) {
        atn.lexerActions[entry.getKey()] = entry.getValue();
    }
    // LINK MODE START STATE TO EACH TOKEN RULE
    for (String modeName : modes) {
        List<Rule> rules = ((LexerGrammar) g).modes.get(modeName);
        TokensStartState startState = atn.modeNameToStartState.get(modeName);
        for (Rule r : rules) {
            if (!r.isFragment()) {
                RuleStartState s = atn.ruleToStartState[r.index];
                epsilon(startState, s);
            }
        }
    }
    ATNOptimizer.optimize(g, atn);
    return atn;
}
Also used : TokensStartState(org.antlr.v4.runtime.atn.TokensStartState) LexerAction(org.antlr.v4.runtime.atn.LexerAction) RuleStartState(org.antlr.v4.runtime.atn.RuleStartState) Rule(org.antlr.v4.tool.Rule) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ST (org.stringtemplate.v4.ST)11 ActionAST (org.antlr.v4.tool.ast.ActionAST)9 GrammarAST (org.antlr.v4.tool.ast.GrammarAST)9 Grammar (org.antlr.v4.tool.Grammar)8 LexerGrammar (org.antlr.v4.tool.LexerGrammar)8 STGroup (org.stringtemplate.v4.STGroup)8 ArrayList (java.util.ArrayList)7 ATNFactory (org.antlr.v4.automata.ATNFactory)6 LexerATNFactory (org.antlr.v4.automata.LexerATNFactory)6 ParserATNFactory (org.antlr.v4.automata.ParserATNFactory)6 CodeGenerator (org.antlr.v4.codegen.CodeGenerator)6 ATNState (org.antlr.v4.runtime.atn.ATNState)6 ActionTransition (org.antlr.v4.runtime.atn.ActionTransition)6 SemanticPipeline (org.antlr.v4.semantics.SemanticPipeline)6 ErrorQueue (org.antlr.v4.test.runtime.ErrorQueue)6 STGroupString (org.stringtemplate.v4.STGroupString)6 BaseRuntimeTest.antlrOnString (org.antlr.v4.test.runtime.BaseRuntimeTest.antlrOnString)5 Rule (org.antlr.v4.tool.Rule)5 HashMap (java.util.HashMap)4 Action (org.antlr.v4.codegen.model.Action)4