program -> sourceFile* EOP ; sourceFile -> moduleDecl ( declaration | useStmt )* EOF ; moduleDecl -> "module" IDENTIFIER ";" ; useStmt -> "use" IDENTIFIER ";" ; // Top-level declarations declaration -> funDecl | structDecl | varDecl ; funDecl -> "fn" type IDENTIFIER "(" parameters? ")" block ; structDecl -> "struct" IDENTIFIER "{" structMember* "}" ; structMember -> fieldDecl | methodDecl ; fieldDecl -> type IDENTIFIER ";" ; methodDecl -> "method" type IDENTIFIER "(" parameters? ")" block ; // Types // Built-in refs such as "int&" are single lexer tokens. Named types can // carry a module qualifier. Attached struct refs/pointers such as "Vec3&" // and "Vec3*" are identifier tokens whose suffix is separated by the parser. // Named reference/pointer suffixes must be attached to the identifier. // Named types resolve through the declaring module and the file's imports. // Inline array sizes are integer literals from 0 to 32767. type -> baseType arraySuffix? ; baseType -> "int" | "float" | "double" | "bool" | "null" | "int&" | "float&" | "double&" | "bool&" | namedType ; namedType -> IDENTIFIER ( "::" IDENTIFIER )? ( "&" | "*" )? ; arraySuffix -> "[" INTEGER "]" | "[" "]" ( "&" | "*" ) ; parameters -> parameter ( "," parameter )* ; parameter -> ( "in" | "inout" )? type IDENTIFIER ; // Statements statement -> echoStmt | block | ifStmt | whileStmt | returnStmt | exprStmt ; block -> "{" blockItem* "}" ; blockItem -> varDecl | statement ; varDecl -> type IDENTIFIER ( "=" expression )? ";" ; echoStmt -> "echo" expression ";" ; exprStmt -> expression ";" ; ifStmt -> "if" "(" expression ")" block ( "else" block )? ; whileStmt -> "while" "(" expression ")" block ; returnStmt -> "return" expression? ";" ; // Expressions, written by precedence from lowest to highest. expression -> assignment ; assignment -> asExpr ( "=" asExpr )* ; asExpr -> logic_or ( "as" type )* ; logic_or -> logic_and ( "or" logic_and )* ; logic_and -> equality ( "and" equality )* ; equality -> comparison ( ( "!=" | "==" ) comparison )* ; comparison -> term ( ( ">" | ">=" | "<" | "<=" ) term )* ; term -> factor ( ( "-" | "+" ) factor )* ; factor -> unary ( ( "/" | "*" ) unary )* ; unary -> ( "!" | "-" ) unary | call ; call -> primary ( "(" arguments? ")" | "." IDENTIFIER | "[" expression "]" )* ; primary -> "true" | "false" | "null" | "this" | INTEGER | FLOAT | DOUBLE | STRING_LITERAL | IDENTIFIER ( "::" IDENTIFIER )? | newExpr | "(" expression ")" ; // Heap array allocation sizes are expressions, not part of the array type. newExpr -> "new" baseType ( "{" expression "}" | "[" expression "]" ( "&" | "*" ) ) ; arguments -> argument ( "," argument )* ; argument -> ( "in" | "inout" )? expression ; // Not currently parsed despite older grammar entries: // top-level method declarations, for statements, struct literals.