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