X-Git-Url: https://gitweb.ps.run/toc/blobdiff_plain/45409c781a9e35df68c43b1e2f028d30bf90c0a0..9610ce88f0b753db81014a053bd3c6d79471c90c:/Toc.g4 diff --git a/Toc.g4 b/Toc.g4 index 95c9a0d..a5d5dd8 100644 --- a/Toc.g4 +++ b/Toc.g4 @@ -2,83 +2,81 @@ grammar Toc; prog: (decl)+ EOF; -decl: varDecl +decl: varDecl ';' | funcDecl | structDecl + | namespaceDecl ; +namespaceDecl: 'namespace' typeName '{' decl* '}'; + varDecl: 'var' var; var: varName (':' type) ('=' expr)?; +varInit: varName (':' type) ('=' expr); -type: typeName; +type: namespaceSpecifier* typeName genericInstantiation? (typeModifier)*; +typeModifier: '*' | ('[' (INT_LIT)? ']'); +namespaceSpecifier: typeName '::'; funcDecl: 'func' func; -func: funcName '(' parameter ')' (':' type) body; -parameter: (firstParameter (additionalParameter)*)?; -firstParameter: var; -additionalParameter: ',' var; +func: funcName genericDecl? '(' parameter ')' (':' type) (body | ';'); +parameter: (var (',' var)*)?; body: '{' stmt* '}'; -structDecl: 'struct' structName '{' structMember* '}'; -structMember: structVar | structMethod; -structVar: var; +structDecl: 'struct' structName genericDecl? '{' structMember* '}'; +structMember: privateDecl? structVar | structMethod; +structVar: var ';'; structMethod: func; +privateDecl: 'private'; +genericDecl: '<' typeName (',' typeName)* '>'; +genericInstantiation: '<' type (',' type)* '>'; -stmt: (varDecl - | conditional - | loop - | assignment - | returnStmt - | expr) ; - -conditional: ifCond; -ifCond: 'if' expr body; - -loop: whileLoop; -whileLoop: 'while' expr body; - -assignment: identifier '=' expr; - -returnStmt: 'return' expr; - -expr: funcCall - | literal - | identifier - | subscript - | memberAccess - | parenExpr - | operatorExpr; +stmt: varDecl ';' + | ifStmt + | switchStmt + | forStmt + | whileStmt + | assignStmt ';' + | returnStmt ';' + | expr ';'; -nonOpExpr: funcCall - | literal - | identifier - | subscript - | memberAccess - | parenExpr; +ifStmt: 'if' expr body elseIfStmt* elseStmt?; +elseIfStmt: 'else' 'if' expr body; +elseStmt: 'else' body; -nonSubscriptExpr: funcCall - | identifier - | memberAccess - | parenExpr; +switchStmt: 'switch' expr switchBody; +switchBody: '{' switchCase* '}'; +switchCase: 'case' expr body; -funcCall: funcName '(' (expr (',' expr)*)? ')'; +forStmt: 'for' varInit ',' expr ',' expr body; -operatorExpr: binaryOperator; -binaryOperator: nonOpExpr BINARY_OPERATOR nonOpExpr (BINARY_OPERATOR nonOpExpr)*; +whileStmt: 'while' expr body; -identifier: varName; +assignStmt: expr '=' expr; -literal: INTLIT; +returnStmt: 'return' expr; -subscript: nonSubscriptExpr '[' expr ']'; +expr: namespaceSpecifier* funcName genericInstantiation? '(' (expr (',' expr)*)? ')' #funcExpr + | expr '.' funcName genericInstantiation? '(' (expr (',' expr)*)? ')' #methodExpr + | literal #litExpr + | '(' expr ')' #parenExpr + | expr (dot | arrow) varName #dotExpr + | prefix_op expr #prefixOpExpr + | expr postfix_op #postfixOpExpr + | expr binary_op expr #binaryOpExpr + | expr '?' expr ':' expr #ternaryOpExpr + | expr '[' expr ']' #bracketExpr + | namespaceSpecifier* varName #identifierExpr + ; -memberAccess: identifier '.' identifier; +dot: '.'; +arrow: '->'; -parenExpr: '(' expr ')'; +literal: INT_LIT | DECIMAL_LIT | StringLit | BOOL_LIT; funcName: NAME; varName: NAME; @@ -86,11 +84,29 @@ typeName: NAME; structName: NAME; -BINARY_OPERATOR: - '+' | '-' | '*' | '/' - | '==' | '!=' - | '<' | '>'; -INTLIT: ('+' | '-')? [0-9]+; +postfix_op: + '++' | '--'; +prefix_op: + '+' | '-' | '!' | '~' | '&' | '*' | postfix_op; +binary_op: + '+' | '-' | '*' | '/' | '%' | '&' | '<' | '|' | '^' | '>' | + '==' | '!=' | '<=' | '>=' | '<' | '>' | + '<<' | '>>' | '||' | '&&' | '&=' | '|=' | '^=' | + '<<=' | '>>=' | '+=' | '-=' | '*=' | '/=' | '%='; + +INT_LIT: ('+' | '-')? [0-9]+; +DECIMAL_LIT: ('+' | '-')* [0-9]+ '.' [0-9]+; +BOOL_LIT: 'true' | 'false'; +StringLit: '"' CharSeq '"'; + +fragment CharSeq: Char+; +fragment Char: ~["\\\r\n] + | '\\' ['"?abfnrtv\\] + | '\\\n' + | '\\\r\n' + ; + NAME: ([a-z] | [A-Z] | [0-9])+; WS: [ \t\r\n]+ -> skip; NEWLINE: [\r\n]+; +COMMENT: '//' .*? '\n' -> skip;