| ... | ... | @@ -0,0 +1,296 @@ |
| 1 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; |
| 3 | const Allocator = std.mem.Allocator; |
| 4 | const ast = std.c.ast; |
| 5 | const Tree = ast.Tree; |
| 6 | const TokenIndex = ast.TokenIndex; |
| 7 | const Token = std.c.Token; |
| 8 | const TokenIterator = ast.Tree.TokenList.Iterator; |
| 9 | |
| 10 | pub const Error = error{ParseError} || Allocator.Error; |
| 11 | |
| 12 | /// Result should be freed with tree.deinit() when there are |
| 13 | /// no more references to any of the tokens or nodes. |
| 14 | pub fn parse(allocator: *Allocator, source: []const u8) !*Tree { |
| 15 | const tree = blk: { |
| 16 | // This block looks unnecessary, but is a "foot-shield" to prevent the SegmentedLists |
| 17 | // from being initialized with a pointer to this `arena`, which is created on |
| 18 | // the stack. Following code should instead refer to `&tree.arena_allocator`, a |
| 19 | // pointer to data which lives safely on the heap and will outlive `parse`. |
| 20 | var arena = std.heap.ArenaAllocator.init(allocator); |
| 21 | errdefer arena.deinit(); |
| 22 | const tree = try arena.allocator.create(ast.Tree); |
| 23 | tree.* = .{ |
| 24 | .root_node = undefined, |
| 25 | .arena_allocator = arena, |
| 26 | .tokens = undefined, |
| 27 | .sources = undefined, |
| 28 | }; |
| 29 | break :blk tree; |
| 30 | }; |
| 31 | errdefer tree.deinit(); |
| 32 | const arena = &tree.arena_allocator.allocator; |
| 33 | |
| 34 | tree.tokens = ast.Tree.TokenList.init(arena); |
| 35 | tree.sources = ast.Tree.SourceList.init(arena); |
| 36 | |
| 37 | var tokenizer = std.zig.Tokenizer.init(source); |
| 38 | while (true) { |
| 39 | const tree_token = try tree.tokens.addOne(); |
| 40 | tree_token.* = tokenizer.next(); |
| 41 | if (tree_token.id == .Eof) break; |
| 42 | } |
| 43 | // TODO preprocess here |
| 44 | var it = tree.tokens.iterator(0); |
| 45 | |
| 46 | while (true) { |
| 47 | const tok = it.peek().?.id; |
| 48 | switch (id) { |
| 49 | .LineComment, |
| 50 | .MultiLineComment, |
| 51 | => { |
| 52 | _ = it.next(); |
| 53 | }, |
| 54 | else => break, |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | tree.root_node = try parseRoot(arena, &it, tree); |
| 59 | return tree; |
| 60 | } |
| 61 | |
| 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 | }); |
| 79 | return node; |
| 80 | }; |
| 81 | return node; |
| 82 | } |
| 83 | |
| 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 | } |
| 91 | |
| 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 {} |
| 120 | |
| 121 | /// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic |
| 122 | fn parseTypeQualifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 123 | |
| 124 | /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn |
| 125 | fn parseFunctionSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 126 | |
| 127 | /// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN |
| 128 | fn parseAlignmentSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 129 | |
| 130 | /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? |
| 131 | fn parseEnumSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 132 | |
| 133 | /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA? |
| 134 | fn parseEnumField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {} |
| 135 | |
| 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 {} |