All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.antlr.v4.codegen.target.SwiftTarget Maven / Gradle / Ivy

There is a newer version: 4.13.2
Show newest version
/*
 * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

package org.antlr.v4.codegen.target;

import org.antlr.v4.codegen.CodeGenerator;
import org.antlr.v4.codegen.Target;
import org.antlr.v4.codegen.UnicodeEscapes;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.atn.ATNType;
import org.antlr.v4.runtime.atn.ActionTransition;
import org.antlr.v4.runtime.atn.AtomTransition;
import org.antlr.v4.runtime.atn.BlockStartState;
import org.antlr.v4.runtime.atn.DecisionState;
import org.antlr.v4.runtime.atn.LexerAction;
import org.antlr.v4.runtime.atn.LexerChannelAction;
import org.antlr.v4.runtime.atn.LexerCustomAction;
import org.antlr.v4.runtime.atn.LexerModeAction;
import org.antlr.v4.runtime.atn.LexerPushModeAction;
import org.antlr.v4.runtime.atn.LexerTypeAction;
import org.antlr.v4.runtime.atn.LoopEndState;
import org.antlr.v4.runtime.atn.PrecedencePredicateTransition;
import org.antlr.v4.runtime.atn.PredicateTransition;
import org.antlr.v4.runtime.atn.RangeTransition;
import org.antlr.v4.runtime.atn.RuleStartState;
import org.antlr.v4.runtime.atn.RuleTransition;
import org.antlr.v4.runtime.atn.SetTransition;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.runtime.misc.IntegerList;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.ast.GrammarAST;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.StringRenderer;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class SwiftTarget extends Target {

    /**
     * The Swift target can cache the code generation templates.
     */
    private static final ThreadLocal targetTemplates = new ThreadLocal();

    protected static final String[] swiftKeywords = {
            "associatedtype", "class", "deinit", "enum", "extension", "func", "import", "init", "inout", "internal",
            "let", "operator", "private", "protocol", "public", "static", "struct", "subscript", "typealias", "var",
            "break", "case", "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if",
            "in", "repeat", "return", "switch", "where", "while",
            "as", "catch", "dynamicType", "false", "is", "nil", "rethrows", "super", "self", "Self", "throw", "throws",
            "true", "try", "__COLUMN__", "__FILE__", "__FUNCTION__","__LINE__", "#column", "#file", "#function", "#line", "_" , "#available", "#else", "#elseif", "#endif", "#if", "#selector",
            "associativity", "convenience", "dynamic", "didSet", "final", "get", "infix", "indirect", "lazy",
            "left", "mutating", "none", "nonmutating", "optional", "override", "postfix", "precedence",
            "prefix", "Protocol", "required", "right", "set", "Type", "unowned", "weak", "willSet"
 };

    /** Avoid grammar symbols in this set to prevent conflicts in gen'd code. */
    protected final Set badWords = new HashSet();

    public String lexerAtnJSON = null;
    public String parserAtnJSON = null;
    public SwiftTarget(CodeGenerator gen) {
        super(gen, "Swift");
    }

    @Override
    public String getVersion() {
        return "4.9.1"; // Java and tool versions move in lock step
    }

    public Set getBadWords() {
        if (badWords.isEmpty()) {
            addBadWords();
        }

        return badWords;
    }

    protected void addBadWords() {
        badWords.addAll(Arrays.asList(swiftKeywords));
        badWords.add("rule");
        badWords.add("parserRule");
    }

    @Override
    public int getSerializedATNSegmentLimit() {
        // 65535 is the class file format byte limit for a UTF-8 encoded string literal
        // 3 is the maximum number of bytes it takes to encode a value in the range 0-0xFFFF
        return 65535 / 3;
    }

    @Override
    protected boolean visibleGrammarSymbolCausesIssueInGeneratedCode(GrammarAST idNode) {
        return getBadWords().contains(idNode.getText());
    }
    @Override
    protected void genFile(Grammar g,
                           ST outputFileST,
                           String fileName)
    {
        super.genFile(g,outputFileST,fileName);

        if (g.isLexer()  && lexerAtnJSON == null) {
            lexerAtnJSON = getLexerOrParserATNJson(g, fileName);
        }
        else if (!g.isLexer()  && parserAtnJSON == null && g.atn != null) {
            parserAtnJSON = getLexerOrParserATNJson(g, fileName);
        }

        if (fileName.endsWith(CodeGenerator.VOCAB_FILE_EXTENSION)) {
            String jsonFileName = fileName.substring(0,fileName.lastIndexOf(CodeGenerator.VOCAB_FILE_EXTENSION));
            if (lexerAtnJSON != null) {
                jsonFileName = jsonFileName +   "ATN.swift";
                // System.out.println(jsonFileName);
                //System.out.println(lexerAtnJSON);
                writeFile(lexerAtnJSON,g,jsonFileName);
            }

            if (parserAtnJSON != null) {
                jsonFileName = jsonFileName +   "ParserATN.swift";
                // System.out.println(jsonFileName);
                //System.out.println(parserAtnJSON);
                writeFile(parserAtnJSON,g,jsonFileName);
            }
        }

//        else if (g instanceof ParseR) {
//            System.out.println("parserGrammar");
//        }
//
        //getCodeGenerator().write(outputFileST, fileName);
    }

    private String getLexerOrParserATNJson(Grammar g, String fileName) {
        ST extST = getTemplates().getInstanceOf("codeFileExtension");
        String className = fileName.substring(0,fileName.lastIndexOf(extST.render()));

        String JSON = "class " + className + "ATN {\n" +
                "    let jsonString: String = \"" +
                serializeTojson(g.atn).replaceAll("\"","\\\\\"") +"\"\n}" ;  //.replaceAll("\"", "\\\\\"");
        return JSON;
    }

    private  void writeFile(String content,Grammar g,String fileName) {

        try {
            Writer w =    this.getCodeGenerator().tool.getOutputFileWriter(g, fileName);
            w.write(content);
            w.close();
        }
        catch (IOException ioe) {
            this.getCodeGenerator().tool.errMgr.toolError(ErrorType.CANNOT_WRITE_FILE,
                    ioe,
                    fileName);
        }
    }
    @Override
    protected STGroup loadTemplates() {
        STGroup result = targetTemplates.get();
        if (result == null) {
            result = super.loadTemplates();
            result.registerRenderer(String.class, new SwiftStringRenderer(), true);
            targetTemplates.set(result);
        }

        return result;
    }
    //added by janyou -->
    public String serializeTojson(ATN atn) {
        JsonObjectBuilder builder =  Json.createObjectBuilder();
        builder.add("version", ATNDeserializer.SERIALIZED_VERSION);
        builder.add("uuid", ATNDeserializer.SERIALIZED_UUID.toString());

        // convert grammar type to ATN const to avoid dependence on ANTLRParser
        builder.add("grammarType",atn.grammarType.ordinal());
        builder.add("maxTokenType",atn.maxTokenType);

        //states
        int nedges = 0;

        Map setIndices = new HashMap();
        List sets = new ArrayList();
        JsonArrayBuilder statesBuilder = Json.createArrayBuilder() ;
        IntegerList nonGreedyStates = new IntegerList();
        IntegerList precedenceStates = new IntegerList();
        for (ATNState s : atn.states) {
            JsonObjectBuilder stateBuilder = Json.createObjectBuilder();
            if ( s==null ) { // might be optimized away
                statesBuilder.addNull();
                continue;
            }

            int stateType = s.getStateType();

            stateBuilder.add("stateType",stateType);
            //stateBuilder.add("stateNumber",s.stateNumber);
            stateBuilder.add("ruleIndex",s.ruleIndex);

            if (s instanceof DecisionState && ((DecisionState)s).nonGreedy) {
                nonGreedyStates.add(s.stateNumber);
            }

            if (s instanceof RuleStartState && ((RuleStartState)s).isLeftRecursiveRule) {
                precedenceStates.add(s.stateNumber);
            }


            if ( s.getStateType() == ATNState.LOOP_END ) {
                stateBuilder.add("detailStateNumber",((LoopEndState)s).loopBackState.stateNumber);
            }
            else if ( s instanceof BlockStartState ) {
                stateBuilder.add("detailStateNumber",((BlockStartState)s).endState.stateNumber);
            }

            if (s.getStateType() != ATNState.RULE_STOP) {
                // the deserializer can trivially derive these edges, so there's no need to serialize them
                nedges += s.getNumberOfTransitions();
            }
            for (int i=0; i0 ) {
            for (ATNState modeStartState : atn.modeToStartState) {

                modeToStartStateBuilder.add(modeStartState.stateNumber);
            }
        }
        builder.add("modeToStartState",modeToStartStateBuilder);


        JsonArrayBuilder nsetsBuilder = Json.createArrayBuilder() ;
        int nsets = sets.size();
        //data.add(nsets);
        builder.add("nsets",nsets);

        for (IntervalSet set : sets) {
            JsonObjectBuilder setBuilder = Json.createObjectBuilder();
            boolean containsEof = set.contains(Token.EOF);
            if (containsEof && set.getIntervals().get(0).b == Token.EOF) {
                //data.add(set.getIntervals().size() - 1);

                setBuilder.add("size",set.getIntervals().size() - 1);
            }
            else {
                //data.add(set.getIntervals().size());

                setBuilder.add("size",set.getIntervals().size());
            }
            setBuilder.add("containsEof",containsEof ? 1 : 0);
            JsonArrayBuilder IntervalsBuilder = Json.createArrayBuilder() ;
            for (Interval I : set.getIntervals()) {
                JsonObjectBuilder IntervalBuilder = Json.createObjectBuilder();
                if (I.a == Token.EOF) {
                    if (I.b == Token.EOF) {
                        continue;
                    }
                    else {
                        IntervalBuilder.add("a",0);
                        //data.add(0);
                    }
                }
                else {
                    IntervalBuilder.add("a",I.a);

                    //data.add(I.a);
                }
                IntervalBuilder.add("b",I.b);
                IntervalsBuilder.add(IntervalBuilder);
            }
            setBuilder.add("Intervals",IntervalsBuilder);
            nsetsBuilder.add(setBuilder);
        }

        builder.add("IntervalSet",nsetsBuilder);
        //builder.add("nedges",nedges);
        JsonArrayBuilder allTransitionsBuilder = Json.createArrayBuilder() ;

        for (ATNState s : atn.states) {

            if ( s==null ) {
                // might be optimized away
                continue;
            }

            if (s.getStateType() == ATNState.RULE_STOP) {
                continue;
            }
            JsonArrayBuilder  transitionsBuilder = Json.createArrayBuilder() ;

            for (int i=0; i Character.MAX_VALUE) {
//				throw new UnsupportedOperationException("Serialized ATN data element out of range.");
//			}
//
//			int value = (data.get(i) + 2) & 0xFFFF;
//			data.set(i, value);
//		}
        JsonObject data = builder.build();
        //  System.out.print(data.toString());
        return data.toString();
    }

    //<--
    protected static class SwiftStringRenderer extends StringRenderer {

        @Override
        public String toString(Object o, String formatString, Locale locale) {
            if ("java-escape".equals(formatString)) {
                // 5C is the hex code for the \ itself
                return ((String)o).replace("\\u", "\\u005Cu");
            }

            return super.toString(o, formatString, locale);
        }

    }

	@Override
	protected void appendUnicodeEscapedCodePoint(int codePoint, StringBuilder sb) {
		UnicodeEscapes.appendSwiftStyleEscapedCodePoint(codePoint, sb);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy