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'; }
 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