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