From 89b05e095427afcbf39593032e2bb2cdd736b45f Mon Sep 17 00:00:00 2001 From: parrt Date: Thu, 20 May 2010 13:00:09 -0800 Subject: [PATCH] got start on action trans testing [git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6878] --- .../v4/tool/templates/codegen/Java/Java.stg | 21 +++-- .../antlr/v4/codegen/ActionTranslator.java | 10 +-- .../antlr/v4/codegen/OutputModelWalker.java | 9 ++ tool/src/org/antlr/v4/codegen/src/Action.java | 5 +- .../org/antlr/v4/codegen/src/ParserFile.java | 10 +++ .../antlr/v4/codegen/src/RuleFunction.java | 16 ++-- tool/src/org/antlr/v4/tool/Grammar.java | 10 ++- ...ibutes.java => TestActionTranslation.java} | 89 ++++++++++++++++++- 8 files changed, 146 insertions(+), 24 deletions(-) rename tool/test/org/antlr/v4/test/{TestAttributes.java => TestActionTranslation.java} (83%) diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg index 593c189e6..e6b3a3299 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg @@ -12,8 +12,9 @@ javaTypeInitMap ::= [ // args must be , -ParserFile(file, parser, dfaDecls, bitSetDecls) ::= << +ParserFile(file, parser, dfaDecls, bitSetDecls, namedActions) ::= << // $ANTLR ANTLRVersion> generatedTimestamp> + 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(p, funcs) ::= << -public class extends Parser { +Parser(parser, funcs) ::= << +public class extends Parser { ()}; separator=", "> + ()}; separator=", "> ; public int type; TokenType(int type) { this.type = type; } } !> - =;}; separator="\n"> - + =;}; separator="\n"> + + @@ -60,7 +62,7 @@ public (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) ::= << @@ -71,12 +73,15 @@ RuleFunction(f,code,decls,context,scope) ::= << state.ctx.push(_ctx); + try { } finally { + _stack.pop(); + return ()state.ctx.pop(); } } @@ -209,7 +214,7 @@ RulePropertyRef_tree(r) ::= "(!=null?(().t RulePropertyRef_text(r) ::= "(!=null?((TokenStream)state.input).toString(.start,.stop):null)" RulePropertyRef_st(r) ::= "(!=null?.st:null)" -AddToList(a) ::= ".add();" +AddToList(a) ::= ".add();" TokenDecl(t) ::= "Token ;" TokenListDecl(t) ::= "List\ = new ArrayList\();" diff --git a/tool/src/org/antlr/v4/codegen/ActionTranslator.java b/tool/src/org/antlr/v4/codegen/ActionTranslator.java index 0b96098a2..c60f30d2b 100644 --- a/tool/src/org/antlr/v4/codegen/ActionTranslator.java +++ b/tool/src/org/antlr/v4/codegen/ActionTranslator.java @@ -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) { } diff --git a/tool/src/org/antlr/v4/codegen/OutputModelWalker.java b/tool/src/org/antlr/v4/codegen/OutputModelWalker.java index e6f952129..bb1fe1fa1 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelWalker.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelWalker.java @@ -87,6 +87,15 @@ public class OutputModelWalker { st.add(fieldName, nestedST); } } + else if ( o instanceof Map ) { + Map nestedOmoMap = (Map)o; + Map m = new HashMap(); + 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); } diff --git a/tool/src/org/antlr/v4/codegen/src/Action.java b/tool/src/org/antlr/v4/codegen/src/Action.java index c3bc7fe03..c3739a403 100644 --- a/tool/src/org/antlr/v4/codegen/src/Action.java +++ b/tool/src/org/antlr/v4/codegen/src/Action.java @@ -14,8 +14,9 @@ public class Action extends SrcOp { public List 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); } diff --git a/tool/src/org/antlr/v4/codegen/src/ParserFile.java b/tool/src/org/antlr/v4/codegen/src/ParserFile.java index f45d3018f..b99b25fdd 100644 --- a/tool/src/org/antlr/v4/codegen/src/ParserFile.java +++ b/tool/src/org/antlr/v4/codegen/src/ParserFile.java @@ -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 bitSetDecls = new ArrayList(); public String TokenLabelType; public String ASTLabelType; + public Map 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(); + 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"); }}; } diff --git a/tool/src/org/antlr/v4/codegen/src/RuleFunction.java b/tool/src/org/antlr/v4/codegen/src/RuleFunction.java index b3add316f..5f25e363a 100644 --- a/tool/src/org/antlr/v4/codegen/src/RuleFunction.java +++ b/tool/src/org/antlr/v4/codegen/src/RuleFunction.java @@ -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 tokenLabels; public List elementsReferencedInRewrite; public List exceptions; - public String finallyAction; + public Action finallyAction; public boolean isStartRule; + public Map 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(); + 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() {{ if ( sup!=null ) addAll(sup); add("context"); add("scope"); add("decls"); add("code"); + add("finallyAction"); add("namedActions"); }}; } } diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index 7ef1255b4..e5b5ba631 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -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 namedActions = new HashMap(); + public Map namedActions = new HashMap(); + ////public DoubleKeyMap namedActions = new DoubleKeyMap(); public Map scopes = new LinkedHashMap(); 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)); + } } } diff --git a/tool/test/org/antlr/v4/test/TestAttributes.java b/tool/test/org/antlr/v4/test/TestActionTranslation.java similarity index 83% rename from tool/test/org/antlr/v4/test/TestAttributes.java rename to tool/test/org/antlr/v4/test/TestActionTranslation.java index 6d50d3a52..51546fe41 100644 --- a/tool/test/org/antlr/v4/test/TestAttributes.java +++ b/tool/test/org/antlr/v4/test/TestActionTranslation.java @@ -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##end-members#}\n" + + "a[int x] returns [int y]\n" + + "@init {#init##end-init#}\n" + + " : id=ID ids+=ID lab=b[34] {\n" + + " #inline##end-inline#\n" + + " }\n" + + " c\n" + + " ;\n" + + " finally {#finally##end-finally#}\n" + + "b[int d] returns [int e]\n" + + " : {#inline2##end-inline2#}\n" + + " ;\n" + + "c : ;\n" + + "d : ;\n"; + + String scopeTemplate = + "parser grammar A;\n"+ + "@members {\n" + + "\n" + + "}\n" + + "scope S { int i; }\n" + + "a[int x] returns [int y]\n" + + "scope { int z; }\n" + + "scope S;\n" + + "@init {}\n" + + " : lab=b[34] {\n" + + " " + + " }\n" + + " ;\n" + + " finally {}\n" + + "b[int d] returns [int e]\n" + + "scope { int f; }\n" + + " : {}\n" + + " ;\n" + + "c : ;"; + @Test public void testEscapedLessThanInAction() throws Exception { String action = "i<3; ''"; + String expected = "i<3; ''"; + 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); + } + } }