org.antlr.v4.codegen.target.SwiftTarget Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of antlr4 Show documentation
Show all versions of antlr4 Show documentation
The ANTLR 4 grammar compiler.
/*
* 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.8"; // 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