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