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 virtdata-lib-realer Show documentation
Show all versions of virtdata-lib-realer Show documentation
With inspiration from other libraries
/*
* 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.7.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);
}
}