1 /* 2 * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 package org.antlr.v4.test.tool; 7 8 import org.antlr.runtime.RecognitionException; 9 import org.antlr.v4.automata.ATNFactory; 10 import org.antlr.v4.automata.LexerATNFactory; 11 import org.antlr.v4.automata.ParserATNFactory; 12 import org.antlr.v4.codegen.CodeGenerator; 13 import org.antlr.v4.semantics.SemanticPipeline; 14 import org.antlr.v4.test.runtime.ErrorQueue; 15 import org.antlr.v4.tool.Grammar; 16 import org.antlr.v4.tool.LexerGrammar; 17 import org.junit.Before; 18 import org.junit.Test; 19 import org.stringtemplate.v4.AutoIndentWriter; 20 import org.stringtemplate.v4.InstanceScope; 21 import org.stringtemplate.v4.Interpreter; 22 import org.stringtemplate.v4.ST; 23 import org.stringtemplate.v4.STGroup; 24 import org.stringtemplate.v4.STWriter; 25 import org.stringtemplate.v4.misc.ErrorManager; 26 import org.stringtemplate.v4.misc.ErrorType; 27 28 import java.io.IOException; 29 import java.io.StringWriter; 30 import java.util.ArrayList; 31 import java.util.List; 32 33 import static org.junit.Assert.assertFalse; 34 import static org.junit.Assert.assertNotEquals; 35 36 public class TestCodeGeneration extends BaseJavaToolTest { 37 @Before 38 @Override testSetUp()39 public void testSetUp() throws Exception { 40 super.testSetUp(); 41 } 42 testArgDecl()43 @Test public void testArgDecl() throws Exception { // should use template not string 44 /*ErrorQueue equeue = */new ErrorQueue(); 45 String g = 46 "grammar T;\n" + 47 "a[int xyz] : 'a' ;\n"; 48 List<String> evals = getEvalInfoForString(g, "int xyz"); 49 System.out.println(evals); 50 for (int i = 0; i < evals.size(); i++) { 51 String eval = evals.get(i); 52 assertFalse("eval should not be POJO: "+eval, eval.startsWith("<pojo:")); 53 } 54 } 55 AssignTokenNamesToStringLiteralsInGeneratedParserRuleContexts()56 @Test public void AssignTokenNamesToStringLiteralsInGeneratedParserRuleContexts() throws Exception { 57 String g = 58 "grammar T;\n" + 59 "root: 't1';\n" + 60 "Token: 't1';"; 61 List<String> evals = getEvalInfoForString(g, "() { return getToken("); 62 assertNotEquals(0, evals.size()); 63 } 64 AssignTokenNamesToStringLiteralArraysInGeneratedParserRuleContexts()65 @Test public void AssignTokenNamesToStringLiteralArraysInGeneratedParserRuleContexts() throws Exception { 66 String g = 67 "grammar T;\n" + 68 "root: 't1' 't1';\n" + 69 "Token: 't1';"; 70 List<String> evals = getEvalInfoForString(g, "() { return getTokens("); 71 assertNotEquals(0, evals.size()); 72 } 73 74 /** Add tags around each attribute/template/value write */ 75 public static class DebugInterpreter extends Interpreter { 76 List<String> evals = new ArrayList<String>(); 77 ErrorManager myErrMgrCopy; 78 int tab = 0; DebugInterpreter(STGroup group, ErrorManager errMgr, boolean debug)79 public DebugInterpreter(STGroup group, ErrorManager errMgr, boolean debug) { 80 super(group, errMgr, debug); 81 myErrMgrCopy = errMgr; 82 } 83 84 @Override writeObject(STWriter out, InstanceScope scope, Object o, String[] options)85 protected int writeObject(STWriter out, InstanceScope scope, Object o, String[] options) { 86 if ( o instanceof ST ) { 87 String name = ((ST)o).getName(); 88 name = name.substring(1); 89 if ( !name.startsWith("_sub") ) { 90 try { 91 out.write("<ST:" + name + ">"); 92 evals.add("<ST:" + name + ">"); 93 int r = super.writeObject(out, scope, o, options); 94 out.write("</ST:" + name + ">"); 95 evals.add("</ST:" + name + ">"); 96 return r; 97 } catch (IOException ioe) { 98 myErrMgrCopy.IOError(scope.st, ErrorType.WRITE_IO_ERROR, ioe); 99 } 100 } 101 } 102 return super.writeObject(out, scope, o, options); 103 } 104 105 @Override writePOJO(STWriter out, InstanceScope scope, Object o, String[] options)106 protected int writePOJO(STWriter out, InstanceScope scope, Object o, String[] options) throws IOException { 107 Class<?> type = o.getClass(); 108 String name = type.getSimpleName(); 109 out.write("<pojo:"+name+">"+o.toString()+"</pojo:"+name+">"); 110 evals.add("<pojo:" + name + ">" + o.toString() + "</pojo:" + name + ">"); 111 return super.writePOJO(out, scope, o, options); 112 } 113 indent(STWriter out)114 public void indent(STWriter out) throws IOException { 115 for (int i=1; i<=tab; i++) { 116 out.write("\t"); 117 } 118 } 119 } 120 getEvalInfoForString(String grammarString, String pattern)121 public List<String> getEvalInfoForString(String grammarString, String pattern) throws RecognitionException { 122 ErrorQueue equeue = new ErrorQueue(); 123 Grammar g = new Grammar(grammarString); 124 List<String> evals = new ArrayList<String>(); 125 if ( g.ast!=null && !g.ast.hasErrors ) { 126 SemanticPipeline sem = new SemanticPipeline(g); 127 sem.process(); 128 129 ATNFactory factory = new ParserATNFactory(g); 130 if (g.isLexer()) factory = new LexerATNFactory((LexerGrammar) g); 131 g.atn = factory.createATN(); 132 133 CodeGenerator gen = new CodeGenerator(g); 134 ST outputFileST = gen.generateParser(); 135 136 // STViz viz = outputFileST.inspect(); 137 // try { 138 // viz.waitForClose(); 139 // } 140 // catch (Exception e) { 141 // e.printStackTrace(); 142 // } 143 144 boolean debug = false; 145 DebugInterpreter interp = 146 new DebugInterpreter(outputFileST.groupThatCreatedThisInstance, 147 outputFileST.impl.nativeGroup.errMgr, 148 debug); 149 InstanceScope scope = new InstanceScope(null, outputFileST); 150 StringWriter sw = new StringWriter(); 151 AutoIndentWriter out = new AutoIndentWriter(sw); 152 interp.exec(out, scope); 153 154 for (String e : interp.evals) { 155 if (e.contains(pattern)) { 156 evals.add(e); 157 } 158 } 159 } 160 if ( equeue.size()>0 ) { 161 System.err.println(equeue.toString()); 162 } 163 return evals; 164 } 165 } 166