module ::= ([COMMENT] [SAD] stmt)* comma ::= ',' [COMMENT] [IND] operator ::= OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9 | 'or' | 'xor' | 'and' | 'is' | 'isnot' | 'in' | 'notin' | 'div' | 'mod' | 'shl' | 'shr' | 'not' | '..' prefixOperator ::= operator optInd ::= [COMMENT] [IND] optPar ::= [IND] | [SAD] lowestExpr ::= orExpr (OP1 optInd orExpr)* orExpr ::= andExpr (OP2 optInd andExpr)* andExpr ::= cmpExpr (OP3 optInd cmpExpr)* cmpExpr ::= sliceExpr (OP4 optInd sliceExpr)* sliceExpr ::= ampExpr (OP5 optInd ampExpr)* ampExpr ::= plusExpr (OP6 optInd plusExpr)* plusExpr ::= mulExpr (OP7 optInd mulExpr)* mulExpr ::= dollarExpr (OP8 optInd dollarExpr)* dollarExpr ::= primary (OP9 optInd primary)* indexExpr ::= expr castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')' addrExpr ::= 'addr' '(' optInd expr optPar ')' symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')' | '[' ']' | '=' | literal)+ '`' | IDENT primaryPrefix ::= (prefixOperator | 'bind') optInd primarySuffix ::= '.' optInd symbol [generalizedLit] | '(' optInd namedExprList optPar ')' | '[' optInd [indexExpr (comma indexExpr)* [comma]] optPar ']' | '^' | pragma primary ::= primaryPrefix* (symbol [generalizedLit] | constructor | castExpr | addrExpr) primarySuffix* generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT | FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT | STR_LIT | RSTR_LIT | TRIPLESTR_LIT | CHAR_LIT | NIL constructor ::= literal | '[' optInd colonExprList optPar ']' | '{' optInd ':' | colonExprList optPar '}' | '(' optInd colonExprList optPar ')' colonExpr ::= expr [':' expr] colonExprList ::= [colonExpr (comma colonExpr)* [comma]] namedExpr ::= expr ['=' expr] namedExprList ::= [namedExpr (comma namedExpr)* [comma]] exprOrType ::= lowestExpr | 'if' expr ':' expr ('elif' expr ':' expr)* 'else' ':' expr | 'var' exprOrType | 'ref' exprOrType | 'ptr' exprOrType | 'type' exprOrType | 'tuple' tupleDesc expr ::= exprOrType | 'proc' paramList [pragma] ['=' stmt] exprList ::= [expr (comma expr)* [comma]] qualifiedIdent ::= symbol ['.' symbol] typeDesc ::= exprOrType | 'proc' paramList [pragma] macroStmt ::= ':' [stmt] ('of' [exprList] ':' stmt |'elif' expr ':' stmt |'except' exceptList ':' stmt )* ['else' ':' stmt] simpleStmt ::= returnStmt | yieldStmt | discardStmt | raiseStmt | breakStmt | continueStmt | pragma | importStmt | fromStmt | includeStmt | exprStmt complexStmt ::= ifStmt | whileStmt | caseStmt | tryStmt | forStmt | blockStmt | asmStmt | procDecl | iteratorDecl | macroDecl | templateDecl | methodDecl | constSection | typeSection | whenStmt | varSection indPush ::= IND # and push indentation onto the stack indPop ::= # pop indentation from the stack stmt ::= simpleStmt [SAD] | indPush (complexStmt | simpleStmt) ([SAD] (complexStmt | simpleStmt))* DED indPop exprStmt ::= lowestExpr ['=' expr | [expr (comma expr)*] [macroStmt]] returnStmt ::= 'return' [expr] yieldStmt ::= 'yield' expr discardStmt ::= 'discard' expr raiseStmt ::= 'raise' [expr] breakStmt ::= 'break' [symbol] continueStmt ::= 'continue' ifStmt ::= 'if' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt] whenStmt ::= 'when' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt] caseStmt ::= 'case' expr [':'] ('of' exprList ':' stmt)* ('elif' expr ':' stmt)* ['else' ':' stmt] whileStmt ::= 'while' expr ':' stmt forStmt ::= 'for' symbol (comma symbol)* 'in' expr ':' stmt exceptList ::= [qualifiedIdent (comma qualifiedIdent)*] tryStmt ::= 'try' ':' stmt ('except' exceptList ':' stmt)* ['finally' ':' stmt] asmStmt ::= 'asm' [pragma] (STR_LIT | RSTR_LIT | TRIPLESTR_LIT) blockStmt ::= 'block' [symbol] ':' stmt filename ::= symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT importStmt ::= 'import' filename (comma filename)* includeStmt ::= 'include' filename (comma filename)* fromStmt ::= 'from' filename 'import' symbol (comma symbol)* pragma ::= '{.' optInd (colonExpr [comma])* optPar ('.}' | '}') param ::= symbol (comma symbol)* (':' typeDesc ['=' expr] | '=' expr) paramList ::= ['(' [param (comma param)*] optPar ')'] [':' typeDesc] genericConstraint ::= 'object' | 'tuple' | 'enum' | 'proc' | 'ref' | 'ptr' | 'var' | 'distinct' | primary genericConstraints ::= genericConstraint ( '|' optInd genericConstraint )* genericParam ::= symbol [':' genericConstraints] ['=' expr] genericParams ::= '[' genericParam (comma genericParam)* optPar ']' routineDecl := symbol ['*'] [genericParams] paramList [pragma] ['=' stmt] procDecl ::= 'proc' routineDecl macroDecl ::= 'macro' routineDecl iteratorDecl ::= 'iterator' routineDecl templateDecl ::= 'template' routineDecl methodDecl ::= 'method' routineDecl colonAndEquals ::= [':' typeDesc] '=' expr constDecl ::= symbol ['*'] [pragma] colonAndEquals [COMMENT | IND COMMENT] | COMMENT constSection ::= 'const' indPush constDecl (SAD constDecl)* DED indPop typeDef ::= typeDesc | objectDef | enumDef | 'distinct' typeDesc objectField ::= symbol ['*'] [pragma] objectIdentPart ::= objectField (comma objectField)* ':' typeDesc [COMMENT|IND COMMENT] objectWhen ::= 'when' expr ':' [COMMENT] objectPart ('elif' expr ':' [COMMENT] objectPart)* ['else' ':' [COMMENT] objectPart] objectCase ::= 'case' expr ':' typeDesc [COMMENT] ('of' exprList ':' [COMMENT] objectPart)* ['else' ':' [COMMENT] objectPart] objectPart ::= objectWhen | objectCase | objectIdentPart | 'nil' | indPush objectPart (SAD objectPart)* DED indPop tupleDesc ::= '[' optInd [param (comma param)*] optPar ']' objectDef ::= 'object' [pragma] ['of' typeDesc] objectPart enumField ::= symbol ['=' expr] enumDef ::= 'enum' (enumField [comma] [COMMENT | IND COMMENT])+ typeDecl ::= COMMENT | symbol ['*'] [genericParams] ['=' typeDef] [COMMENT | IND COMMENT] typeSection ::= 'type' indPush typeDecl (SAD typeDecl)* DED indPop colonOrEquals ::= ':' typeDesc ['=' expr] | '=' expr varField ::= symbol ['*'] [pragma] varPart ::= symbol (comma symbol)* colonOrEquals [COMMENT | IND COMMENT] varSection ::= 'var' (varPart | indPush (COMMENT|varPart) (SAD (COMMENT|varPart))* DED indPop)