forked from jasder/antlr
got start on action trans testing
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6878]
This commit is contained in:
parent
05ef22d9e7
commit
89b05e0954
|
@ -12,8 +12,9 @@ javaTypeInitMap ::= [
|
|||
|
||||
// args must be <object-model-object>, <fields-resulting-in-STs>
|
||||
|
||||
ParserFile(file, parser, dfaDecls, bitSetDecls) ::= <<
|
||||
ParserFile(file, parser, dfaDecls, bitSetDecls, namedActions) ::= <<
|
||||
// $ANTLR ANTLRVersion> <file.fileName> generatedTimestamp>
|
||||
<namedActions.header>
|
||||
import org.antlr.v4.runtime.Parser;
|
||||
import org.antlr.v4.runtime.RecognizerSharedState;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
|
@ -25,19 +26,20 @@ import org.antlr.runtime.*;
|
|||
<parser>
|
||||
>>
|
||||
|
||||
Parser(p, funcs) ::= <<
|
||||
public class <p.name> extends Parser {
|
||||
Parser(parser, funcs) ::= <<
|
||||
public class <parser.name> extends Parser {
|
||||
<!
|
||||
public enum TokenType {
|
||||
EOF(-1),
|
||||
<p.tokens.keys:{k | <k>(<p.tokens.(k)>)}; separator=", ">
|
||||
<parser.tokens.keys:{k | <k>(<parser.tokens.(k)>)}; separator=", ">
|
||||
;
|
||||
public int type;
|
||||
TokenType(int type) { this.type = type; }
|
||||
}
|
||||
!>
|
||||
<p.tokens.keys:{k | public static final int <k>=<p.tokens.(k)>;}; separator="\n">
|
||||
<p:ctor()>
|
||||
<parser.tokens.keys:{k | public static final int <k>=<parser.tokens.(k)>;}; separator="\n">
|
||||
<namedActions.members>
|
||||
<parser:ctor()>
|
||||
<funcs; separator="\n">
|
||||
<dfaDecls; separator="\n">
|
||||
<bitSetDecls; separator="\n">
|
||||
|
@ -60,7 +62,7 @@ public <p.name>(TokenStream input, RecognizerSharedState state) {
|
|||
S.b_return retval = new S.b_return();
|
||||
*/
|
||||
|
||||
RuleFunction(f,code,decls,context,scope) ::= <<
|
||||
RuleFunction(f,code,decls,context,scope,namedActions,finallyAction) ::= <<
|
||||
<context>
|
||||
<scope>
|
||||
|
||||
|
@ -71,12 +73,15 @@ RuleFunction(f,code,decls,context,scope) ::= <<
|
|||
<if(f.ctxType)>
|
||||
state.ctx.push(_ctx);
|
||||
<endif>
|
||||
<namedActions.init>
|
||||
<decls; separator="\n">
|
||||
try {
|
||||
<code>
|
||||
}
|
||||
finally {
|
||||
<namedActions.after>
|
||||
<if(f.scope)><f.scope.name>_stack.pop();<endif>
|
||||
<finallyAction>
|
||||
<if(f.ctxType)>return (<f.ctxType>)state.ctx.pop();<endif>
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +214,7 @@ RulePropertyRef_tree(r) ::= "(<r.label>!=null?((<file.ASTLabelType>)<r.label>.t
|
|||
RulePropertyRef_text(r) ::= "(<r.label>!=null?((TokenStream)state.input).toString(<r.label>.start,<r.label>.stop):null)"
|
||||
RulePropertyRef_st(r) ::= "(<r.label>!=null?<r.label>.st:null)"
|
||||
|
||||
AddToList(a) ::= "<a.listName>.add(<a.opWithResultToAdd.label>);"
|
||||
AddToList(a) ::= "<a.listName>.add(<first(a.opWithResultToAdd.labels)>);"
|
||||
|
||||
TokenDecl(t) ::= "Token <t.name>;"
|
||||
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();"
|
||||
|
|
|
@ -139,24 +139,24 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
chunks.add(new SetAttr(x.getText(), rhsChunks));
|
||||
}
|
||||
|
||||
public void setDynamicScopeAttr(String expr, Token x, Token y, Token rhs) {
|
||||
}
|
||||
|
||||
public void dynamicScopeAttr(String expr, Token x, Token y) {
|
||||
}
|
||||
|
||||
public void setDynamicNegativeIndexedScopeAttr(String expr, Token x, Token y, Token index, Token rhs) {
|
||||
public void setDynamicScopeAttr(String expr, Token x, Token y, Token rhs) {
|
||||
}
|
||||
|
||||
public void dynamicNegativeIndexedScopeAttr(String expr, Token x, Token y, Token index) {
|
||||
}
|
||||
|
||||
public void setDynamicAbsoluteIndexedScopeAttr(String expr, Token x, Token y, Token index, Token rhs) {
|
||||
public void setDynamicNegativeIndexedScopeAttr(String expr, Token x, Token y, Token index, Token rhs) {
|
||||
}
|
||||
|
||||
public void dynamicAbsoluteIndexedScopeAttr(String expr, Token x, Token y, Token index) {
|
||||
}
|
||||
|
||||
public void setDynamicAbsoluteIndexedScopeAttr(String expr, Token x, Token y, Token index, Token rhs) {
|
||||
}
|
||||
|
||||
public void templateInstance(String expr) {
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,15 @@ public class OutputModelWalker {
|
|||
st.add(fieldName, nestedST);
|
||||
}
|
||||
}
|
||||
else if ( o instanceof Map ) {
|
||||
Map<Object, OutputModelObject> nestedOmoMap = (Map<Object, OutputModelObject>)o;
|
||||
Map<Object, ST> m = new HashMap<Object, ST>();
|
||||
for (Object key : nestedOmoMap.keySet()) {
|
||||
ST nestedST = walk(nestedOmoMap.get(key));
|
||||
m.put(key, nestedST);
|
||||
}
|
||||
st.add(fieldName, m);
|
||||
}
|
||||
else if ( o!=null ) {
|
||||
tool.errMgr.toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, fieldName);
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ public class Action extends SrcOp {
|
|||
public List<ActionChunk> chunks;
|
||||
public Action(OutputModelFactory factory, GrammarAST ast) {
|
||||
super(factory,ast);
|
||||
RuleFunction rf = factory.currentRule.peek();
|
||||
chunks = ActionTranslator.translateAction(factory,rf, ast.token, (ActionAST)ast);
|
||||
RuleFunction rf = null;
|
||||
if ( factory.currentRule.size()>0 ) rf = factory.currentRule.peek();
|
||||
chunks = ActionTranslator.translateAction(factory, rf, ast.token, (ActionAST)ast);
|
||||
System.out.println("actions="+chunks);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package org.antlr.v4.codegen.src;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.tool.GrammarAST;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** */
|
||||
public class ParserFile extends OutputModelObject {
|
||||
|
@ -13,6 +16,7 @@ public class ParserFile extends OutputModelObject {
|
|||
public List<BitSetDecl> bitSetDecls = new ArrayList<BitSetDecl>();
|
||||
public String TokenLabelType;
|
||||
public String ASTLabelType;
|
||||
public Map<String, Action> namedActions;
|
||||
|
||||
public ParserFile(OutputModelFactory factory, String fileName) {
|
||||
super(factory);
|
||||
|
@ -20,6 +24,11 @@ public class ParserFile extends OutputModelObject {
|
|||
factory.file = this;
|
||||
TokenLabelType = factory.gen.g.getOption("TokenLabelType");
|
||||
ASTLabelType = factory.gen.g.getOption("ASTLabelType");
|
||||
namedActions = new HashMap<String, Action>();
|
||||
for (String name : factory.gen.g.namedActions.keySet()) {
|
||||
GrammarAST ast = factory.gen.g.namedActions.get(name);
|
||||
namedActions.put(name, new Action(factory, ast));
|
||||
}
|
||||
parser = new Parser(factory, this);
|
||||
}
|
||||
|
||||
|
@ -34,6 +43,7 @@ public class ParserFile extends OutputModelObject {
|
|||
if ( sup!=null ) addAll(sup);
|
||||
add("parser");
|
||||
add("dfaDecls");
|
||||
add("namedActions");
|
||||
add("bitSetDecls");
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -12,9 +12,7 @@ import org.antlr.v4.tool.Attribute;
|
|||
import org.antlr.v4.tool.GrammarAST;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/** */
|
||||
public class RuleFunction extends OutputModelObject {
|
||||
|
@ -26,8 +24,9 @@ public class RuleFunction extends OutputModelObject {
|
|||
public Collection<String> tokenLabels;
|
||||
public List<String> elementsReferencedInRewrite;
|
||||
public List<String> exceptions;
|
||||
public String finallyAction;
|
||||
public Action finallyAction;
|
||||
public boolean isStartRule;
|
||||
public Map<String, Action> namedActions;
|
||||
|
||||
public StructDecl context;
|
||||
public DynamicScopeStruct scope;
|
||||
|
@ -75,8 +74,14 @@ public class RuleFunction extends OutputModelObject {
|
|||
ruleLabels = r.getLabelNames();
|
||||
tokenLabels = r.getTokenRefs();
|
||||
exceptions = Utils.nodesToStrings(r.exceptionActions);
|
||||
if ( r.finallyAction!=null ) finallyAction = r.finallyAction.getText();
|
||||
if ( r.finallyAction!=null ) finallyAction = new Action(factory, r.finallyAction);
|
||||
|
||||
namedActions = new HashMap<String, Action>();
|
||||
for (String name : r.namedActions.keySet()) {
|
||||
GrammarAST ast = r.namedActions.get(name);
|
||||
namedActions.put(name, new Action(factory, ast));
|
||||
}
|
||||
|
||||
factory.currentRule.push(this);
|
||||
GrammarASTAdaptor adaptor = new GrammarASTAdaptor(r.ast.token.getInputStream());
|
||||
GrammarAST blk = (GrammarAST)r.ast.getFirstChildWithType(ANTLRParser.BLOCK);
|
||||
|
@ -102,6 +107,7 @@ public class RuleFunction extends OutputModelObject {
|
|||
return new ArrayList<String>() {{
|
||||
if ( sup!=null ) addAll(sup);
|
||||
add("context"); add("scope"); add("decls"); add("code");
|
||||
add("finallyAction"); add("namedActions");
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,8 @@ public class Grammar implements AttributeResolver {
|
|||
* I track the AST node for the action in case I need the line number
|
||||
* for errors.
|
||||
*/
|
||||
public Map<String,ActionAST> namedActions = new HashMap<String,ActionAST>();
|
||||
public Map<String,ActionAST> namedActions = new HashMap<String,ActionAST>();
|
||||
////public DoubleKeyMap<String,String,ActionAST> namedActions = new DoubleKeyMap<String,String,ActionAST>();
|
||||
|
||||
public Map<String, AttributeDict> scopes = new LinkedHashMap<String, AttributeDict>();
|
||||
public static final String AUTO_GENERATED_TOKEN_NAME_PREFIX = "T__";
|
||||
|
@ -211,8 +212,11 @@ public class Grammar implements AttributeResolver {
|
|||
namedActions.put(name, (ActionAST)atAST.getChild(1));
|
||||
}
|
||||
else {
|
||||
String name = atAST.getChild(1).getText();
|
||||
namedActions.put(name, (ActionAST)atAST.getChild(2));
|
||||
String scope = atAST.getChild(0).getText();
|
||||
if ( scope.equals(getTypeString()) ) {
|
||||
String name = atAST.getChild(1).getText();
|
||||
namedActions.put(name, (ActionAST)atAST.getChild(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,66 @@
|
|||
package org.antlr.v4.test;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.antlr.v4.automata.LexerNFAFactory;
|
||||
import org.antlr.v4.automata.NFAFactory;
|
||||
import org.antlr.v4.automata.ParserNFAFactory;
|
||||
import org.antlr.v4.codegen.CodeGenerator;
|
||||
import org.antlr.v4.semantics.SemanticPipeline;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.antlr.v4.tool.LexerGrammar;
|
||||
import org.junit.Test;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
/** */
|
||||
public class TestAttributes extends BaseTest {
|
||||
public class TestActionTranslation extends BaseTest {
|
||||
String attributeTemplate =
|
||||
"parser grammar A;\n"+
|
||||
"@members {#members#<members>#end-members#}\n" +
|
||||
"a[int x] returns [int y]\n" +
|
||||
"@init {#init#<init>#end-init#}\n" +
|
||||
" : id=ID ids+=ID lab=b[34] {\n" +
|
||||
" #inline#<inline>#end-inline#\n" +
|
||||
" }\n" +
|
||||
" c\n" +
|
||||
" ;\n" +
|
||||
" finally {#finally#<finally>#end-finally#}\n" +
|
||||
"b[int d] returns [int e]\n" +
|
||||
" : {#inline2#<inline2>#end-inline2#}\n" +
|
||||
" ;\n" +
|
||||
"c : ;\n" +
|
||||
"d : ;\n";
|
||||
|
||||
String scopeTemplate =
|
||||
"parser grammar A;\n"+
|
||||
"@members {\n" +
|
||||
"<members>\n" +
|
||||
"}\n" +
|
||||
"scope S { int i; }\n" +
|
||||
"a[int x] returns [int y]\n" +
|
||||
"scope { int z; }\n" +
|
||||
"scope S;\n" +
|
||||
"@init {<init>}\n" +
|
||||
" : lab=b[34] {\n" +
|
||||
" <inline>" +
|
||||
" }\n" +
|
||||
" ;\n" +
|
||||
" finally {<finally>}\n" +
|
||||
"b[int d] returns [int e]\n" +
|
||||
"scope { int f; }\n" +
|
||||
" : {<inline2>}\n" +
|
||||
" ;\n" +
|
||||
"c : ;";
|
||||
|
||||
@Test public void testEscapedLessThanInAction() throws Exception {
|
||||
String action = "i<3; '<xmltag>'";
|
||||
String expected = "i<3; '<xmltag>'";
|
||||
testActions(attributeTemplate, "members", action, expected);
|
||||
testActions(attributeTemplate, "init", action, expected);
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
testActions(attributeTemplate, "finally", action, expected);
|
||||
testActions(attributeTemplate, "inline2", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testEscaped$InAction() throws Exception {
|
||||
String action = "int \\$n; \"\\$in string\\$\"";
|
||||
}
|
||||
|
@ -379,5 +433,38 @@ public class TestAttributes extends BaseTest {
|
|||
String action = "int x = $b::n;";
|
||||
}
|
||||
|
||||
public void testActions(String template, String actionName, String action, String expected) {
|
||||
ST st = new ST(template);
|
||||
st.add(actionName, action);
|
||||
String grammar = st.render();
|
||||
try {
|
||||
ErrorQueue equeue = new ErrorQueue();
|
||||
Grammar g = new Grammar(grammar);
|
||||
if ( g.ast!=null && !g.ast.hasErrors ) {
|
||||
SemanticPipeline sem = new SemanticPipeline(g);
|
||||
sem.process();
|
||||
|
||||
NFAFactory factory = new ParserNFAFactory(g);
|
||||
if ( g.isLexer() ) factory = new LexerNFAFactory((LexerGrammar)g);
|
||||
g.nfa = factory.createNFA();
|
||||
|
||||
CodeGenerator gen = new CodeGenerator(g);
|
||||
ST outputFileST = gen.generate();
|
||||
String output = outputFileST.render();
|
||||
System.out.println(output);
|
||||
String b = "#" + actionName + "#";
|
||||
int start = output.indexOf(b);
|
||||
String e = "#end-" + actionName + "#";
|
||||
int end = output.indexOf(e);
|
||||
String snippet = output.substring(start+b.length(),end);
|
||||
assertEquals(expected, snippet);
|
||||
}
|
||||
if ( equeue.size()>0 ) {
|
||||
System.err.println(equeue.toString(g.tool));
|
||||
}
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
re.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue