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