| ... | ... | @@ -55,242 +55,356 @@ pub fn parse(allocator: *Allocator, source: []const u8) !*Tree { |
| 55 | 55 | } |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | | tree.root_node = try parseRoot(arena, &it, tree); |
| 58 | var parser = Parser{ |
| 59 | .arena = arena, |
| 60 | .it = &it, |
| 61 | .tree = tree, |
| 62 | }; |
| 63 | |
| 64 | tree.root_node = try parser.root(); |
| 59 | 65 | return tree; |
| 60 | 66 | } |
| 61 | 67 | |
| 62 | | /// Root <- ExternalDeclaration* eof |
| 63 | | fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!*Node { |
| 64 | | const node = try arena.create(ast.Root); |
| 65 | | node.* = .{ |
| 66 | | .decls = ast.Node.DeclList.init(arena), |
| 67 | | .eof_token = undefined, |
| 68 | | }; |
| 69 | | while (parseExternalDeclarations(arena, it, tree) catch |err| switch (err) { |
| 70 | | error.OutOfMemory => return error.OutOfMemory, |
| 71 | | error.ParseError => return node, |
| 72 | | }) |decl| { |
| 73 | | try node.decls.push(decl); |
| 74 | | } |
| 75 | | node.eof_token = eatToken(it, .Eof) orelse { |
| 76 | | try tree.errors.push(.{ |
| 77 | | .ExpectedDecl = .{ .token = it.index }, |
| 78 | | }); |
| 68 | const Parser = struct { |
| 69 | arena: *Allocator, |
| 70 | it: *TokenIterator, |
| 71 | tree: *Tree, |
| 72 | |
| 73 | /// Root <- ExternalDeclaration* eof |
| 74 | fn root(parser: *Parser) Allocator.Error!*Node { |
| 75 | const node = try arena.create(ast.Root); |
| 76 | node.* = .{ |
| 77 | .decls = ast.Node.DeclList.init(arena), |
| 78 | .eof = undefined, |
| 79 | }; |
| 80 | while (parser.externalDeclarations() catch |err| switch (err) { |
| 81 | error.OutOfMemory => return error.OutOfMemory, |
| 82 | error.ParseError => return node, |
| 83 | }) |decl| { |
| 84 | try node.decls.push(decl); |
| 85 | } |
| 86 | node.eof = eatToken(it, .Eof) orelse { |
| 87 | try tree.errors.push(.{ |
| 88 | .ExpectedDecl = .{ .token = it.index }, |
| 89 | }); |
| 90 | return node; |
| 91 | }; |
| 79 | 92 | return node; |
| 80 | | }; |
| 81 | | return node; |
| 82 | | } |
| 93 | } |
| 83 | 94 | |
| 84 | | /// ExternalDeclaration |
| 85 | | /// <- Declaration |
| 86 | | /// / DeclarationSpecifiers Declarator Declaration* CompoundStmt |
| 87 | | fn parseExternalDeclarations(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 88 | | if (try parseDeclaration(arena, it, tree)) |decl| {} |
| 89 | | return null; |
| 90 | | } |
| 95 | /// ExternalDeclaration |
| 96 | /// <- Declaration |
| 97 | /// / DeclarationSpecifiers Declarator Declaration* CompoundStmt |
| 98 | fn externalDeclarations(parser: *Parser) !?*Node { |
| 99 | if (try Declaration(parser)) |decl| {} |
| 100 | return null; |
| 101 | } |
| 102 | |
| 103 | /// Declaration |
| 104 | /// <- DeclarationSpecifiers (Declarator (EQUAL Initializer)?)* SEMICOLON |
| 105 | /// \ StaticAssertDeclaration |
| 106 | fn declaration(parser: *Parser) !?*Node {} |
| 107 | |
| 108 | /// StaticAssertDeclaration <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON |
| 109 | fn staticAssertDeclaration(parser: *Parser) !?*Node {} |
| 110 | |
| 111 | /// DeclarationSpecifiers |
| 112 | /// <- StorageClassSpecifier DeclarationSpecifiers? |
| 113 | /// / TypeSpecifier DeclarationSpecifiers? |
| 114 | /// / TypeQualifier DeclarationSpecifiers? |
| 115 | /// / FunctionSpecifier DeclarationSpecifiers? |
| 116 | /// / AlignmentSpecifier DeclarationSpecifiers? |
| 117 | fn declarationSpecifiers(parser: *Parser) !*Node {} |
| 118 | |
| 119 | /// StorageClassSpecifier |
| 120 | /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register |
| 121 | fn storageClassSpecifier(parser: *Parser) !*Node {} |
| 122 | |
| 123 | /// TypeSpecifier |
| 124 | /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double |
| 125 | /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary / |
| 126 | /// / Keyword_atomic LPAREN TypeName RPAREN |
| 127 | /// / EnumSpecifier |
| 128 | /// / RecordSpecifier |
| 129 | /// / IDENTIFIER // typedef name |
| 130 | fn typeSpecifier(parser: *Parser) !*Node {} |
| 131 | |
| 132 | /// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic |
| 133 | fn typeQualifier(parser: *Parser) !*Node {} |
| 134 | |
| 135 | /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn |
| 136 | fn functionSpecifier(parser: *Parser) !*Node {} |
| 91 | 137 | |
| 92 | | /// Declaration |
| 93 | | /// <- DeclarationSpecifiers (Declarator (EQUAL Initializer)?)* SEMICOLON |
| 94 | | /// \ StaticAssertDeclaration |
| 95 | | fn parseDeclaration(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {} |
| 96 | | |
| 97 | | /// StaticAssertDeclaration <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON |
| 98 | | fn parseStaticAssertDeclaration(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {} |
| 99 | | |
| 100 | | /// DeclarationSpecifiers |
| 101 | | /// <- StorageClassSpecifier DeclarationSpecifiers? |
| 102 | | /// / TypeSpecifier DeclarationSpecifiers? |
| 103 | | /// / TypeQualifier DeclarationSpecifiers? |
| 104 | | /// / FunctionSpecifier DeclarationSpecifiers? |
| 105 | | /// / AlignmentSpecifier DeclarationSpecifiers? |
| 106 | | fn parseDeclarationSpecifiers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 107 | | |
| 108 | | /// StorageClassSpecifier |
| 109 | | /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register |
| 110 | | fn parseStorageClassSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 111 | | |
| 112 | | /// TypeSpecifier |
| 113 | | /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double |
| 114 | | /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary / |
| 115 | | /// / Keyword_atomic LPAREN TypeName RPAREN |
| 116 | | /// / EnumSpecifier |
| 117 | | /// / RecordSpecifier |
| 118 | | /// / IDENTIFIER // typedef name |
| 119 | | fn parseTypeSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 138 | /// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN |
| 139 | fn alignmentSpecifier(parser: *Parser) !*Node {} |
| 120 | 140 | |
| 121 | | /// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic |
| 122 | | fn parseTypeQualifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 141 | /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? |
| 142 | fn enumSpecifier(parser: *Parser) !*Node {} |
| 123 | 143 | |
| 124 | | /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn |
| 125 | | fn parseFunctionSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 144 | /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA? |
| 145 | fn enumField(parser: *Parser) !*Node {} |
| 126 | 146 | |
| 127 | | /// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN |
| 128 | | fn parseAlignmentSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 147 | /// RecordSpecifier <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)? |
| 148 | fn recordSpecifier(parser: *Parser) !*Node {} |
| 149 | |
| 150 | /// RecordField |
| 151 | /// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON |
| 152 | /// \ StaticAssertDeclaration |
| 153 | fn recordField(parser: *Parser) !*Node {} |
| 154 | |
| 155 | /// TypeName |
| 156 | /// <- SpecifierQualifer AbstractDeclarator? |
| 157 | fn typeName(parser: *Parser) !*Node {} |
| 158 | |
| 159 | /// SpecifierQualifer |
| 160 | /// <- TypeSpecifier SpecifierQualifer? |
| 161 | /// / TypeQualifier SpecifierQualifer? |
| 162 | fn specifierQualifer(parser: *Parser) !*Node {} |
| 163 | |
| 164 | /// RecordDeclarator <- Declarator? (COLON ConstExpr)? |
| 165 | fn recordDeclarator(parser: *Parser) !*Node {} |
| 166 | |
| 167 | /// Declarator <- Pointer? DirectDeclarator |
| 168 | fn declarator(parser: *Parser) !*Node {} |
| 169 | |
| 170 | /// Pointer <- ASTERISK TypeQualifier* Pointer? |
| 171 | fn pointer(parser: *Parser) !*Node {} |
| 172 | |
| 173 | /// DirectDeclarator |
| 174 | /// <- IDENTIFIER |
| 175 | /// / LPAREN Declarator RPAREN |
| 176 | /// / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET |
| 177 | /// / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN |
| 178 | fn directDeclarator(parser: *Parser) !*Node {} |
| 179 | |
| 180 | /// BracketDeclarator |
| 181 | /// <- Keyword_static TypeQualifier* AssignmentExpr |
| 182 | /// / TypeQualifier+ (ASTERISK / Keyword_static AssignmentExpr) |
| 183 | /// / TypeQualifier+ AssignmentExpr? |
| 184 | /// / AssignmentExpr |
| 185 | fn bracketDeclarator(parser: *Parser) !*Node {} |
| 186 | |
| 187 | /// ParamDecl <- DeclarationSpecifiers (Declarator / AbstractDeclarator) |
| 188 | fn paramDecl(parser: *Parser) !*Node {} |
| 189 | |
| 190 | /// AbstractDeclarator <- Pointer? DirectAbstractDeclarator? |
| 191 | fn abstractDeclarator(parser: *Parser) !*Node {} |
| 192 | |
| 193 | /// DirectAbstractDeclarator |
| 194 | /// <- IDENTIFIER |
| 195 | /// / LPAREN DirectAbstractDeclarator RPAREN |
| 196 | /// / DirectAbstractDeclarator? LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET |
| 197 | /// / DirectAbstractDeclarator? LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN |
| 198 | fn directAbstractDeclarator(parser: *Parser) !*Node {} |
| 199 | |
| 200 | /// Expr <- AssignmentExpr (COMMA Expr)* |
| 201 | fn expr(parser: *Parser) !*Node {} |
| 202 | |
| 203 | /// AssignmentExpr |
| 204 | /// <- ConditionalExpr // TODO recursive? |
| 205 | /// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA / |
| 206 | /// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL / |
| 207 | /// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr |
| 208 | fn assignmentExpr(parser: *Parser) !*Node {} |
| 209 | |
| 210 | /// ConstExpr <- ConditionalExpr |
| 211 | /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)? |
| 212 | fn conditionalExpr(parser: *Parser) !*Node {} |
| 213 | |
| 214 | /// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)* |
| 215 | fn logicalOrExpr(parser: *Parser) !*Node {} |
| 216 | |
| 217 | /// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)* |
| 218 | fn logicalAndExpr(parser: *Parser) !*Node {} |
| 219 | |
| 220 | /// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)* |
| 221 | fn binOrExpr(parser: *Parser) !*Node {} |
| 222 | |
| 223 | /// BinXorExpr <- BinAndExpr (CARET BinXorExpr)* |
| 224 | fn binXorExpr(parser: *Parser) !*Node {} |
| 225 | |
| 226 | /// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)* |
| 227 | fn binAndExpr(parser: *Parser) !*Node {} |
| 228 | |
| 229 | /// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)* |
| 230 | fn equalityExpr(parser: *Parser) !*Node {} |
| 231 | |
| 232 | /// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)* |
| 233 | fn comparisionExpr(parser: *Parser) !*Node {} |
| 234 | |
| 235 | /// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)* |
| 236 | fn shiftExpr(parser: *Parser) !*Node {} |
| 237 | |
| 238 | /// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)* |
| 239 | fn additiveExpr(parser: *Parser) !*Node {} |
| 240 | |
| 241 | /// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)* |
| 242 | fn multiplicativeExpr(parser: *Parser) !*Node {} |
| 243 | |
| 244 | /// UnaryExpr |
| 245 | /// <- LPAREN TypeName RPAREN UnaryExpr |
| 246 | /// / Keyword_sizeof LAPERN TypeName RPAREN |
| 247 | /// / Keyword_sizeof UnaryExpr |
| 248 | /// / Keyword_alignof LAPERN TypeName RPAREN |
| 249 | /// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr |
| 250 | /// / PrimaryExpr PostFixExpr* |
| 251 | fn unaryExpr(parser: *Parser) !*Node {} |
| 252 | |
| 253 | /// PrimaryExpr |
| 254 | /// <- IDENTIFIER |
| 255 | /// / INTEGERLITERAL / FLITERAL / STRINGLITERAL / CHARLITERAL |
| 256 | /// / LPAREN Expr RPAREN |
| 257 | /// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN |
| 258 | fn primaryExpr(parser: *Parser) !*Node {} |
| 259 | |
| 260 | /// Generic |
| 261 | /// <- TypeName COLON AssignmentExpr |
| 262 | /// / Keyword_default COLON AssignmentExpr |
| 263 | fn generic(parser: *Parser) !*Node {} |
| 264 | |
| 265 | /// PostFixExpr |
| 266 | /// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE |
| 267 | /// / LBRACKET Expr RBRACKET |
| 268 | /// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN |
| 269 | /// / (PERIOD / ARROW) IDENTIFIER |
| 270 | /// / (PLUSPLUS / MINUSMINUS) |
| 271 | fn postFixExpr(parser: *Parser) !*Node {} |
| 272 | |
| 273 | /// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA? |
| 274 | fn initializers(parser: *Parser) !*Node {} |
| 275 | |
| 276 | /// Initializer |
| 277 | /// <- LBRACE Initializers RBRACE |
| 278 | /// / AssignmentExpr |
| 279 | fn initializer(parser: *Parser) !*Node {} |
| 280 | |
| 281 | /// Designator |
| 282 | /// <- LBRACKET Initializers RBRACKET |
| 283 | /// / PERIOD IDENTIFIER |
| 284 | fn designator(parser: *Parser) !*Node {} |
| 285 | |
| 286 | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE |
| 287 | fn compoundStmt(parser: *Parser) !?*Node {} |
| 288 | |
| 289 | /// Stmt |
| 290 | /// <- CompoundStmt |
| 291 | /// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)? |
| 292 | /// / Keyword_switch LPAREN Expr RPAREN Stmt |
| 293 | /// / Keyword_while LPAREN Expr RPAREN Stmt |
| 294 | /// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON |
| 295 | /// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt |
| 296 | /// / Keyword_default COLON Stmt |
| 297 | /// / Keyword_case ConstExpr COLON Stmt |
| 298 | /// / Keyword_goto IDENTIFIER SEMICOLON |
| 299 | /// / Keyword_continue SEMICOLON |
| 300 | /// / Keyword_break SEMICOLON |
| 301 | /// / Keyword_return Expr? SEMICOLON |
| 302 | /// / IDENTIFIER COLON Stmt |
| 303 | /// / ExprStmt |
| 304 | fn stmt(parser: *Parser) !?*Node { |
| 305 | if (parser.compoundStmt()) |node| return node; |
| 306 | // if (parser.eatToken(.Keyword_if)) |tok| {} |
| 307 | // if (parser.eatToken(.Keyword_switch)) |tok| {} |
| 308 | // if (parser.eatToken(.Keyword_while)) |tok| {} |
| 309 | // if (parser.eatToken(.Keyword_do)) |tok| {} |
| 310 | // if (parser.eatToken(.Keyword_for)) |tok| {} |
| 311 | // if (parser.eatToken(.Keyword_default)) |tok| {} |
| 312 | // if (parser.eatToken(.Keyword_case)) |tok| {} |
| 313 | if (parser.eatToken(.Keyword_goto)) |tok| { |
| 314 | const node = try parser.arena.create(Node.JumpStmt); |
| 315 | node.* = .{ |
| 316 | .ltoken = tok, |
| 317 | .kind = .Goto, |
| 318 | .semicolon = parser.expectToken(.Semicolon), |
| 319 | }; |
| 320 | return &node.base; |
| 321 | } |
| 322 | if (parser.eatToken(.Keyword_continue)) |tok| { |
| 323 | const node = try parser.arena.create(Node.JumpStmt); |
| 324 | node.* = .{ |
| 325 | .ltoken = tok, |
| 326 | .kind = .Continue, |
| 327 | .semicolon = parser.expectToken(.Semicolon), |
| 328 | }; |
| 329 | return &node.base; |
| 330 | } |
| 331 | if (parser.eatToken(.Keyword_break)) |tok| { |
| 332 | const node = try parser.arena.create(Node.JumpStmt); |
| 333 | node.* = .{ |
| 334 | .ltoken = tok, |
| 335 | .kind = .Break, |
| 336 | .semicolon = parser.expectToken(.Semicolon), |
| 337 | }; |
| 338 | return &node.base; |
| 339 | } |
| 340 | if (parser.eatToken(.Keyword_return)) |tok| { |
| 341 | const node = try parser.arena.create(Node.JumpStmt); |
| 342 | node.* = .{ |
| 343 | .ltoken = tok, |
| 344 | .kind = .{ .Return = try parser.expr() }, |
| 345 | .semicolon = parser.expectToken(.Semicolon), |
| 346 | }; |
| 347 | return &node.base; |
| 348 | } |
| 349 | if (parser.eatToken(.Identifier)) |tok| { |
| 350 | if (parser.eatToken(.Colon)) |col| { |
| 351 | const node = try parser.arena.create(Node.Label); |
| 352 | node.* = .{ |
| 353 | .identifier = tok, |
| 354 | .semicolon = parser.expectToken(.Colon), |
| 355 | }; |
| 356 | return &node.base; |
| 357 | } |
| 358 | putBackToken(tok); |
| 359 | } |
| 360 | if (parser.exprStmt()) |node| return node; |
| 361 | return null; |
| 362 | } |
| 129 | 363 | |
| 130 | | /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? |
| 131 | | fn parseEnumSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 364 | /// ExprStmt <- Expr? SEMICOLON |
| 365 | fn exprStmt(parser: *Parser) !*Node { |
| 366 | const node = try parser.arena.create(Node.ExprStmt); |
| 367 | node.* = .{ |
| 368 | .expr = try parser.expr(), |
| 369 | .semicolon = parser.expectToken(.Semicolon), |
| 370 | }; |
| 371 | return &node.base; |
| 372 | } |
| 132 | 373 | |
| 133 | | /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA? |
| 134 | | fn parseEnumField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 374 | fn eatToken(parser: *Parser, id: Token.Id) ?TokenIndex { |
| 375 | while (true) { |
| 376 | const next_tok = parser.it.next() orelse return null; |
| 377 | if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) { |
| 378 | if (next_tok.id == id) { |
| 379 | return parser.it.index; |
| 380 | } |
| 381 | parser.it.prev(); |
| 382 | return null; |
| 383 | } |
| 384 | } |
| 385 | } |
| 135 | 386 | |
| 136 | | /// RecordSpecifier <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)? |
| 137 | | fn parseRecordSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 138 | | |
| 139 | | /// RecordField |
| 140 | | /// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON |
| 141 | | /// \ StaticAssertDeclaration |
| 142 | | fn parseRecordField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 143 | | |
| 144 | | /// TypeName |
| 145 | | /// <- SpecifierQualifer AbstractDeclarator? |
| 146 | | fn parseTypeName(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 147 | | |
| 148 | | /// SpecifierQualifer |
| 149 | | /// <- TypeSpecifier SpecifierQualifer? |
| 150 | | /// / TypeQualifier SpecifierQualifer? |
| 151 | | fn parseSpecifierQualifer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 152 | | |
| 153 | | /// RecordDeclarator <- Declarator? (COLON ConstExpr)? |
| 154 | | fn parseRecordDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 155 | | |
| 156 | | /// Declarator <- Pointer? DirectDeclarator |
| 157 | | fn parseDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 158 | | |
| 159 | | /// Pointer <- ASTERISK TypeQualifier* Pointer? |
| 160 | | fn parsePointer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 161 | | |
| 162 | | /// DirectDeclarator |
| 163 | | /// <- IDENTIFIER |
| 164 | | /// / LPAREN Declarator RPAREN |
| 165 | | /// / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET |
| 166 | | /// / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN |
| 167 | | fn parseDirectDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 168 | | |
| 169 | | /// BracketDeclarator |
| 170 | | /// <- Keyword_static TypeQualifier* AssignmentExpr |
| 171 | | /// / TypeQualifier+ (ASTERISK / Keyword_static AssignmentExpr) |
| 172 | | /// / TypeQualifier+ AssignmentExpr? |
| 173 | | /// / AssignmentExpr |
| 174 | | fn parseBracketDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 175 | | |
| 176 | | /// ParamDecl <- DeclarationSpecifiers (Declarator / AbstractDeclarator) |
| 177 | | fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 178 | | |
| 179 | | /// AbstractDeclarator <- Pointer? DirectAbstractDeclarator? |
| 180 | | fn parseAbstractDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 181 | | |
| 182 | | /// DirectAbstractDeclarator |
| 183 | | /// <- IDENTIFIER |
| 184 | | /// / LPAREN DirectAbstractDeclarator RPAREN |
| 185 | | /// / DirectAbstractDeclarator? LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET |
| 186 | | /// / DirectAbstractDeclarator? LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN |
| 187 | | fn parseDirectAbstractDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 188 | | |
| 189 | | /// Expr <- AssignmentExpr (COMMA Expr)* |
| 190 | | fn parseExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 191 | | |
| 192 | | /// AssignmentExpr |
| 193 | | /// <- ConditionalExpr |
| 194 | | /// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA / |
| 195 | | /// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL / |
| 196 | | /// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr |
| 197 | | fn parseAssignmentExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 198 | | |
| 199 | | /// ConstExpr <- ConditionalExpr |
| 200 | | /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)? |
| 201 | | fn parseConditionalExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 202 | | |
| 203 | | /// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)* |
| 204 | | fn parseLogicalOrExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 205 | | |
| 206 | | /// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)* |
| 207 | | fn parseLogicalAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 208 | | |
| 209 | | /// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)* |
| 210 | | fn parseBinOrExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 211 | | |
| 212 | | /// BinXorExpr <- BinAndExpr (CARET BinXorExpr)* |
| 213 | | fn parseBinXorExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 214 | | |
| 215 | | /// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)* |
| 216 | | fn parseBinAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 217 | | |
| 218 | | /// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)* |
| 219 | | fn parseEqualityExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 220 | | |
| 221 | | /// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)* |
| 222 | | fn parseComparisionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 223 | | |
| 224 | | /// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)* |
| 225 | | fn parseShiftExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 226 | | |
| 227 | | /// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)* |
| 228 | | fn parseAdditiveExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 229 | | |
| 230 | | /// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)* |
| 231 | | fn parseMultiplicativeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 232 | | |
| 233 | | /// UnaryExpr |
| 234 | | /// <- LPAREN TypeName RPAREN UnaryExpr |
| 235 | | /// / Keyword_sizeof LAPERN TypeName RPAREN |
| 236 | | /// / Keyword_sizeof UnaryExpr |
| 237 | | /// / Keyword_alignof LAPERN TypeName RPAREN |
| 238 | | /// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr |
| 239 | | /// / PrimaryExpr PostFixExpr* |
| 240 | | fn parseUnaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 241 | | |
| 242 | | /// PrimaryExpr |
| 243 | | /// <- IDENTIFIER |
| 244 | | /// / INTEGERLITERAL / FLITERAL / STRINGLITERAL / CHARLITERAL |
| 245 | | /// / LPAREN Expr RPAREN |
| 246 | | /// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN |
| 247 | | fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 248 | | |
| 249 | | /// Generic |
| 250 | | /// <- TypeName COLON AssignmentExpr |
| 251 | | /// / Keyword_default COLON AssignmentExpr |
| 252 | | fn parseGeneric(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 253 | | |
| 254 | | /// PostFixExpr |
| 255 | | /// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE |
| 256 | | /// / LBRACKET Expr RBRACKET |
| 257 | | /// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN |
| 258 | | /// / (PERIOD / ARROW) IDENTIFIER |
| 259 | | /// / (PLUSPLUS / MINUSMINUS) |
| 260 | | fn parsePostFixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 261 | | |
| 262 | | /// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA? |
| 263 | | fn parseInitializers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 264 | | |
| 265 | | /// Initializer |
| 266 | | /// <- LBRACE Initializers RBRACE |
| 267 | | /// / AssignmentExpr |
| 268 | | fn parseInitializer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 269 | | |
| 270 | | /// Designator |
| 271 | | /// <- LBRACKET Initializers RBRACKET |
| 272 | | /// / PERIOD IDENTIFIER |
| 273 | | fn parseDesignator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 274 | | |
| 275 | | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE |
| 276 | | fn parseCompoundStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 277 | | |
| 278 | | /// Stmt |
| 279 | | /// <- CompoundStmt |
| 280 | | /// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)? |
| 281 | | /// / Keyword_switch LPAREN Expr RPAREN Stmt |
| 282 | | /// / Keyword_while LPAREN Expr RPAREN Stmt |
| 283 | | /// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON |
| 284 | | /// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt |
| 285 | | /// / Keyword_default COLON Stmt |
| 286 | | /// / Keyword_case ConstExpr COLON Stmt |
| 287 | | /// / Keyword_goto IDENTIFIER SEMICOLON |
| 288 | | /// / Keyword_continue SEMICOLON |
| 289 | | /// / Keyword_break SEMICOLON |
| 290 | | /// / Keyword_return Expr? SEMICOLON |
| 291 | | /// / IDENTIFIER COLON Stmt |
| 292 | | /// / ExprStmt |
| 293 | | fn parseStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 294 | | |
| 295 | | /// ExprStmt <- Expr? SEMICOLON |
| 296 | | fn parseExprStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 387 | fn expectToken(parser: *Parser, id: Token.Id) Error!TokenIndex { |
| 388 | while (true) { |
| 389 | const next_tok = parser.it.next() orelse return error.ParseError; |
| 390 | if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) { |
| 391 | if (next_tok.id != id) { |
| 392 | try tree.errors.push(.{ |
| 393 | .ExpectedToken = .{ .token = parser.it.index, .expected_id = id }, |
| 394 | }); |
| 395 | return error.ParseError; |
| 396 | } |
| 397 | return parser.it.index; |
| 398 | } |
| 399 | } |
| 400 | } |
| 401 | |
| 402 | fn putBackToken(it: *TokenIterator, putting_back: TokenIndex) void { |
| 403 | while (true) { |
| 404 | const prev_tok = it.prev() orelse return; |
| 405 | if (next_tok.id == .LineComment or next_tok.id == .MultiLineComment) continue; |
| 406 | assert(it.list.at(putting_back) == prev_tok); |
| 407 | return; |
| 408 | } |
| 409 | } |
| 410 | }; |