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 
7 package org.antlr.v4.test.tool;
8 
9 import org.antlr.v4.tool.Grammar;
10 import org.junit.Before;
11 import org.junit.Test;
12 
13 /** */
14 @SuppressWarnings("unused")
15 public class TestActionTranslation extends BaseJavaToolTest {
16 	@Before
17 	@Override
testSetUp()18 	public void testSetUp() throws Exception {
19 		super.testSetUp();
20 	}
21 
22 	String attributeTemplate =
23 		"attributeTemplate(members,init,inline,finally,inline2) ::= <<\n" +
24 		"parser grammar A;\n"+
25 		"@members {#members#<members>#end-members#}\n" +
26 		"a[int x, int x1] returns [int y]\n" +
27 		"@init {#init#<init>#end-init#}\n" +
28 		"    :   id=ID ids+=ID lab=b[34] c d {\n" +
29 		"		 #inline#<inline>#end-inline#\n" +
30 		"		 }\n" +
31 		"		 c\n" +
32 		"    ;\n" +
33 		"    finally {#finally#<finally>#end-finally#}\n" +
34 		"b[int d] returns [int e]\n" +
35 		"    :   {#inline2#<inline2>#end-inline2#}\n" +
36 		"    ;\n" +
37 		"c returns [int x, int y] : ;\n" +
38 		"d	 :   ;\n" +
39 		">>";
40 
testEscapedLessThanInAction()41     @Test public void testEscapedLessThanInAction() throws Exception {
42         String action = "i<3; '<xmltag>'";
43 		String expected = "i<3; '<xmltag>'";
44 		testActions(attributeTemplate, "members", action, expected);
45 		testActions(attributeTemplate, "init", action, expected);
46 		testActions(attributeTemplate, "inline", action, expected);
47 		testActions(attributeTemplate, "finally", action, expected);
48 		testActions(attributeTemplate, "inline2", action, expected);
49     }
50 
testEscaped$InAction()51     @Test public void testEscaped$InAction() throws Exception {
52 		String action = "int \\$n; \"\\$in string\\$\"";
53 		String expected = "int $n; \"$in string$\"";
54 		testActions(attributeTemplate, "members", action, expected);
55 		testActions(attributeTemplate, "init", action, expected);
56 		testActions(attributeTemplate, "inline", action, expected);
57 		testActions(attributeTemplate, "finally", action, expected);
58 		testActions(attributeTemplate, "inline2", action, expected);
59     }
60 
61 	/**
62 	 * Regression test for "in antlr v4 lexer, $ translation issue in action".
63 	 * https://github.com/antlr/antlr4/issues/176
64 	 */
testUnescaped$InAction()65 	@Test public void testUnescaped$InAction() throws Exception {
66 		String action = "\\$string$";
67 		String expected = "$string$";
68 		testActions(attributeTemplate, "members", action, expected);
69 		testActions(attributeTemplate, "init", action, expected);
70 		testActions(attributeTemplate, "inline", action, expected);
71 		testActions(attributeTemplate, "finally", action, expected);
72 		testActions(attributeTemplate, "inline2", action, expected);
73 	}
74 
testEscapedSlash()75 	@Test public void testEscapedSlash() throws Exception {
76 		String action   = "x = '\\n';";  // x = '\n'; -> x = '\n';
77 		String expected = "x = '\\n';";
78 		testActions(attributeTemplate, "members", action, expected);
79 		testActions(attributeTemplate, "init", action, expected);
80 		testActions(attributeTemplate, "inline", action, expected);
81 		testActions(attributeTemplate, "finally", action, expected);
82 		testActions(attributeTemplate, "inline2", action, expected);
83 	}
84 
testComplicatedArgParsing()85 	@Test public void testComplicatedArgParsing() throws Exception {
86 		String action = "x, (*a).foo(21,33), 3.2+1, '\\n', "+
87 						"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
88 		String expected = "x, (*a).foo(21,33), 3.2+1, '\\n', "+
89 						"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
90 		testActions(attributeTemplate, "members", action, expected);
91 		testActions(attributeTemplate, "init", action, expected);
92 		testActions(attributeTemplate, "inline", action, expected);
93 		testActions(attributeTemplate, "finally", action, expected);
94 		testActions(attributeTemplate, "inline2", action, expected);
95 	}
96 
testComplicatedArgParsingWithTranslation()97 	@Test public void testComplicatedArgParsingWithTranslation() throws Exception {
98 		String action = "x, $ID.text+\"3242\", (*$ID).foo(21,33), 3.2+1, '\\n', "+
99 						"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
100 		String expected =
101 			"x, (((AContext)_localctx).ID!=null?((AContext)_localctx).ID.getText():null)+\"3242\", " +
102 			"(*((AContext)_localctx).ID).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
103 		testActions(attributeTemplate, "inline", action, expected);
104 	}
105 
testArguments()106 	@Test public void testArguments() throws Exception {
107 		String action = "$x; $ctx.x";
108 		String expected = "_localctx.x; _localctx.x";
109 		testActions(attributeTemplate, "inline", action, expected);
110 	}
111 
testReturnValue()112 	@Test public void testReturnValue() throws Exception {
113 		String action = "$y; $ctx.y";
114 		String expected = "_localctx.y; _localctx.y";
115 		testActions(attributeTemplate, "inline", action, expected);
116 	}
117 
testReturnValueWithNumber()118 	@Test public void testReturnValueWithNumber() throws Exception {
119 		String action = "$ctx.x1";
120 		String expected = "_localctx.x1";
121 		testActions(attributeTemplate, "inline", action, expected);
122 	}
123 
testReturnValuesCurrentRule()124 	@Test public void testReturnValuesCurrentRule() throws Exception {
125 		String action = "$y; $ctx.y;";
126 		String expected = "_localctx.y; _localctx.y;";
127 		testActions(attributeTemplate, "inline", action, expected);
128 	}
129 
testReturnValues()130 	@Test public void testReturnValues() throws Exception {
131 		String action = "$lab.e; $b.e; $y.e = \"\";";
132 		String expected = "((AContext)_localctx).lab.e; ((AContext)_localctx).b.e; _localctx.y.e = \"\";";
133 		testActions(attributeTemplate, "inline", action, expected);
134 	}
135 
testReturnWithMultipleRuleRefs()136     @Test public void testReturnWithMultipleRuleRefs() throws Exception {
137 		String action = "$c.x; $c.y;";
138 		String expected = "((AContext)_localctx).c.x; ((AContext)_localctx).c.y;";
139 		testActions(attributeTemplate, "inline", action, expected);
140     }
141 
testTokenRefs()142     @Test public void testTokenRefs() throws Exception {
143 		String action = "$id; $ID; $id.text; $id.getText(); $id.line;";
144 		String expected = "((AContext)_localctx).id; ((AContext)_localctx).ID; (((AContext)_localctx).id!=null?((AContext)_localctx).id.getText():null); ((AContext)_localctx).id.getText(); (((AContext)_localctx).id!=null?((AContext)_localctx).id.getLine():0);";
145 		testActions(attributeTemplate, "inline", action, expected);
146     }
147 
testRuleRefs()148     @Test public void testRuleRefs() throws Exception {
149         String action = "$lab.start; $c.text;";
150 		String expected = "(((AContext)_localctx).lab!=null?(((AContext)_localctx).lab.start):null); (((AContext)_localctx).c!=null?_input.getText(((AContext)_localctx).c.start,((AContext)_localctx).c.stop):null);";
151 		testActions(attributeTemplate, "inline", action, expected);
152     }
153 
154     /** Added in response to https://github.com/antlr/antlr4/issues/1211 */
testUnknownAttr()155 	@Test public void testUnknownAttr() throws Exception {
156 		String action = "$qqq.text";
157 		String expected = ""; // was causing an exception
158 		testActions(attributeTemplate, "inline", action, expected);
159 	}
160 
161 	/**
162 	 * Regression test for issue #1295
163      * $e.v yields incorrect value 0 in "e returns [int v] : '1' {$v = 1;} | '(' e ')' {$v = $e.v;} ;"
164 	 * https://github.com/antlr/antlr4/issues/1295
165 	 */
testRuleRefsRecursive()166 	@Test public void testRuleRefsRecursive() throws Exception {
167         String recursiveTemplate =
168             "recursiveTemplate(inline) ::= <<\n" +
169             "parser grammar A;\n"+
170             "e returns [int v]\n" +
171             "    :   INT {$v = $INT.int;}\n" +
172             "    |   '(' e ')' {\n" +
173             "		 #inline#<inline>#end-inline#\n" +
174             "		 }\n" +
175             "    ;\n" +
176             ">>";
177         String leftRecursiveTemplate =
178             "recursiveTemplate(inline) ::= <<\n" +
179             "parser grammar A;\n"+
180             "e returns [int v]\n" +
181             "    :   a=e op=('*'|'/') b=e  {$v = eval($a.v, $op.type, $b.v);}\n" +
182             "    |   INT {$v = $INT.int;}\n" +
183             "    |   '(' e ')' {\n" +
184             "		 #inline#<inline>#end-inline#\n" +
185             "		 }\n" +
186             "    ;\n" +
187             ">>";
188         // ref to value returned from recursive call to rule
189         String action = "$v = $e.v;";
190 		String expected = "((EContext)_localctx).v =  ((EContext)_localctx).e.v;";
191 		testActions(recursiveTemplate, "inline", action, expected);
192 		testActions(leftRecursiveTemplate, "inline", action, expected);
193         // ref to predefined attribute obtained from recursive call to rule
194         action = "$v = $e.text.length();";
195         expected = "((EContext)_localctx).v =  (((EContext)_localctx).e!=null?_input.getText(((EContext)_localctx).e.start,((EContext)_localctx).e.stop):null).length();";
196 		testActions(recursiveTemplate, "inline", action, expected);
197 		testActions(leftRecursiveTemplate, "inline", action, expected);
198 	}
199 
testRefToTextAttributeForCurrentRule()200 	@Test public void testRefToTextAttributeForCurrentRule() throws Exception {
201         String action = "$ctx.text; $text";
202 
203 		// this is the expected translation for all cases
204 		String expected =
205 			"_localctx.text; _input.getText(_localctx.start, _input.LT(-1))";
206 
207 		testActions(attributeTemplate, "init", action, expected);
208 		testActions(attributeTemplate, "inline", action, expected);
209 		testActions(attributeTemplate, "finally", action, expected);
210     }
211 
testEmptyActions()212     @Test public void testEmptyActions() throws Exception {
213 	    String gS =
214 	   		"grammar A;\n"+
215 	   		"a[] : 'a' ;\n" +
216 	   		"c : a[] c[] ;\n";
217 	    Grammar g = new Grammar(gS);
218     }
219 
220 
221 /*
222     @Test public void testSimplePlusEqualLabel() throws Exception {
223         String action = "$ids.size();"; // must be qualified
224     }
225     @Test public void testPlusEqualStringLabel() throws Exception {
226         String action = "$ids.size();"; // must be qualified
227     }
228     @Test public void testPlusEqualSetLabel() throws Exception {
229         String action = "$ids.size();"; // must be qualified
230     }
231     @Test public void testPlusEqualWildcardLabel() throws Exception {
232         String action = "$ids.size();"; // must be qualified
233     }
234     @Test public void testImplicitTokenLabel() throws Exception {
235         String action = "$ID; $ID.text; $ID.getText()";
236     }
237 
238     @Test public void testImplicitRuleLabel() throws Exception {
239         String action = "$r.start;";
240     }
241 
242     @Test public void testReuseExistingLabelWithImplicitRuleLabel() throws Exception {
243         String action = "$r.start;";
244     }
245 
246     @Test public void testReuseExistingListLabelWithImplicitRuleLabel() throws Exception {
247         String action = "$r.start;";
248     }
249 
250     @Test public void testReuseExistingLabelWithImplicitTokenLabel() throws Exception {
251         String action = "$ID.text;";
252     }
253 
254     @Test public void testReuseExistingListLabelWithImplicitTokenLabel() throws Exception {
255         String action = "$ID.text;";
256     }
257 
258     @Test public void testRuleLabelWithoutOutputOption() throws Exception {
259     }
260     @Test public void testMissingArgs() throws Exception {
261     }
262     @Test public void testArgsWhenNoneDefined() throws Exception {
263     }
264     @Test public void testReturnInitValue() throws Exception {
265     }
266     @Test public void testMultipleReturnInitValue() throws Exception {
267     }
268     @Test public void testCStyleReturnInitValue() throws Exception {
269     }
270     @Test public void testArgsWithInitValues() throws Exception {
271     }
272     @Test public void testArgsOnToken() throws Exception {
273     }
274     @Test public void testArgsOnTokenInLexer() throws Exception {
275     }
276     @Test public void testLabelOnRuleRefInLexer() throws Exception {
277         String action = "$i.text";
278     }
279 
280     @Test public void testRefToRuleRefInLexer() throws Exception {
281         String action = "$ID.text";
282     }
283 
284     @Test public void testRefToRuleRefInLexerNoAttribute() throws Exception {
285         String action = "$ID";
286     }
287 
288     @Test public void testCharLabelInLexer() throws Exception {
289     }
290     @Test public void testCharListLabelInLexer() throws Exception {
291     }
292     @Test public void testWildcardCharLabelInLexer() throws Exception {
293     }
294     @Test public void testWildcardCharListLabelInLexer() throws Exception {
295     }
296     @Test public void testMissingArgsInLexer() throws Exception {
297     }
298     @Test public void testLexerRulePropertyRefs() throws Exception {
299         String action = "$text $type $line $pos $channel $index $start $stop";
300     }
301 
302     @Test public void testLexerLabelRefs() throws Exception {
303         String action = "$a $b.text $c $d.text";
304     }
305 
306     @Test public void testSettingLexerRulePropertyRefs() throws Exception {
307         String action = "$text $type=1 $line=1 $pos=1 $channel=1 $index";
308     }
309 
310     @Test public void testArgsOnTokenInLexerRuleOfCombined() throws Exception {
311     }
312     @Test public void testMissingArgsOnTokenInLexerRuleOfCombined() throws Exception {
313     }
314     @Test public void testTokenLabelTreeProperty() throws Exception {
315         String action = "$id.tree;";
316     }
317 
318     @Test public void testTokenRefTreeProperty() throws Exception {
319         String action = "$ID.tree;";
320     }
321 
322     @Test public void testAmbiguousTokenRef() throws Exception {
323         String action = "$ID;";
324     }
325 
326     @Test public void testAmbiguousTokenRefWithProp() throws Exception {
327         String action = "$ID.text;";
328     }
329 
330     @Test public void testRuleRefWithDynamicScope() throws Exception {
331         String action = "$field::x = $field.st;";
332     }
333 
334     @Test public void testAssignToOwnRulenameAttr() throws Exception {
335         String action = "$rule.tree = null;";
336     }
337 
338     @Test public void testAssignToOwnParamAttr() throws Exception {
339         String action = "$rule.i = 42; $i = 23;";
340     }
341 
342     @Test public void testIllegalAssignToOwnRulenameAttr() throws Exception {
343         String action = "$rule.stop = 0;";
344     }
345 
346     @Test public void testIllegalAssignToLocalAttr() throws Exception {
347         String action = "$tree = null; $st = null; $start = 0; $stop = 0; $text = 0;";
348     }
349 
350     @Test public void testIllegalAssignRuleRefAttr() throws Exception {
351         String action = "$other.tree = null;";
352     }
353 
354     @Test public void testIllegalAssignTokenRefAttr() throws Exception {
355         String action = "$ID.text = \"test\";";
356     }
357 
358     @Test public void testAssignToTreeNodeAttribute() throws Exception {
359         String action = "$tree.scope = localScope;";
360     }
361 
362     @Test public void testDoNotTranslateAttributeCompare() throws Exception {
363         String action = "$a.line == $b.line";
364     }
365 
366     @Test public void testDoNotTranslateScopeAttributeCompare() throws Exception {
367         String action = "if ($rule::foo == \"foo\" || 1) { System.out.println(\"ouch\"); }";
368     }
369 
370     @Test public void testTreeRuleStopAttributeIsInvalid() throws Exception {
371         String action = "$r.x; $r.start; $r.stop";
372     }
373 
374     @Test public void testRefToTextAttributeForCurrentTreeRule() throws Exception {
375         String action = "$text";
376     }
377 
378     @Test public void testTypeOfGuardedAttributeRefIsCorrect() throws Exception {
379         String action = "int x = $b::n;";
380     }
381 
382 	@Test public void testBracketArgParsing() throws Exception {
383 	}
384 
385 	@Test public void testStringArgParsing() throws Exception {
386 		String action = "34, '{', \"it's<\", '\"', \"\\\"\", 19";
387 	}
388 	@Test public void testComplicatedSingleArgParsing() throws Exception {
389 		String action = "(*a).foo(21,33,\",\")";
390 	}
391 	@Test public void testArgWithLT() throws Exception {
392 		String action = "34<50";
393 	}
394 	@Test public void testGenericsAsArgumentDefinition() throws Exception {
395 		String action = "$foo.get(\"ick\");";
396 	}
397 	@Test public void testGenericsAsArgumentDefinition2() throws Exception {
398 		String action = "$foo.get(\"ick\"); x=3;";
399 	}
400 	@Test public void testGenericsAsReturnValue() throws Exception {
401 	}
402 */
403 	// TODO: nonlocal $rule::x
404 }
405