@@ -102,10 +102,12 @@ private Statement assignmentStatement() {
102102 consume (TokenType .EQ );
103103 return new AssignmentStatement (variable , expression ());
104104 }
105- if (lookMatch (0 , TokenType .WORD ) && lookMatch (1 , TokenType .LBRACKET )) {
106- final ArrayAccessExpression array = element ();
105+
106+ final Expression qualifiedNameExpr = qualifiedName ();
107+ if (lookMatch (0 , TokenType .EQ ) && (qualifiedNameExpr instanceof ContainerAccessExpression )) {
107108 consume (TokenType .EQ );
108- return new ArrayAssignmentStatement (array , expression ());
109+ final ContainerAccessExpression containerExpr = (ContainerAccessExpression ) qualifiedNameExpr ;
110+ return new ContainerAssignmentStatement (containerExpr , expression ());
109111 }
110112 throw new ParseException ("Unknown statement: " + get (0 ));
111113 }
@@ -249,31 +251,6 @@ private Expression map() {
249251 return new MapExpression (elements );
250252 }
251253
252- private ArrayAccessExpression element () {
253- // array[e1][e2]...[eN]
254- final String variable = consume (TokenType .WORD ).getText ();
255- final List <Expression > indices = new ArrayList <>();
256- do {
257- consume (TokenType .LBRACKET );
258- indices .add (expression ());
259- consume (TokenType .RBRACKET );
260- } while (lookMatch (0 , TokenType .LBRACKET ));
261- return new ArrayAccessExpression (variable , indices );
262- }
263-
264- private ArrayAccessExpression object () {
265- // object.field1.field2
266- // Syntaxic sugar for object["field1"]["field2"]
267- final String variable = consume (TokenType .WORD ).getText ();
268- final List <Expression > indices = new ArrayList <>();
269- while (match (TokenType .DOT )) {
270- final String fieldName = consume (TokenType .WORD ).getText ();
271- final Expression key = new ValueExpression (fieldName );
272- indices .add (key );
273- }
274- return new ArrayAccessExpression (variable , indices );
275- }
276-
277254 private MatchExpression match () {
278255 // match expression {
279256 // case pattern1: result1
@@ -563,9 +540,11 @@ private Expression primary() {
563540 }
564541
565542 private Expression variable () {
543+ // function(...
566544 if (lookMatch (0 , TokenType .WORD ) && lookMatch (1 , TokenType .LPAREN )) {
567545 return function (new ValueExpression (consume (TokenType .WORD ).getText ()));
568546 }
547+
569548 final Expression qualifiedNameExpr = qualifiedName ();
570549 if (qualifiedNameExpr != null ) {
571550 // variable(args) || arr["key"](args) || obj.key(args)
@@ -585,17 +564,35 @@ private Expression variable() {
585564 }
586565
587566 private Expression qualifiedName () {
567+ // var || var.key[index].key2
588568 final Token current = get (0 );
589- if (lookMatch (0 , TokenType .WORD ) && lookMatch (1 , TokenType .LBRACKET )) {
590- return element ();
569+ if (!match (TokenType .WORD )) return null ;
570+
571+ final List <Expression > indices = variableSuffix ();
572+ if ((indices == null ) || indices .isEmpty ()) {
573+ return new VariableExpression (current .getText ());
591574 }
592- if (lookMatch (0 , TokenType .WORD ) && lookMatch (1 , TokenType .DOT )) {
593- return object ();
575+ return new ContainerAccessExpression (current .getText (), indices );
576+ }
577+
578+ private List <Expression > variableSuffix () {
579+ // .key1.arr1[expr1][expr2].key2
580+ if (!lookMatch (0 , TokenType .DOT ) && !lookMatch (0 , TokenType .LBRACKET )) {
581+ return null ;
594582 }
595- if (match (TokenType .WORD )) {
596- return new VariableExpression (current .getText ());
583+ final List <Expression > indices = new ArrayList <>();
584+ while (lookMatch (0 , TokenType .DOT ) || lookMatch (0 , TokenType .LBRACKET )) {
585+ if (match (TokenType .DOT )) {
586+ final String fieldName = consume (TokenType .WORD ).getText ();
587+ final Expression key = new ValueExpression (fieldName );
588+ indices .add (key );
589+ }
590+ if (match (TokenType .LBRACKET )) {
591+ indices .add (expression ());
592+ consume (TokenType .RBRACKET );
593+ }
597594 }
598- return null ;
595+ return indices ;
599596 }
600597
601598 private Expression value () {
0 commit comments