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