got dyn scope code gen partially going
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6879]
This commit is contained in:
parent
89b05e0954
commit
be72c49e53
|
@ -26,7 +26,7 @@ import org.antlr.runtime.*;
|
|||
<parser>
|
||||
>>
|
||||
|
||||
Parser(parser, funcs) ::= <<
|
||||
Parser(parser, scopes, funcs) ::= <<
|
||||
public class <parser.name> extends Parser {
|
||||
<!
|
||||
public enum TokenType {
|
||||
|
@ -38,6 +38,7 @@ public class <parser.name> extends Parser {
|
|||
}
|
||||
!>
|
||||
<parser.tokens.keys:{k | public static final int <k>=<parser.tokens.(k)>;}; separator="\n">
|
||||
<scopes>
|
||||
<namedActions.members>
|
||||
<parser:ctor()>
|
||||
<funcs; separator="\n">
|
||||
|
@ -67,12 +68,13 @@ RuleFunction(f,code,decls,context,scope,namedActions,finallyAction) ::= <<
|
|||
<scope>
|
||||
|
||||
<if(f.modifiers)><f.modifiers:{f | <f> }><else>public final <endif><if(f.ctxType)><f.ctxType><else>void<endif> <f.name>(<f.ctxType> _ctx) throws RecognitionException {
|
||||
<if(f.scope)>
|
||||
<f.scope.name>_stack.push(new <f.scope.name>());
|
||||
<endif>
|
||||
<if(f.ctxType)>
|
||||
state.ctx.push(_ctx);
|
||||
<endif>
|
||||
<if(f.scope)>
|
||||
<f.scope.name>_stack.push(new <f.scope.name>());
|
||||
<endif>
|
||||
<f.globalScopesUsed:{s | <s>_stack.push(new <s>());}; separator="\n">
|
||||
<namedActions.init>
|
||||
<decls; separator="\n">
|
||||
try {
|
||||
|
@ -80,6 +82,7 @@ RuleFunction(f,code,decls,context,scope,namedActions,finallyAction) ::= <<
|
|||
}
|
||||
finally {
|
||||
<namedActions.after>
|
||||
<f.globalScopesUsed:{s | <s>_stack.pop();}; separator="\n">
|
||||
<if(f.scope)><f.scope.name>_stack.pop();<endif>
|
||||
<finallyAction>
|
||||
<if(f.ctxType)>return (<f.ctxType>)state.ctx.pop();<endif>
|
||||
|
@ -214,6 +217,13 @@ 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)"
|
||||
|
||||
DynScopeAttrRef(s) ::= "(<s.scope>_stack.peek()).<s.attr>"
|
||||
DynScopeAttrRef_negIndex(s, indexChunks) ::= <<
|
||||
(<s.scope>_stack.elementAt(<s.scope>_stack.size()-<indexChunks>-1)).<s.attr>
|
||||
>>
|
||||
DynScopeAttrRef_index(s, indexChunks) ::=
|
||||
"(<s.scope>_stack.elementAt(<indexChunks>)).<s.attr>"
|
||||
|
||||
AddToList(a) ::= "<a.listName>.add(<first(a.opWithResultToAdd.labels)>);"
|
||||
|
||||
TokenDecl(t) ::= "Token <t.name>;"
|
||||
|
@ -237,7 +247,7 @@ DynamicScopeStruct(d,attrs) ::= <<
|
|||
public static class <d.name> {
|
||||
<attrs:{a | <a>;}; separator="\n">
|
||||
};
|
||||
public QStack\<<f.scope.name>\> <f.scope.name>_stack = new QStack\<<f.scope.name>\>();
|
||||
public QStack\<<d.name>\> <d.name>_stack = new QStack\<<d.name>\>();
|
||||
>>
|
||||
|
||||
AttributeDecl(d) ::= "<d.decl>"
|
||||
|
|
|
@ -80,6 +80,7 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
}
|
||||
|
||||
public void attr(String expr, Token x) {
|
||||
// TODO: $SCOPENAME
|
||||
System.out.println("attr "+x);
|
||||
Attribute a = node.resolver.resolveToAttribute(x.getText(), node);
|
||||
if ( a!=null ) {
|
||||
|
@ -125,7 +126,13 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
Attribute a = node.resolver.resolveToAttribute(x.getText(), y.getText(), node);
|
||||
switch ( a.dict.type ) {
|
||||
case ARG: chunks.add(new ArgRef(y.getText())); break; // has to be current rule
|
||||
case RET: chunks.add(new QRetValueRef(getRuleLabel(x.getText()), y.getText())); break;
|
||||
case RET:
|
||||
if ( factory.currentRule.size()>0 && factory.currentRule.peek().name.equals(x.getText()) ) {
|
||||
chunks.add(new RetValueRef(y.getText())); break;
|
||||
}
|
||||
else {
|
||||
chunks.add(new QRetValueRef(getRuleLabel(x.getText()), y.getText())); break;
|
||||
}
|
||||
case PREDEFINED_RULE: chunks.add(getRulePropertyRef(x, y)); break;
|
||||
case TOKEN: chunks.add(getTokenPropertyRef(x, y)); break;
|
||||
// case PREDEFINED_LEXER_RULE: chunks.add(new RetValueRef(x.getText())); break;
|
||||
|
@ -140,18 +147,30 @@ public class ActionTranslator implements ActionSplitterListener {
|
|||
}
|
||||
|
||||
public void dynamicScopeAttr(String expr, Token x, Token y) {
|
||||
System.out.println("scoped "+x+"."+y);
|
||||
// we assume valid, just gen code
|
||||
String scope = x.getText();
|
||||
if ( factory.g.getRule(x.getText())!=null ) {
|
||||
scope = factory.gen.target.getRuleDynamicScopeStructName(scope);
|
||||
}
|
||||
chunks.add(new DynScopeAttrRef(scope, y.getText()));
|
||||
}
|
||||
|
||||
public void setDynamicScopeAttr(String expr, Token x, Token y, Token rhs) {
|
||||
}
|
||||
|
||||
public void dynamicNegativeIndexedScopeAttr(String expr, Token x, Token y, Token index) {
|
||||
List<ActionChunk> indexChunks = translateActionChunk(factory,rf,index.getText(),node);
|
||||
chunks.add(new DynScopeAttrRef_negIndex(x.getText(), y.getText(), indexChunks));
|
||||
}
|
||||
|
||||
public void setDynamicNegativeIndexedScopeAttr(String expr, Token x, Token y, Token index, Token rhs) {
|
||||
|
||||
}
|
||||
|
||||
public void dynamicAbsoluteIndexedScopeAttr(String expr, Token x, Token y, Token index) {
|
||||
List<ActionChunk> indexChunks = translateActionChunk(factory,rf,index.getText(),node);
|
||||
chunks.add(new DynScopeAttrRef_index(x.getText(), y.getText(), indexChunks));
|
||||
}
|
||||
|
||||
public void setDynamicAbsoluteIndexedScopeAttr(String expr, Token x, Token y, Token index, Token rhs) {
|
||||
|
|
|
@ -135,7 +135,7 @@ public class Target {
|
|||
if ( r.args==null && r.retvals==null ) return "ParserRuleContext";
|
||||
return r.name+"_ctx";
|
||||
}
|
||||
public String getDynamicScopeStructName(String ruleName) { return ruleName+"_scope"; }
|
||||
public String getRuleDynamicScopeStructName(String ruleName) { return ruleName+"_scope"; }
|
||||
|
||||
// should be same for all refs to same token like $ID within single rule function
|
||||
public String getImplicitTokenLabel(String tokenName) { return "_t"+tokenName; }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.antlr.v4.codegen.src;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.tool.AttributeDict;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -13,7 +14,8 @@ public class Parser extends OutputModelObject {
|
|||
public String name;
|
||||
public Map<String,Integer> tokens;
|
||||
public List<RuleFunction> funcs = new ArrayList<RuleFunction>();
|
||||
ParserFile file;
|
||||
public List<DynamicScopeStruct> scopes = new ArrayList<DynamicScopeStruct>();
|
||||
public ParserFile file;
|
||||
|
||||
public Parser(OutputModelFactory factory, ParserFile file) {
|
||||
this.factory = factory;
|
||||
|
@ -24,12 +26,15 @@ public class Parser extends OutputModelObject {
|
|||
Integer ttype = factory.g.tokenNameToTypeMap.get(t);
|
||||
if ( ttype>0 ) tokens.put(t, ttype);
|
||||
}
|
||||
for (AttributeDict d : factory.g.scopes.values()) {
|
||||
scopes.add( new DynamicScopeStruct(factory, d.name, d.attributes.values()) );
|
||||
}
|
||||
for (Rule r : factory.g.rules.values()) funcs.add( new RuleFunction(factory, r) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getChildren() {
|
||||
final List<String> sup = super.getChildren();
|
||||
return new ArrayList<String>() {{ if ( sup!=null ) addAll(sup); add("funcs"); }};
|
||||
return new ArrayList<String>() {{ if ( sup!=null ) addAll(sup); add("funcs"); add("scopes"); }};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,10 +59,14 @@ public class RuleFunction extends OutputModelObject {
|
|||
argsAndReturnValues.addAll(r.retvals.attributes.values());
|
||||
}
|
||||
if ( r.scope!=null ) {
|
||||
scope = new DynamicScopeStruct(factory, factory.gen.target.getDynamicScopeStructName(r.name),
|
||||
scope = new DynamicScopeStruct(factory, factory.gen.target.getRuleDynamicScopeStructName(r.name),
|
||||
r.scope.attributes.values());
|
||||
}
|
||||
|
||||
//globalScopesUsed = new ArrayList<String>();
|
||||
//for (Token t : r.useScopes) globalScopesUsed.add(t.getText());
|
||||
globalScopesUsed = Utils.apply(r.useScopes, "getText");
|
||||
|
||||
if ( argsAndReturnValues.size()>0 ) {
|
||||
context = new StructDecl(factory, factory.gen.target.getRuleFunctionContextStructName(r),
|
||||
argsAndReturnValues);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package org.antlr.v4.codegen.src.actions;
|
||||
|
||||
/** */
|
||||
public class DynScopeAttrRef extends ActionChunk {
|
||||
public String scope;
|
||||
public String attr;
|
||||
|
||||
public DynScopeAttrRef(String scope, String attr) {
|
||||
this.attr = attr;
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.antlr.v4.codegen.src.actions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** */
|
||||
public class DynScopeAttrRef_index extends DynScopeAttrRef {
|
||||
public List<ActionChunk> indexChunks;
|
||||
public DynScopeAttrRef_index(String scope, String attr, List<ActionChunk> indexChunks) {
|
||||
super(scope, attr);
|
||||
this.indexChunks = indexChunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getChildren() {
|
||||
final List<String> sup = super.getChildren();
|
||||
return new ArrayList<String>() {{
|
||||
if ( sup!=null ) addAll(sup);
|
||||
add("indexChunks");
|
||||
}};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.antlr.v4.codegen.src.actions;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** */
|
||||
public class DynScopeAttrRef_negIndex extends DynScopeAttrRef_index {
|
||||
public DynScopeAttrRef_negIndex(String scope, String attr, List<ActionChunk> indexChunks) {
|
||||
super(scope, attr, indexChunks);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package org.antlr.v4.misc;
|
|||
|
||||
import org.antlr.v4.tool.GrammarAST;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
@ -117,4 +118,20 @@ public class Utils {
|
|||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
public static <From,To> List<To> apply(List<From> list, String methodName) {
|
||||
if ( list==null ) return null;
|
||||
List<To> b = new ArrayList<To>();
|
||||
for (From f : list) {
|
||||
try {
|
||||
Method m = f.getClass().getMethod(methodName, (Class[])null);
|
||||
To r = (To)m.invoke(f, (Object[])null);
|
||||
b.add(r);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,8 @@ public class AttributeChecks implements ActionSplitterListener {
|
|||
if ( node.resolver.resolveToAttribute(x.getText(), y.getText(), node)==null ) {
|
||||
Rule rref = isolatedRuleRef(x.getText());
|
||||
if ( rref!=null ) {
|
||||
if ( rref!=null && rref.args!=null && rref.args.get(y.getText())!=null ) {
|
||||
//if ( r.name.equals(x.getText()) ) return; // $a.x in rule a is ok
|
||||
if ( rref.args!=null && rref.args.get(y.getText())!=null ) {
|
||||
g.tool.errMgr.grammarError(ErrorType.INVALID_RULE_PARAMETER_REF,
|
||||
g.fileName, y, y.getText(), expr);
|
||||
}
|
||||
|
|
|
@ -78,8 +78,7 @@ public class Alternative implements AttributeResolver {
|
|||
*/
|
||||
public Attribute resolveToAttribute(String x, String y, ActionAST node) {
|
||||
if ( rule.name.equals(x) ) { // x is this rule?
|
||||
AttributeDict d = rule.getPredefinedScope(LabelType.RULE_LABEL);
|
||||
return d.get(y);
|
||||
return rule.resolveToAttribute(x, y, node);
|
||||
}
|
||||
if ( tokenRefs.get(x)!=null ) { // token ref in this alt?
|
||||
return rule.getPredefinedScope(LabelType.TOKEN_LABEL).get(y);
|
||||
|
|
|
@ -186,8 +186,7 @@ public class Rule implements AttributeResolver {
|
|||
/** $x.y Attribute: x is surrounding rule, label ref (in any alts) */
|
||||
public Attribute resolveToAttribute(String x, String y, ActionAST node) {
|
||||
if ( this.name.equals(x) ) { // x is this rule?
|
||||
AttributeDict d = getPredefinedScope(LabelType.RULE_LABEL);
|
||||
return d.get(y);
|
||||
return resolveToAttribute(y, node);
|
||||
}
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
if ( anyLabelDef!=null ) {
|
||||
|
@ -221,7 +220,7 @@ public class Rule implements AttributeResolver {
|
|||
|
||||
public boolean resolvesToToken(String x, ActionAST node) {
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
if ( anyLabelDef.type==LabelType.TOKEN_LABEL ) return true;
|
||||
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.TOKEN_LABEL ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ public class TestActionTranslation extends BaseTest {
|
|||
String attributeTemplate =
|
||||
"parser grammar A;\n"+
|
||||
"@members {#members#<members>#end-members#}\n" +
|
||||
"a[int x] returns [int y]\n" +
|
||||
"a[int x, int x1] returns [int y]\n" +
|
||||
"@init {#init#<init>#end-init#}\n" +
|
||||
" : id=ID ids+=ID lab=b[34] {\n" +
|
||||
" : id=ID ids+=ID lab=b[34] c d {\n" +
|
||||
" #inline#<inline>#end-inline#\n" +
|
||||
" }\n" +
|
||||
" c\n" +
|
||||
|
@ -27,29 +27,24 @@ public class TestActionTranslation extends BaseTest {
|
|||
"b[int d] returns [int e]\n" +
|
||||
" : {#inline2#<inline2>#end-inline2#}\n" +
|
||||
" ;\n" +
|
||||
"c : ;\n" +
|
||||
"c returns [int x, int y] : ;\n" +
|
||||
"d : ;\n";
|
||||
|
||||
String scopeTemplate =
|
||||
"parser grammar A;\n"+
|
||||
"@members {\n" +
|
||||
"<members>\n" +
|
||||
"#members#<members>#end-members#\n" +
|
||||
"}\n" +
|
||||
"scope S { int i; }\n" +
|
||||
"a[int x] returns [int y]\n" +
|
||||
"a\n" +
|
||||
"scope { int z; }\n" +
|
||||
"scope S;\n" +
|
||||
"@init {<init>}\n" +
|
||||
" : lab=b[34] {\n" +
|
||||
" <inline>" +
|
||||
"@init {#init#<init>#end-init#}\n" +
|
||||
" : {\n" +
|
||||
" #inline#<inline>#end-inline#" +
|
||||
" }\n" +
|
||||
" ;\n" +
|
||||
" finally {<finally>}\n" +
|
||||
"b[int d] returns [int e]\n" +
|
||||
"scope { int f; }\n" +
|
||||
" : {<inline2>}\n" +
|
||||
" ;\n" +
|
||||
"c : ;";
|
||||
" finally {#finally#<finally>#end-finally#}\n";
|
||||
|
||||
@Test public void testEscapedLessThanInAction() throws Exception {
|
||||
String action = "i<3; '<xmltag>'";
|
||||
|
@ -62,133 +57,125 @@ public class TestActionTranslation extends BaseTest {
|
|||
}
|
||||
|
||||
@Test public void testEscaped$InAction() throws Exception {
|
||||
String action = "int \\$n; \"\\$in string\\$\"";
|
||||
}
|
||||
@Test public void testArguments() throws Exception {
|
||||
String action = "$i; $i.x; $u; $u.x";
|
||||
}
|
||||
@Test public void testComplicatedArgParsing() throws Exception {
|
||||
String action = "x, (*a).foo(21,33), 3.2+1, '\\n', "+
|
||||
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
}
|
||||
@Test public void testBracketArgParsing() throws Exception {
|
||||
}
|
||||
@Test public void testStringArgParsing() throws Exception {
|
||||
String action = "34, '{', \"it's<\", '\"', \"\\\"\", 19";
|
||||
}
|
||||
@Test public void testComplicatedSingleArgParsing() throws Exception {
|
||||
String action = "(*a).foo(21,33,\",\")";
|
||||
}
|
||||
@Test public void testArgWithLT() throws Exception {
|
||||
String action = "34<50";
|
||||
}
|
||||
@Test public void testGenericsAsArgumentDefinition() throws Exception {
|
||||
String action = "$foo.get(\"ick\");";
|
||||
}
|
||||
@Test public void testGenericsAsArgumentDefinition2() throws Exception {
|
||||
String action = "$foo.get(\"ick\"); x=3;";
|
||||
}
|
||||
@Test public void testGenericsAsReturnValue() throws Exception {
|
||||
}
|
||||
@Test public void testComplicatedArgParsingWithTranslation() throws Exception {
|
||||
String action = "x, $A.text+\"3242\", (*$A).foo(21,33), 3.2+1, '\\n', "+
|
||||
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
}
|
||||
@Test public void testRefToReturnValueBeforeRefToPredefinedAttr() throws Exception {
|
||||
String action = "$x.foo";
|
||||
}
|
||||
@Test public void testRuleLabelBeforeRefToPredefinedAttr() throws Exception {
|
||||
String action = "$x.text";
|
||||
}
|
||||
@Test public void testInvalidArguments() throws Exception {
|
||||
String action = "$x";
|
||||
}
|
||||
@Test public void testReturnValue() throws Exception {
|
||||
String action = "$x.i";
|
||||
}
|
||||
@Test public void testReturnValueWithNumber() throws Exception {
|
||||
String action = "$x.i1";
|
||||
}
|
||||
@Test public void testReturnValues() throws Exception {
|
||||
String action = "$i; $i.x; $u; $u.x";
|
||||
String action = "int \\$n; \"\\$in string\\$\"";
|
||||
String expected = "int \\$n; \"\\$in string\\$\"";
|
||||
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 testComplicatedArgParsing() throws Exception {
|
||||
String action = "x, (*a).foo(21,33), 3.2+1, '\\n', "+
|
||||
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
String expected = "x, (*a).foo(21,33), 3.2+1, '\\n', "+
|
||||
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
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 testComplicatedArgParsingWithTranslation() throws Exception {
|
||||
String action = "x, $ID.text+\"3242\", (*$ID).foo(21,33), 3.2+1, '\\n', "+
|
||||
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
String expected = "x, (_rID!=null?_rID.getText():null)+\"3242\"," +
|
||||
" (*_tID).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testArguments() throws Exception {
|
||||
String action = "$x; $a.x";
|
||||
String expected = "_ctx.x; _ctx.x";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testReturnValue() throws Exception {
|
||||
String action = "$x; $a.x";
|
||||
String expected = "_ctx.x; _ctx.x";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testReturnValueWithNumber() throws Exception {
|
||||
String action = "$a.x1";
|
||||
String expected = "_ctx.x1";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testReturnValuesCurrentRule() throws Exception {
|
||||
String action = "$y; $a.y;";
|
||||
String expected = "_ctx.y; _ctx.y;";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testReturnValues() throws Exception {
|
||||
String action = "$lab.e; $b.e;";
|
||||
String expected = "lab.e; _rb.e;";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testReturnWithMultipleRuleRefs() throws Exception {
|
||||
String action1 = "$obj = $rule2.obj;";
|
||||
String action2 = "$obj = $rule3.obj;";
|
||||
String expecting1 = "obj = rule21;";
|
||||
String expecting2 = "obj = rule32;";
|
||||
String action = action1;
|
||||
String action = "$c.x; $c.y;";
|
||||
String expected = "_rc.x; _rc.y;";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
@Test public void testInvalidReturnValues() throws Exception {
|
||||
String action = "$x";
|
||||
|
||||
@Test public void testTokenRefs() throws Exception {
|
||||
String action = "$id; $ID; $id.text; $id.getText(); $id.line;";
|
||||
String expected = "id; _tID; (id!=null?id.getText():null); id.getText(); (id!=null?id.getLine():0);";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
@Test public void testTokenLabels() throws Exception {
|
||||
String action = "$id; $f; $id.text; $id.getText(); $id.dork " +
|
||||
"$id.type; $id.line; $id.pos; " +
|
||||
"$id.channel; $id.index;";
|
||||
}
|
||||
@Test public void testRuleLabels() throws Exception {
|
||||
String action = "$r.x; $r.start;\n $r.stop;\n $r.tree; $a.x; $a.stop;";
|
||||
}
|
||||
@Test public void testAmbiguRuleRef() throws Exception {
|
||||
}
|
||||
@Test public void testRuleLabelsWithSpecialToken() throws Exception {
|
||||
String action = "$r.x; $r.start; $r.stop; $r.tree; $a.x; $a.stop;";
|
||||
}
|
||||
@Test public void testForwardRefRuleLabels() throws Exception {
|
||||
String action = "$r.x; $r.start; $r.stop; $r.tree; $a.x; $a.tree;";
|
||||
}
|
||||
@Test public void testInvalidRuleLabelAccessesParameter() throws Exception {
|
||||
String action = "$r.z";
|
||||
}
|
||||
@Test public void testInvalidRuleLabelAccessesScopeAttribute() throws Exception {
|
||||
String action = "$r.n";
|
||||
}
|
||||
@Test public void testInvalidRuleAttribute() throws Exception {
|
||||
String action = "$r.blort";
|
||||
}
|
||||
@Test public void testMissingRuleAttribute() throws Exception {
|
||||
String action = "$r";
|
||||
}
|
||||
@Test public void testMissingUnlabeledRuleAttribute() throws Exception {
|
||||
String action = "$a";
|
||||
}
|
||||
@Test public void testNonDynamicAttributeOutsideRule() throws Exception {
|
||||
String action = "public void foo() { $x; }";
|
||||
}
|
||||
@Test public void testNonDynamicAttributeOutsideRule2() throws Exception {
|
||||
String action = "public void foo() { $x.y; }";
|
||||
|
||||
@Test public void testRuleRefs() throws Exception {
|
||||
String action = "$lab.start; $c.tree;";
|
||||
String expected = "(lab!=null?(()lab.start):null); (_rc!=null?(()_rc.tree):null);";
|
||||
testActions(attributeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testBasicGlobalScope() throws Exception {
|
||||
String action = "$Symbols::names.add($id.text);";
|
||||
}
|
||||
@Test public void testUnknownGlobalScope() throws Exception {
|
||||
String action = "$Symbols::names.add($id.text);";
|
||||
}
|
||||
@Test public void testIndexedGlobalScope() throws Exception {
|
||||
String action = "$Symbols[-1]::names.add($id.text);";
|
||||
String action = "$S::i";
|
||||
String expected = "((S)S_stack.peek()).i";
|
||||
testActions(scopeTemplate, "members", action, expected);
|
||||
}
|
||||
|
||||
@Test public void test0IndexedGlobalScope() throws Exception {
|
||||
String action = "$Symbols[0]::names.add($id.text);";
|
||||
String action = "$S[0]::i";
|
||||
String expected = "(S_stack.elementAt(0)).i";
|
||||
testActions(scopeTemplate, "members", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testAbsoluteIndexedGlobalScope() throws Exception {
|
||||
String action = "$Symbols[3]::names.add($id.text);";
|
||||
}
|
||||
@Test public void testScopeAndAttributeWithUnderscore() throws Exception {
|
||||
String action = "$foo_bar::a_b;";
|
||||
}
|
||||
@Test public void testSharedGlobalScope() throws Exception {
|
||||
String action = "$Symbols::x;";
|
||||
}
|
||||
@Test public void testGlobalScopeOutsideRule() throws Exception {
|
||||
String action = "public void foo() {$Symbols::names.add('foo');}";
|
||||
}
|
||||
@Test public void testRuleScopeOutsideRule() throws Exception {
|
||||
String action = "public void foo() {$a::name;}";
|
||||
String action = "$S[3]::i";
|
||||
String expected = "(S_stack.elementAt(3)).i";
|
||||
testActions(scopeTemplate, "members", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testNegIndexedGlobalScope() throws Exception {
|
||||
String action = "$S[-1]::i";
|
||||
String expected = "(S_stack.elementAt(S_stack.size()-1-1)).i";
|
||||
testActions(scopeTemplate, "members", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testNegIndexedGlobalScope2() throws Exception {
|
||||
String action = "$S[-$S::i]::i";
|
||||
String expected = "(S_stack.elementAt(S_stack.size()-(S_stack.peek()).i-1)).i";
|
||||
testActions(scopeTemplate, "members", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testBasicRuleScope() throws Exception {
|
||||
String action = "$a::n;";
|
||||
String action = "$a::z";
|
||||
String expected = "(a_scope_stack.peek()).z";
|
||||
testActions(scopeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testBasicGlobalScopeInRule() throws Exception {
|
||||
String action = "$S::i";
|
||||
String expected = "(S_stack.peek()).i";
|
||||
testActions(scopeTemplate, "inline", action, expected);
|
||||
}
|
||||
|
||||
@Test public void testUnqualifiedRuleScopeAccessInsideRule() throws Exception {
|
||||
String action = "$n;";
|
||||
}
|
||||
|
@ -250,14 +237,6 @@ public class TestActionTranslation extends BaseTest {
|
|||
@Test public void testRuleLabelFromMultipleAlts() throws Exception {
|
||||
String action = "$b.text;"; // must be qualified
|
||||
}
|
||||
@Test public void testUnknownDynamicAttribute() throws Exception {
|
||||
String action = "$a::x";
|
||||
}
|
||||
|
||||
@Test public void testUnknownGlobalDynamicAttribute() throws Exception {
|
||||
String action = "$Symbols::x";
|
||||
}
|
||||
|
||||
@Test public void testUnqualifiedRuleScopeAttribute() throws Exception {
|
||||
String action = "$n;"; // must be qualified
|
||||
}
|
||||
|
@ -433,6 +412,29 @@ public class TestActionTranslation extends BaseTest {
|
|||
String action = "int x = $b::n;";
|
||||
}
|
||||
|
||||
@Test public void testBracketArgParsing() throws Exception {
|
||||
}
|
||||
|
||||
@Test public void testStringArgParsing() throws Exception {
|
||||
String action = "34, '{', \"it's<\", '\"', \"\\\"\", 19";
|
||||
}
|
||||
@Test public void testComplicatedSingleArgParsing() throws Exception {
|
||||
String action = "(*a).foo(21,33,\",\")";
|
||||
}
|
||||
@Test public void testArgWithLT() throws Exception {
|
||||
String action = "34<50";
|
||||
}
|
||||
@Test public void testGenericsAsArgumentDefinition() throws Exception {
|
||||
String action = "$foo.get(\"ick\");";
|
||||
}
|
||||
@Test public void testGenericsAsArgumentDefinition2() throws Exception {
|
||||
String action = "$foo.get(\"ick\"); x=3;";
|
||||
}
|
||||
@Test public void testGenericsAsReturnValue() throws Exception {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testActions(String template, String actionName, String action, String expected) {
|
||||
ST st = new ST(template);
|
||||
st.add(actionName, action);
|
||||
|
@ -451,7 +453,7 @@ public class TestActionTranslation extends BaseTest {
|
|||
CodeGenerator gen = new CodeGenerator(g);
|
||||
ST outputFileST = gen.generate();
|
||||
String output = outputFileST.render();
|
||||
System.out.println(output);
|
||||
//System.out.println(output);
|
||||
String b = "#" + actionName + "#";
|
||||
int start = output.indexOf(b);
|
||||
String e = "#end-" + actionName + "#";
|
||||
|
|
|
@ -62,11 +62,12 @@ public class TestAttributeChecks extends BaseTest {
|
|||
"$a.q", "error(31): A.g:4:10: unknown attribute q for rule a in $a.q\n",
|
||||
};
|
||||
|
||||
String[] inlineChecks = {
|
||||
String[] inlineChecks = {
|
||||
"$text", "",
|
||||
"$start", "",
|
||||
"$x = $y", "",
|
||||
"$y = $x", "",
|
||||
"$a.x = $a.y", "",
|
||||
"$lab.e", "",
|
||||
"$lab.text", "",
|
||||
"$b.e", "",
|
||||
|
@ -76,24 +77,26 @@ public class TestAttributeChecks extends BaseTest {
|
|||
"$id", "",
|
||||
"$id.text", "",
|
||||
"$ids", "",
|
||||
};
|
||||
|
||||
String[] bad_inlineChecks = {
|
||||
"$a", "error(33): A.g:6:4: missing attribute access on rule reference a in $a\n",
|
||||
"$b", "error(33): A.g:6:4: missing attribute access on rule reference b in $b\n",
|
||||
"$lab", "error(33): A.g:6:4: missing attribute access on rule reference lab in $lab\n",
|
||||
"$c", "error(33): A.g:6:4: missing attribute access on rule reference c in $c\n", // no scope
|
||||
"$q", "error(29): A.g:6:4: unknown attribute reference q in $q\n",
|
||||
"$q.y", "error(29): A.g:6:4: unknown attribute reference q in $q.y\n",
|
||||
"$q = 3", "error(29): A.g:6:4: unknown attribute reference q in $q\n",
|
||||
"$q = 3;", "error(29): A.g:6:4: unknown attribute reference q in $q = 3;\n",
|
||||
"$q.y = 3;", "error(29): A.g:6:4: unknown attribute reference q in $q.y = 3;\n",
|
||||
"$q = $blort;", "error(29): A.g:6:4: unknown attribute reference q in $q = $blort;\n" +
|
||||
"$q.y", "error(29): A.g:6:4: unknown attribute reference q in $q.y\n",
|
||||
"$q = 3", "error(29): A.g:6:4: unknown attribute reference q in $q\n",
|
||||
"$q = 3;", "error(29): A.g:6:4: unknown attribute reference q in $q = 3;\n",
|
||||
"$q.y = 3;", "error(29): A.g:6:4: unknown attribute reference q in $q.y = 3;\n",
|
||||
"$q = $blort;", "error(29): A.g:6:4: unknown attribute reference q in $q = $blort;\n" +
|
||||
"error(29): A.g:6:9: unknown attribute reference blort in $blort\n",
|
||||
"$a.ick", "error(31): A.g:6:6: unknown attribute ick for rule a in $a.ick\n",
|
||||
"$a.ick = 3;", "error(31): A.g:6:6: unknown attribute ick for rule a in $a.ick = 3;\n",
|
||||
"$b.d", "error(30): A.g:6:6: cannot access rule d's parameter: $b.d\n", // can't see rule ref's arg
|
||||
"$a.ick", "error(31): A.g:6:6: unknown attribute ick for rule a in $a.ick\n",
|
||||
"$a.ick = 3;", "error(31): A.g:6:6: unknown attribute ick for rule a in $a.ick = 3;\n",
|
||||
"$b.d", "error(30): A.g:6:6: cannot access rule d's parameter: $b.d\n", // can't see rule ref's arg
|
||||
"$d.text", "error(29): A.g:6:4: unknown attribute reference d in $d.text\n", // valid rule, but no ref
|
||||
"$lab.d", "error(30): A.g:6:8: cannot access rule d's parameter: $lab.d\n",
|
||||
};
|
||||
};
|
||||
|
||||
String[] finallyChecks = {
|
||||
"$text", "",
|
||||
|
@ -213,6 +216,10 @@ public class TestAttributeChecks extends BaseTest {
|
|||
testActions("inline", inlineChecks, attributeTemplate);
|
||||
}
|
||||
|
||||
@Test public void testBadInlineActions() throws RecognitionException {
|
||||
testActions("inline", bad_inlineChecks, attributeTemplate);
|
||||
}
|
||||
|
||||
@Test public void testFinallyActions() throws RecognitionException {
|
||||
testActions("finally", finallyChecks, attributeTemplate);
|
||||
}
|
||||
|
@ -242,6 +249,24 @@ public class TestAttributeChecks extends BaseTest {
|
|||
testErrors(new String[] {grammar, expected}, false);
|
||||
}
|
||||
|
||||
@Test public void testNonDynamicAttributeOutsideRule() throws Exception {
|
||||
String action = "public void foo() { $x; }";
|
||||
}
|
||||
@Test public void testNonDynamicAttributeOutsideRule2() throws Exception {
|
||||
String action = "public void foo() { $x.y; }";
|
||||
}
|
||||
@Test public void testUnknownGlobalScope() throws Exception {
|
||||
String action = "$Symbols::names.add($id.text);";
|
||||
}
|
||||
@Test public void testUnknownDynamicAttribute() throws Exception {
|
||||
String action = "$a::x";
|
||||
}
|
||||
|
||||
@Test public void testUnknownGlobalDynamicAttribute() throws Exception {
|
||||
String action = "$Symbols::x";
|
||||
}
|
||||
|
||||
|
||||
public void testActions(String location, String[] pairs, String template) {
|
||||
for (int i = 0; i < pairs.length; i+=2) {
|
||||
String action = pairs[i];
|
||||
|
|
Loading…
Reference in New Issue