diff --git a/app/aem/core/src/main/antlr/ApmLang.g4 b/app/aem/core/src/main/antlr/ApmLang.g4 index 9b7c6df5..38e5ef09 100644 --- a/app/aem/core/src/main/antlr/ApmLang.g4 +++ b/app/aem/core/src/main/antlr/ApmLang.g4 @@ -33,7 +33,7 @@ name ; privilegeName - : IDENTIFIER ':' IDENTIFIER + : IDENTIFIER COLON IDENTIFIER ; path @@ -42,7 +42,7 @@ path ; array - : ARRAY_BEGIN arrayValue (',' arrayValue)* ARRAY_END + : ARRAY_BEGIN (arrayValue (COMMA arrayValue)*)? ARRAY_END ; arrayValue @@ -53,11 +53,11 @@ arrayValue ; structure - : STRUCTURE_BEGIN structureEntry (',' structureEntry)* STRUCTURE_END + : STRUCTURE_BEGIN (structureEntry (COMMA structureEntry)*)? STRUCTURE_END ; structureEntry - : structureKey ':' structureValue + : structureKey COLON structureValue ; structureKey @@ -176,6 +176,12 @@ STRUCTURE_BEGIN STRUCTURE_END : '}' ; +COMMA + : ',' + ; +COLON + : ':' + ; BLOCK_BEGIN : 'begin' | 'BEGIN' diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ScriptRunner.java b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ScriptRunner.java index f74d1eb9..0232050c 100644 --- a/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ScriptRunner.java +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ScriptRunner.java @@ -145,6 +145,10 @@ public Status visitRequireVariable(RequireVariableContext ctx) { public Status visitForEach(ForEachContext ctx) { List> values = readValues(ctx); ListIterator> iterator = values.listIterator(); + if (!iterator.hasNext() && shouldVisitNextChild()) { + String key = ctx.IDENTIFIER().toString(); + progress(ctx, Status.SKIPPED, "for-each", String.format("%s is always empty", key)); + } while (iterator.hasNext() && shouldVisitNextChild()) { try { int index = iterator.nextIndex(); diff --git a/app/aem/core/src/test/groovy/com/cognifide/apm/core/grammar/ScriptRunnerTest.groovy b/app/aem/core/src/test/groovy/com/cognifide/apm/core/grammar/ScriptRunnerTest.groovy index b9414da6..e7ef01b7 100644 --- a/app/aem/core/src/test/groovy/com/cognifide/apm/core/grammar/ScriptRunnerTest.groovy +++ b/app/aem/core/src/test/groovy/com/cognifide/apm/core/grammar/ScriptRunnerTest.groovy @@ -92,7 +92,9 @@ class ScriptRunnerTest extends Specification { "Executing command SHOW \"t\"", "Executing command SHOW [3, \"ab\"]", "Executing command SHOW [\"a\", \"b\", \"c\", \"d\", 1, 2]", - "Executing command SHOW [\n\t[\"a\", \"b\"],\n\t[\"c\", \"d\"]\n]"] + "Executing command SHOW [\n\t[\"a\", \"b\"],\n\t[\"c\", \"d\"]\n]", + "Executing command SHOW []", + "Executing command SHOW {}"] } def "run macro"() { diff --git a/app/aem/core/src/test/resources/define.apm b/app/aem/core/src/test/resources/define.apm index 4074e82e..5b4ecab9 100644 --- a/app/aem/core/src/test/resources/define.apm +++ b/app/aem/core/src/test/resources/define.apm @@ -43,6 +43,8 @@ DEFINE tab3 [['a', 'b'], ['c', 'd']] DEFINE obj {x:'a', y:1, z:['c', 1], 't':'t'} DEFINE tabEnum [a, b, "c", "d", 1, 2] DEFINE tab4 [1 + 2, "a" + "b"] +DEFINE emptyList [] +DEFINE emptyMap {} SHOW $a SHOW $b SHOW $tab1 @@ -60,3 +62,5 @@ SHOW ${obj[t]} SHOW $tab4 SHOW $tabEnum SHOW $tab3 +SHOW $emptyList +SHOW $emptyMap