got start on action trans testing

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6878]
This commit is contained in:
parrt 2010-05-20 13:00:09 -08:00
parent 05ef22d9e7
commit 89b05e0954
8 changed files with 146 additions and 24 deletions

View File

@ -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>();"

View File

@ -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) {
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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");
}};
}

View File

@ -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");
}};
}
}

View File

@ -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));
}
}
}

View File

@ -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);
}
}
}