diff --git a/grammar/Circom.g4 b/grammar/Circom.g4 index 0605d02..6013fdc 100644 --- a/grammar/Circom.g4 +++ b/grammar/Circom.g4 @@ -1,45 +1,26 @@ grammar Circom; +import LexerCircom; + circuit - : pragmaDeclaration+ includeDeclaration* blockDeclaration* componentMainDeclaration? + : PRAGMA_DECLARATION+ INCLUDE_DECLARATION* blockDeclaration* componentMainDeclaration? EOF ; -pragmaDeclaration - : 'pragma' version ';' - | 'pragma' 'custom_templates' ';' - ; - -version - : 'circom' INT '.' INT '.' INT - ; - -includeDeclaration - : 'include' packageName ';' - ; - -packageName - : '"' qualifiedPackageName '"' - ; - -qualifiedPackageName - : .*? '.circom'? - ; - blockDeclaration : functionDeclaration | templateDeclaration ; functionDeclaration - : 'function' ID '(' args* ')' functionStmt + : 'function' ID '(' ARGS* ')' functionStmt ; functionStmt : '{' functionStmt* '}' - | ID selfOp + | ID SELF_OP | varDeclaration - | expression (assignment | assigmentOp) expression + | expression (ASSIGNMENT | ASSIGNMENT_OP) expression | 'if' parExpression functionStmt ('else' functionStmt)? | 'while' parExpression functionStmt | 'for' '(' forControl ')' functionStmt @@ -48,28 +29,28 @@ functionStmt ; templateDeclaration - : 'template' ID '(' args* ')' statement* - | 'template' 'custom' ID '(' args* ')' statement* + : 'template' ID '(' ARGS* ')' statement* + | 'template' 'custom' ID '(' ARGS* ')' statement* ; componentMainDeclaration - : 'component' 'main' ('{' 'public' '[' args ']' '}')? '=' ID '(' intSequence* ')' ';' + : 'component' 'main' ('{' 'public' '[' ARGS ']' '}')? '=' ID '(' INT_SEQUENCE* ')' ';' ; statement : '{' statement* '}' - | ID selfOp + | ID SELF_OP | varDeclaration | signalDeclaration | componentDeclaration | blockInstantiation - | expression (assignment | constraintEq) expression - | (primary | ((ID arrayDimension*) '.' (ID arrayDimension*))) (leftAssignment | assigmentOp) expression - | expression rightAssignment primary - | '_' (assignment | leftAssignment) (expression | blockInstantiation) - | (expression | blockInstantiation) rightAssignment '_' - | '(' argsWithUnderscore ')' (assignment | leftAssignment) blockInstantiation - | blockInstantiation rightAssignment '(' argsWithUnderscore ')' + | expression (ASSIGNMENT | CONSTRATINT_EQ) expression + | (primary | (variableDefinition '.' variableDefinition)) (LEFT_ASSIGNMENT | ASSIGNMENT_OP) expression + | expression RIGHT_ASSIGNMENT primary + | '_' (ASSIGNMENT | LEFT_ASSIGNMENT) (expression | blockInstantiation) + | (expression | blockInstantiation) RIGHT_ASSIGNMENT '_' + | '(' ARGS_AND_UNDERSCORE ')' (ASSIGNMENT | LEFT_ASSIGNMENT) blockInstantiation + | blockInstantiation RIGHT_ASSIGNMENT '(' ARGS_AND_UNDERSCORE ')' | 'if' parExpression statement ('else' statement)? | 'while' parExpression statement | 'for' '(' forControl ')' statement @@ -79,9 +60,9 @@ statement forControl: forInit ';' expression ';' forUpdate ; -forInit: varDefinition (assignment rhsValue)? ; +forInit: varDefinition (ASSIGNMENT rhsValue)? ; -forUpdate: expression | (ID (selfOp | (assignment expression))) ; +forUpdate: expression | (ID (SELF_OP | (ASSIGNMENT expression))) ; parExpression: '(' expression ')' ; @@ -103,81 +84,39 @@ expression primary : '(' expression ')' | '[' expression (',' expression)* ']' - | intSequence - | args - | ID arrayDimension* + | variableDefinition + | INT_SEQUENCE + | ARGS | INT ; -componentDefinition: 'component' ID ; - componentDeclaration - : componentDefinition arrayDimension* (assignment blockInstantiation)? + : COMPONENT_DEFINITION arrayDimension* (ASSIGNMENT blockInstantiation)? ; -signalDefinition: 'signal' signalType? ('{' args '}')? ID arrayDimension*; - -signalType: 'input' | 'output' ; +signalDefinition: 'signal' SIGNAL_TYPE? ('{' ARGS '}')? variableDefinition; signalDeclaration - : signalDefinition (leftAssignment rhsValue)? - | signalDefinition (',' ID arrayDimension*)* + : signalDefinition (LEFT_ASSIGNMENT rhsValue)? + | signalDefinition (',' variableDefinition)* ; -varDefinition: 'var' ID arrayDimension* ; +varDefinition: 'var' variableDefinition ; varDeclaration - : varDefinition (assignment rhsValue)? - | varDefinition (',' ID arrayDimension*)* + : varDefinition (ASSIGNMENT rhsValue)? + | varDefinition (',' variableDefinition)* ; -assignment: '=' ; - -assigmentOp: '+=' | '-=' | '*=' | '**=' | '/=' | '\\=' | '%=' | '<<=' | '>>=' | '&=' | '^=' | '|=' ; - -selfOp: '++' | '--' ; - -leftAssignment: '<--' | '<==' ; - -rightAssignment: '-->' | '==>' ; - -constraintEq: '===' ; - rhsValue: expression | blockInstantiation ; componentCall - : '(' expression (',' expression)* ')' - | '(' ID leftAssignment expression (',' ID leftAssignment expression)* ')' - | '(' expression rightAssignment ID (',' expression rightAssignment ID)* ')' + : '(' LEFT_ASSIGNMENT? expression (',' LEFT_ASSIGNMENT? expression)* ')' + | '(' expression RIGHT_ASSIGNMENT ID (',' expression RIGHT_ASSIGNMENT ID)* ')' ; blockInstantiation: ID '(' ((expression)* | (expression (',' expression)*)) ')' componentCall? ; -arrayDimension: '[' (INT | ID | expression) ']' ; - -argsWithUnderscore: ('_' | ID) (',' ('_' | ID) )* ; - -args: ID (',' ID)* ; - -intSequence: INT (',' INT)* ; - -ID: '_'* LETTER (LETTER | DIGIT | '_' | '$')* ; // match identifiers - -INT: DIGIT+ ; // match integers - -DIGIT: [0-9] ; // match single digit - -LETTER: [a-zA-Z] ; // match single letter - -COMMENT - : '/*' .*? '*/' -> channel(HIDDEN) // match anything between /* and */ - ; - -LINE_COMMENT - : '//' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN) - ; - -WS : [ \r\t\u000C\n]+ -> channel(HIDDEN) - ; - +variableDefinition: ID arrayDimension* ; +arrayDimension: '[' expression ']' ; diff --git a/grammar/LexerCircom.g4 b/grammar/LexerCircom.g4 new file mode 100644 index 0000000..46c2180 --- /dev/null +++ b/grammar/LexerCircom.g4 @@ -0,0 +1,65 @@ +lexer grammar LexerCircom; + +PRAGMA_DECLARATION + : 'pragma' VERSION ';' + | 'pragma' 'custom_templates' ';' + ; + +VERSION + : 'circom' INT '.' INT '.' INT + ; + +INCLUDE_DECLARATION + : 'include' PACKAGE_NAME ';' + ; + +PACKAGE_NAME + : '"' QUALIFIED_PACKAGE_NAME '"' + ; + +fragment +QUALIFIED_PACKAGE_NAME + : .*? '.circom'? + ; + +COMPONENT_DEFINITION: 'component' ID ; + +SIGNAL_TYPE: 'input' | 'output' ; + +ASSIGNMENT: '=' ; + +ASSIGNMENT_OP: '+=' | '-=' | '*=' | '**=' | '/=' | '\\=' | '%=' | '<<=' | '>>=' | '&=' | '^=' | '|=' ; + +SELF_OP: '++' | '--' ; + +LEFT_ASSIGNMENT: '<--' | '<==' ; + +RIGHT_ASSIGNMENT: '-->' | '==>' ; + +CONSTRATINT_EQ: '===' ; + +ARGS_AND_UNDERSCORE: ('_' | ID) (',' ('_' | ID) )* ; + +ARGS: ID (',' ID)* ; + +INT_SEQUENCE: INT (',' INT)* ; + +ID: '_'* LETTER (LETTER | DIGIT | '_' | '$')* ; // match identifiers + +INT: DIGIT+ ; // match integers + +DIGIT: [0-9] ; // match single digit + +LETTER: [a-zA-Z] ; // match single letter + +COMMENT + : '/*' .*? '*/' -> channel(HIDDEN) // match anything between /* and */ + ; + +LINE_COMMENT + : '//' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN) + ; + +WS : [ \r\t\u000C\n]+ -> channel(HIDDEN) + ; +