arnaucube
arnaucube/circomPublic Self-hosted repository
circom/parser/jaz.jison
parser/jaz.jisonRaw
  1/* description: Construct AST for jaz language. */
  2
  3/* lexical grammar */
  4%lex
  5
  6%%
  7
  8\s+                     { /* skip whitespace */ }
  9\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/ { /* console.log("MULTILINE COMMENT: "+yytext); */  }
 10\/\/.*                                      { /* console.log("SINGLE LINE COMMENT: "+yytext); */ }
 11var                     { return 'var'; }
 12signal                  { return 'signal'; }
 13input                   { return 'input'; }
 14output                  { return 'output'; }
 15linearCombination       { return 'linearCombination'; }
 16component               { return 'component'; }
 17template                { return 'template'; }
 18function                { return 'function'; }
 19if                      { return 'if'; }
 20else                    { return 'else'; }
 21for                     { return 'for'; }
 22while                   { return 'while'; }
 23do                      { return 'do'; }
 24return                  { return 'return'; }
 25include                 { return 'include'; }
 260x[0-9A-Fa-f]*          { return 'HEXNUMBER'; }
 27[0-9]+                  { return 'DECNUMBER'; }
 28[a-zA-Z][a-zA-Z$_0-9]*  { return 'IDENTIFIER'; }
 29\"[^"]+\"               { yytext = yytext.slice(1,-1); return 'STRING'; }
 30\=\=\>                  { return '==>'; }
 31\<\=\=                  { return '<=='; }
 32\-\-\>                  { return '-->'; }
 33\<\-\-                  { return '<--'; }
 34\=\=\=                  { return '==='; }
 35\>\>\=                  { return '>>='; }
 36\<\<\=                  { return '<<='; }
 37\&\&                    { return '&&'; }
 38\|\|                    { return '||'; }
 39\=\=                    { return '=='; }
 40\<\=                    { return '<='; }
 41\>\=                    { return '>='; }
 42\!\=                    { return '!='; }
 43\>\>                    { return '>>'; }
 44\<\<                    { return '<<'; }
 45\*\*                    { return '**'; }
 46\+\+                    { return '++'; }
 47\-\-                    { return '--'; }
 48\+\=                    { return '+='; }
 49\-\=                    { return '-='; }
 50\*\=                    { return '*='; }
 51\/\=                    { return '/='; }
 52\%\=                    { return '%='; }
 53\|\=                    { return '|='; }
 54\&\=                    { return '&='; }
 55\^\=                    { return '^='; }
 56\=                      { return '='; }
 57\+                      { return '+'; }
 58\-                      { return '-'; }
 59\*                      { return '*'; }
 60\/                      { return '/'; }
 61\%                      { return '%'; }
 62\^                      { return '^'; }
 63\&                      { return '&'; }
 64\|                      { return '|'; }
 65\!                      { return '!'; }
 66\<                      { return '<'; }
 67\>                      { return '>'; }
 68\!                      { return '!'; }
 69\?                      { return '?'; }
 70\:                      { return ':'; }
 71\(                      { return '('; }
 72\)                      { return ')'; }
 73\[                      { return '['; }
 74\]                      { return ']'; }
 75\{                      { return '{'; }
 76\}                      { return '}'; }
 77\;                      { return ';'; }
 78\,                      { return ','; }
 79\.                      { return '.'; }
 80<<EOF>>                 { return 'EOF'; }
 81.                       { console.log("INVALID: " + yytext); return 'INVALID'}
 82
 83/lex
 84
 85%left ';'
 86%right 'if' 'else'
 87%left EMPTY
 88%left IDLIST
 89%left ','
 90%right '?' ':' TERCOND '=' '+=' '-=' '*=' '/=' '%=' '>>=' '<<=' '&=' '|=' '^=' '<==' '==>' '===' '<--' '-->'
 91%left '||'
 92%left '&&'
 93%left '|'
 94%left '^'
 95%left '&'
 96%left '==' '!='
 97%left '<=' '>=' '<' '>'
 98%left '<<' '>>'
 99
100%left '+' '-'
101%left '*' '/' '%'
102%left '**'
103%right '++' '--' UMINUS UPLUS '!' '~'
104%left '.'
105%left DECL
106%left  PLUSPLUSRIGHT MINUSMINUSRIGHT '[' ']' '(' ')'
107%left HIGH
108
109
110
111%{
112const bigInt = require('big-integer');
113const util = require('util');
114const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
115const __MASK__ = new bigInt(2).pow(253).minus(1);
116
117function setLines(dst, first, last) {
118    last = last || first;
119    dst.first_line = first.first_line;
120    dst.first_column = first.first_column;
121    dst.last_line = last.last_line;
122    dst.last_column = last.last_column;
123}
124
125%}
126
127%start allStatments
128
129%% /* language grammar */
130
131
132allStatments
133    : statmentList EOF
134        {
135//            console.log(JSON.stringify($1, null, 1));
136            $$ = { type: "BLOCK", statements: $1.statments };
137            setLines($$, @1);
138            return $$
139        }
140    ;
141
142statmentList
143    : statmentList statment
144        {
145            $1.statments.push($2);
146            setLines($1, @1, @2);
147        }
148    | statment
149        {
150            $$ = { type: "STATMENTLIST", statments: [$1] };
151            setLines($$, @1);
152        }
153    ;
154
155statment
156    : functionDefinitionStatment
157        {
158            $$ = $1;
159        }
160    | templateDefinitionStatment
161        {
162            $$ = $1;
163        }
164    | ifStatment
165        {
166            $$ = $1;
167        }
168    | forStatment
169        {
170            $$ = $1;
171        }
172    | whileStatment
173        {
174            $$ = $1;
175        }
176    | doWhileStatment
177        {
178            $$ = $1;
179        }
180    | returnStatment
181        {
182            $$ = $1;
183        }
184    | block
185        {
186            $$ = $1;
187        }
188    | expressionStatment
189        {
190            $$ = $1;
191        }
192    | includeStatment
193        {
194            $$ = $1;
195        }
196    ;
197
198
199functionDefinitionStatment
200    : 'function' IDENTIFIER '(' identifierList ')' block
201        {
202            $$ = { type: "FUNCTIONDEF", name: $2, params: $4.identifiers, block: $6};
203            setLines($$, @1, @6);
204        }
205    | 'function' IDENTIFIER '(' ')' block
206        {
207            $$ = { type: "FUNCTIONDEF", name: $2, params: [], block: $5 };
208            setLines($$, @1, @5);
209        }
210    ;
211
212templateDefinitionStatment
213    : 'template' IDENTIFIER '(' identifierList ')' block
214        {
215            $$ = { type: "TEMPLATEDEF", name: $2, params: $4.identifiers, block: $6 };
216            setLines($$, @1, @6);
217        }
218    | 'template' IDENTIFIER '(' ')' block
219        {
220            $$ = { type: "TEMPLATEDEF", name: $2, params: [], block: $5 };
221            setLines($$, @1, @5);
222        }
223    ;
224
225
226identifierList
227    : identifierList ',' IDENTIFIER
228        {
229            $1.identifiers.push($3);
230            setLines($1, @1, @3);
231        }
232    | IDENTIFIER %prec EMPTY
233        {
234            $$ = { type: "IDENTIFIERLIST", identifiers: [$1] };
235            setLines($$, @1);
236        }
237    ;
238
239ifStatment
240    : 'if' '(' expression ')' statment 'else' statment
241        {
242            if ($3.type == "NUMBER") {
243                $$ = !$3.value.eq(0) ? $5 : $7;
244            } else {
245                $$ = { type: "IF", condition: $3, then: $5, else: $7 };
246            }
247            setLines($$, @1, @7);
248        }
249    | 'if' '(' expression ')' statment
250        {
251            if ($3.type == "NUMBER") {
252                $$ = !$3.value.eq(0) ? $5 : { type: "NUMBER", value: bigInt(0) };
253            } else {
254                $$ = { type: "IF", condition: $3, then: $5 };
255            }
256            setLines($$, @1, @5);
257        }
258    ;
259
260forStatment
261    : 'for' '(' expression ';' expression ';' expression ')' statment
262        {
263            $$ = { type: "FOR", init: $3, condition: $5, step: $7, body: $9 };
264            setLines($$, @1, @9);
265        }
266    ;
267
268whileStatment
269    : 'while' '(' expression ')' statment
270        {
271            $$ = { type: "WHILE", condition: $3, body: $5 };
272            setLines($$, @1, @5);
273        }
274    ;
275
276doWhileStatment
277    : 'do' statment 'while' '(' expression ')'
278        {
279            $$ = { type: "DOWHILE", condition: $5, body: $2 };
280            setLines($$, @1, @6);
281        }
282    ;
283
284returnStatment
285    : 'return' expression ';'
286        {
287            $$ = { type: "RETURN", value: $2 };
288            setLines($$, @1, @3);
289        }
290    | 'return' expression %prec ';'
291        {
292            $$ = { type: "RETURN", value: $2 }
293            setLines($$, @1, @2);
294        }
295    ;
296
297includeStatment
298    : 'include' STRING ';'
299        {
300            $$ = { type: "INCLUDE", file: $2 };
301            setLines($$, @1, @3);
302        }
303    | 'include' STRING %prec ';'
304        {
305            $$ = { type: "INCLUDE", file: $2 }
306            setLines($$, @1, @2);
307        }
308    ;
309
310block
311    : '{' statmentList '}'
312        {
313            $$ = { type: "BLOCK", statements: $2.statments };
314            setLines($$, @1, @3);
315        }
316    ;
317
318expressionStatment
319    : expression ';' %prec ';'
320        {
321            $$ = $1;
322        }
323    | expression %prec ';'
324        {
325            $$ = $1;
326        }
327    ;
328
329expression
330    : e17 %prec EMPTY
331        {
332            $$ = $1;
333        }
334    ;
335
336e17
337   : leftHandExpression '=' e17
338        {
339            $$ = { type: "OP", op: "=", values: [$1, $3] };
340            setLines($$, @1, @3);
341        }
342    | leftHandExpression '+=' e17
343        {
344            $$ = { type: "OP", op: "+=", values: [$1, $3] };
345            setLines($$, @1, @3);
346        }
347    | leftHandExpression '-=' e17
348        {
349            $$ = { type: "OP", op: "-=", values: [$1, $3] };
350            setLines($$, @1, @3);
351        }
352    | leftHandExpression '*=' e17
353        {
354            $$ = { type: "OP", op: "*=", values: [$1, $3] };
355            setLines($$, @1, @3);
356        }
357    | leftHandExpression '/=' e17
358        {
359            $$ = { type: "OP", op: "/=", values: [$1, $3] };
360            setLines($$, @1, @3);
361        }
362    | leftHandExpression '%=' e17
363        {
364            $$ = { type: "OP", op: "%=", values: [$1, $3] };
365            setLines($$, @1, @3);
366        }
367    | leftHandExpression '<<=' e17
368        {
369            $$ = { type: "OP", op: "<<=", values: [$1, $3] };
370            setLines($$, @1, @3);
371        }
372    | leftHandExpression '>>=' e17
373        {
374            $$ = { type: "OP", op: ">>=", values: [$1, $3] };
375            setLines($$, @1, @3);
376        }
377    | leftHandExpression '&=' e17
378        {
379            $$ = { type: "OP", op: "&=", values: [$1, $3] };
380            setLines($$, @1, @3);
381        }
382    | leftHandExpression '|=' e17
383        {
384            $$ = { type: "OP", op: "|=", values: [$1, $3] };
385            setLines($$, @1, @3);
386        }
387    | leftHandExpression '^=' e17
388        {
389            $$ = { type: "OP", op: "^=", values: [$1, $3] };
390            setLines($$, @1, @3);
391        }
392    | leftHandExpression '<==' e17
393        {
394            $$ = { type: "OP", op: "<==", values: [$1, $3] };
395            setLines($$, @1, @3);
396        }
397    | e17 '==>' leftHandExpression
398        {
399            $$ = { type: "OP", op: "<==", values: [$3, $1] };
400            setLines($$, @1, @3);
401        }
402    | leftHandExpression '<--' e17
403        {
404            $$ = { type: "OP", op: "<--", values: [$1, $3] };
405            setLines($$, @1, @3);
406        }
407    | e17 '-->' leftHandExpression
408        {
409            $$ = { type: "OP", op: "<--", values: [$3, $1] };
410            setLines($$, @1, @3);
411        }
412    | e16 '===' e17
413        {
414            $$ = { type: "OP", op: "===", values: [$1, $3] };
415            setLines($$, @1, @3);
416        }
417    | e17 '?' e17 ':' e17 %prec TERCOND
418        {
419            if ($1.type == "NUMBER") {
420                $$ = !$1.value.eq(0) ? $3 : $5;
421            } else {
422                $$ = { type: "OP", op: "?", values: [$1, $3, $5] };
423            }
424            setLines($$, @1, @5);
425        }
426    | e16 %prec EMPTY
427       {
428        $$ = $1;
429       }
430    ;
431
432e16
433    : rightArray
434       {
435        $$ = $1;
436       }
437    | e15 %prec EMPTY
438       {
439        $$ = $1;
440       }
441    ;
442
443e15
444    : e15 '||' e14
445        {
446            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
447                $$ = { type: "NUMBER", value: !$1.value.eq(0) || !$3.value.eq(0) ? bigInt(1) : bigInt(0) };
448            } else {
449                $$ = { type: "OP", op: "||", values: [$1, $3] };
450            }
451            setLines($$, @1, @3);
452        }
453    | e14 %prec EMPTY
454       {
455        $$ = $1;
456       }
457    ;
458
459e14
460    : e14 '&&' e13
461        {
462            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
463                $$ = { type: "NUMBER", value: !$1.value.eq(0) && !$3.value.eq(0) ? bigInt(1) : bigInt(0) };
464            } else {
465                $$ = { type: "OP", op: "&&", values: [$1, $3] };
466            }
467            setLines($$, @1, @3);
468        }
469    | e13 %prec EMPTY
470       {
471        $$ = $1;
472       }
473    ;
474
475e13
476    : e13 '|' e12
477        {
478            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
479                $$ = { type: "NUMBER", value: $1.value.or($3.value).and(__MASK__) };
480            } else {
481                $$ = { type: "OP", op: "|", values: [$1, $3] };
482            }
483            setLines($$, @1, @3);
484        }
485    | e12 %prec EMPTY
486       {
487        $$ = $1;
488       }
489    ;
490
491
492e12
493    : e12 '^' e11
494        {
495            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
496                $$ = { type: "NUMBER", value: $1.value.or($3.value).and(__MASK__) };
497            } else {
498                $$ = { type: "OP", op: "^", values: [$1, $3] };
499            }
500            setLines($$, @1, @3);
501        }
502    | e11 %prec EMPTY
503        {
504            $$ = $1;
505        }
506    ;
507
508e11
509    : e11 '&' e10
510        {
511            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
512                $$ = { type: "NUMBER", value: $1.value.and($3.value).and(__MASK__) };
513            } else {
514                $$ = { type: "OP", op: "&", values: [$1, $3] };
515            }
516            setLines($$, @1, @3);
517        }
518    | e10 %prec EMPTY
519        {
520            $$ = $1;
521        }
522    ;
523
524
525
526
527e10
528    : e10 '==' e9
529        {
530            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
531                $$ = { type: "NUMBER", value: $1.value.equals($3.value) ? bigInt(1) : bigInt(0) };
532            } else {
533                $$ = { type: "OP", op: "==", values: [$1, $3] };
534            }
535            setLines($$, @1, @3);
536        }
537    | e10 '!=' e9
538        {
539            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
540                $$ = { type: "NUMBER", value: $1.value.eq($3.value) ? bigInt(0) : bigInt(1) };
541            } else {
542                $$ = { type: "OP", op: "!=", values: [$1, $3] };
543            }
544            setLines($$, @1, @3);
545        }
546    | e9 %prec EMPTY
547       {
548        $$ = $1
549       }
550    ;
551
552e9
553    : e9 '<=' e7
554        {
555            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
556                $$ = { type: "NUMBER", value: $1.value.lesserOrEquals($3.value) ? bigInt(1) : bigInt(0) };
557            } else {
558                $$ = { type: "OP", op: "<=", values: [$1, $3] };
559            }
560            setLines($$, @1, @3);
561        }
562    | e9 '>=' e7
563        {
564            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
565                $$ = { type: "NUMBER", value: $1.value.greaterOrEquals($3.value) ? bigInt(1) : bigInt(0) };
566            } else {
567                $$ = { type: "OP", op: ">=", values: [$1, $3] };
568            }
569            setLines($$, @1, @3);
570        }
571    | e9 '<' e7
572        {
573            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
574                $$ = { type: "NUMBER", value: $1.value.lesser($3.value) ? bigInt(1) : bigInt(0) };
575            } else {
576                $$ = { type: "OP", op: "<", values: [$1, $3] };
577            }
578            setLines($$, @1, @3);
579        }
580    | e9 '>' e7
581        {
582            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
583                $$ = { type: "NUMBER", value: $1.value.greater($3.value) ? bigInt(1) : bigInt(0) };
584            } else {
585                $$ = { type: "OP", op: ">", values: [$1, $3] };
586            }
587            setLines($$, @1, @3);
588        }
589    | e7 %prec EMPTY
590       {
591        $$ = $1
592       }
593    ;
594
595e7
596    : e7 '<<' e6
597        {
598            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
599                let v = $3.value.greater(256) ? 256 : $3.value.value;
600                $$ = { type: "NUMBER", value: $1.value.shiftLeft(v).and(__MASK__) };
601            } else {
602                $$ = { type: "OP", op: "<<", values: [$1, $3] };
603            }
604            setLines($$, @1, @3);
605        }
606    | e7 '>>' e6
607        {
608            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
609                let v = $3.value.greater(256) ? 256 : $3.value.value;
610                $$ = {t1ype: "NUMBER", value: $1.value.shiftRight(v).and(__MASK__) };
611            } else {
612                $$ = { type: "OP", op: ">>", values: [$1, $3] };
613            }
614            setLines($$, @1, @3);
615        }
616    | e6 %prec EMPTY
617       {
618            $$ = $1;
619       }
620    ;
621
622e6
623    : e6 '+' e5
624        {
625            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
626                $$ = { type: "NUMBER", value: ($1.value.plus($3.value)).mod(__P__) };
627            } else {
628                $$ = { type: "OP", op: "+", values: [$1, $3] };
629            }
630            setLines($$, @1, @3);
631        }
632    | e6 '-' e5
633        {
634            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
635                $$ = { type: "NUMBER", value: ($1.value.plus(__P__).minus($3.value)).mod(__P__) };
636            } else {
637                $$ = { type: "OP", op: "-", values: [$1, $3] };
638            }
639            setLines($$, @1, @3);
640        }
641    | e5 %prec EMPTY
642        {
643            $$ = $1;
644        }
645    ;
646
647
648e5
649    : e5 '*' e4
650        {
651            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
652                $$ = { type: "NUMBER", value: ($1.value.times($3.value)).mod(__P__) };
653            } else {
654                $$ = { type: "OP", op: "*", values: [$1, $3] };
655            }
656            setLines($$, @1, @3);
657        }
658    | e5 '/' e4
659        {
660            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
661                $$ = { type: "NUMBER", value: ($1.value.times($3.value.modInv(__P__))).mod(__P__) };
662            } else {
663                $$ = { type: "OP", op: "/", values: [$1, $3] };
664            }
665            setLines($$, @1, @3);
666        }
667    | e5 '%' e4
668        {
669            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
670                $$ = { type: "NUMBER", value: $1.value.mod($3.value) };
671            } else {
672                $$ = { type: "OP", op: "%", values: [$1, $3] };
673            }
674            setLines($$, @1, @3);
675        }
676    | e4 %prec EMPTY
677        {
678            $$ = $1;
679        }
680    ;
681
682e4
683    : e4 '**' e3
684        {
685            if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
686                $$ = { type: "NUMBER", value: $1.value.modPow($3.value, __P__) };
687            } else {
688                $$ = { type: "OP", op: "**", values: [$1, $3] };
689            }
690            setLines($$, @1, @3);
691        }
692    | e3 %prec EMPTY
693        {
694            $$ = $1;
695        }
696    ;
697
698
699e3
700    : '++' leftHandExpression
701        {
702            $$ = { type: "OP", op: "PLUSPLUSLEFT", values: [$2] };
703            setLines($$, @1, @2);
704        }
705    | '--' leftHandExpression
706        {
707            $$ = { type: "OP", op: "MINUSMINUSLEFT", values: [$2] };
708            setLines($$, @1, @2);
709        }
710    | '+' e3 %prec UPLUS
711        {
712            $$ = $2;
713            setLines($$, @1, @2);
714        }
715    | '-' e3 %prec UMINUS
716        {
717            if ($2.type == "NUMBER") {
718                $$ = { type: "NUMBER", value: __P__.minus($2.value).mod(__P__) };
719            } else {
720                $$ = { type: "OP", op: "UMINUS", values: [$2] };
721            }
722            setLines($$, @1, @2);
723        }
724    | '!' e3
725        {
726            if ($2.type == "NUMBER") {
727                $$ = { type: "NUMBER", value: $2.value.eq(0) ? bigInt(1) : bigInt(0) };
728            } else {
729                $$ = { type: "OP", op: "!", values: [$2] };
730            }
731            setLines($$, @1, @2);
732        }
733    | '~' e3
734        {
735            if ($2.type == "NUMBER") {
736                $$ = { type: "NUMBER", value: $2.value.xor(__MASK__) };
737            } else {
738                $$ = { type: "OP", op: "~", values: [$2] };
739            }
740            setLines($$, @1, @2);
741        }
742    | e2 %prec EMPTY
743        {
744            $$ = $1;
745        }
746    ;
747
748e2
749    : leftHandExpression '++' %prec PLUSPLUSRIGHT
750        {
751            $$ = {type: "OP", op: "PLUSPLUSRIGHT", values: [$1] };
752            setLines($$, @1, @2);
753        }
754    | leftHandExpression '--' %prec MINUSMINUSRIGHT
755        {
756            $$ = {type: "OP", op: "MINUSMINUSRIGHT", values: [$1] };
757            setLines($$, @1, @2);
758        }
759    | functionCall
760        {
761            $$ = $1;
762        }
763    | e0 %prec EMPTY
764        {
765            $$ = $1;
766        }
767    ;
768
769e0
770    : leftHandExpression %prec EMPTY
771        {
772            $$ = $1
773        }
774    | DECNUMBER
775        {
776            $$ = {type: "NUMBER", value: bigInt($1).mod(__P__) }
777            setLines($$, @1);
778        }
779    | HEXNUMBER
780        {
781            $$ = {type: "NUMBER", value: bigInt($1.substr(2).toUpperCase(), 16).mod(__P__) }
782            setLines($$, @1);
783        }
784    | '(' expression ')' %prec EMPTY
785        {
786            $$ = $2;
787            setLines($$, @1, @3);
788        }
789    ;
790
791leftHandExpression
792    : simpleLeftHandExpression '.' simpleLeftHandExpression %prec EMPTY
793        {
794            $$ = {type: "PIN", component: $1, pin: $3 };
795            setLines($$, @1, @3);
796        }
797    | declaration %prec DECL
798        {
799            $$ = $1
800        }
801    | simpleLeftHandExpression %prec EMPTY
802        {
803            $$ = $1
804        }
805    ;
806
807
808
809declaration
810    : 'var' simpleLeftHandExpression %prec DECL
811        {
812            $$ = {type: "DECLARE", declareType: "VARIABLE", name: $2}
813            setLines($$, @1, @2);
814        }
815    | 'signal' simpleLeftHandExpression %prec DECL
816        {
817            $$ = {type: "DECLARE", declareType: "SIGNAL", name: $2}
818            setLines($$, @1, @2);
819        }
820    | 'signal' 'input' simpleLeftHandExpression %prec DECL
821        {
822            $$ = {type: "DECLARE", declareType: "SIGNALIN", name: $3};
823            setLines($$, @1, @3);
824        }
825    | 'signal' 'output' simpleLeftHandExpression %prec DECL
826        {
827            $$ = {type: "DECLARE", declareType: "SIGNALOUT", name: $3};
828            setLines($$, @1, @3);
829        }
830    | 'component' simpleLeftHandExpression %prec DECL
831        {
832            $$ = {type: "DECLARE", declareType: "COMPONENT", name: $2}
833            setLines($$, @1, @2);
834        }
835    ;
836
837simpleLeftHandExpression
838    : simpleLeftHandExpression array
839        {
840            for (let i=0; i< $2.values.length; i++) {
841                $1.selectors.push($2.values[i]);
842            }
843            setLines($1, @1, @2);
844        }
845    | IDENTIFIER %prec EMPTY
846        {
847            $$ = {type: "VARIABLE", name: $1 , selectors: []};
848            setLines($$, @1);
849        }
850    ;
851
852functionCall
853    : IDENTIFIER '(' expressionList ')'
854        {
855            $$ = {type: "FUNCTIONCALL", name: $1, params: $3.expressions}
856            setLines($$, @1, @4);
857        }
858    | IDENTIFIER '(' ')'
859        {
860            $$ = {type: "FUNCTIONCALL", name: $1, params: []}
861            setLines($$, @1, @3);
862        }
863    ;
864
865expressionList
866    : expressionList ',' expression
867        {
868            $1.expressions.push($3);
869            setLines($$, @1, @3);
870        }
871    | expression %prec ','
872        {
873            $$ = {type: "EXPRESSIONLST", expressions: [$1]};
874            setLines($$, @1);
875        }
876    ;
877
878rightArray
879    : array %prec EMPTY
880        {
881            $$ = $1;
882        }
883    ;
884
885array
886    : '[' expressionList ']'
887           {
888                $$ = { type: "ARRAY", values: $2.expressions};
889                setLines($$, @1, @3);
890           }
891    ;
892