std-c outline parser
This commit is contained in:
parent
e1b01d32f0
commit
73a53fa263
@ -5,6 +5,7 @@ const page_size = std.mem.page_size;
|
||||
const tokenizer = @import("c/tokenizer.zig");
|
||||
pub const Token = tokenizer.Token;
|
||||
pub const Tokenizer = tokenizer.Tokenizer;
|
||||
pub const parse = @import("c/parse.zig").parse;
|
||||
pub const ast = @import("c/ast.zig");
|
||||
|
||||
pub usingnamespace @import("os/bits.zig");
|
||||
|
296
lib/std/c/parse.zig
Normal file
296
lib/std/c/parse.zig
Normal file
@ -0,0 +1,296 @@
|
||||
const std = @import("../std.zig");
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const ast = std.c.ast;
|
||||
const Tree = ast.Tree;
|
||||
const TokenIndex = ast.TokenIndex;
|
||||
const Token = std.c.Token;
|
||||
const TokenIterator = ast.Tree.TokenList.Iterator;
|
||||
|
||||
pub const Error = error{ParseError} || Allocator.Error;
|
||||
|
||||
/// Result should be freed with tree.deinit() when there are
|
||||
/// no more references to any of the tokens or nodes.
|
||||
pub fn parse(allocator: *Allocator, source: []const u8) !*Tree {
|
||||
const tree = blk: {
|
||||
// This block looks unnecessary, but is a "foot-shield" to prevent the SegmentedLists
|
||||
// from being initialized with a pointer to this `arena`, which is created on
|
||||
// the stack. Following code should instead refer to `&tree.arena_allocator`, a
|
||||
// pointer to data which lives safely on the heap and will outlive `parse`.
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
errdefer arena.deinit();
|
||||
const tree = try arena.allocator.create(ast.Tree);
|
||||
tree.* = .{
|
||||
.root_node = undefined,
|
||||
.arena_allocator = arena,
|
||||
.tokens = undefined,
|
||||
.sources = undefined,
|
||||
};
|
||||
break :blk tree;
|
||||
};
|
||||
errdefer tree.deinit();
|
||||
const arena = &tree.arena_allocator.allocator;
|
||||
|
||||
tree.tokens = ast.Tree.TokenList.init(arena);
|
||||
tree.sources = ast.Tree.SourceList.init(arena);
|
||||
|
||||
var tokenizer = std.zig.Tokenizer.init(source);
|
||||
while (true) {
|
||||
const tree_token = try tree.tokens.addOne();
|
||||
tree_token.* = tokenizer.next();
|
||||
if (tree_token.id == .Eof) break;
|
||||
}
|
||||
// TODO preprocess here
|
||||
var it = tree.tokens.iterator(0);
|
||||
|
||||
while (true) {
|
||||
const tok = it.peek().?.id;
|
||||
switch (id) {
|
||||
.LineComment,
|
||||
.MultiLineComment,
|
||||
=> {
|
||||
_ = it.next();
|
||||
},
|
||||
else => break,
|
||||
}
|
||||
}
|
||||
|
||||
tree.root_node = try parseRoot(arena, &it, tree);
|
||||
return tree;
|
||||
}
|
||||
|
||||
/// Root <- ExternalDeclaration* eof
|
||||
fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!*Node {
|
||||
const node = try arena.create(ast.Root);
|
||||
node.* = .{
|
||||
.decls = ast.Node.DeclList.init(arena),
|
||||
.eof_token = undefined,
|
||||
};
|
||||
while (parseExternalDeclarations(arena, it, tree) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.ParseError => return node,
|
||||
}) |decl| {
|
||||
try node.decls.push(decl);
|
||||
}
|
||||
node.eof_token = eatToken(it, .Eof) orelse {
|
||||
try tree.errors.push(.{
|
||||
.ExpectedDecl = .{ .token = it.index },
|
||||
});
|
||||
return node;
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
/// ExternalDeclaration
|
||||
/// <- Declaration
|
||||
/// / DeclarationSpecifiers Declarator Declaration* CompoundStmt
|
||||
fn parseExternalDeclarations(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||
if (try parseDeclaration(arena, it, tree)) |decl| {}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Declaration
|
||||
/// <- DeclarationSpecifiers (Declarator (EQUAL Initializer)?)* SEMICOLON
|
||||
/// \ StaticAssertDeclaration
|
||||
fn parseDeclaration(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {}
|
||||
|
||||
/// StaticAssertDeclaration <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
|
||||
fn parseStaticAssertDeclaration(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {}
|
||||
|
||||
/// DeclarationSpecifiers
|
||||
/// <- StorageClassSpecifier DeclarationSpecifiers?
|
||||
/// / TypeSpecifier DeclarationSpecifiers?
|
||||
/// / TypeQualifier DeclarationSpecifiers?
|
||||
/// / FunctionSpecifier DeclarationSpecifiers?
|
||||
/// / AlignmentSpecifier DeclarationSpecifiers?
|
||||
fn parseDeclarationSpecifiers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// StorageClassSpecifier
|
||||
/// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
|
||||
fn parseStorageClassSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// TypeSpecifier
|
||||
/// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double
|
||||
/// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary /
|
||||
/// / Keyword_atomic LPAREN TypeName RPAREN
|
||||
/// / EnumSpecifier
|
||||
/// / RecordSpecifier
|
||||
/// / IDENTIFIER // typedef name
|
||||
fn parseTypeSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
|
||||
fn parseTypeQualifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// FunctionSpecifier <- Keyword_inline / Keyword_noreturn
|
||||
fn parseFunctionSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN
|
||||
fn parseAlignmentSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
|
||||
fn parseEnumSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA?
|
||||
fn parseEnumField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// RecordSpecifier <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)?
|
||||
fn parseRecordSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// RecordField
|
||||
/// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
|
||||
/// \ StaticAssertDeclaration
|
||||
fn parseRecordField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// TypeName
|
||||
/// <- SpecifierQualifer AbstractDeclarator?
|
||||
fn parseTypeName(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// SpecifierQualifer
|
||||
/// <- TypeSpecifier SpecifierQualifer?
|
||||
/// / TypeQualifier SpecifierQualifer?
|
||||
fn parseSpecifierQualifer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// RecordDeclarator <- Declarator? (COLON ConstExpr)?
|
||||
fn parseRecordDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Declarator <- Pointer? DirectDeclarator
|
||||
fn parseDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Pointer <- ASTERISK TypeQualifier* Pointer?
|
||||
fn parsePointer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// DirectDeclarator
|
||||
/// <- IDENTIFIER
|
||||
/// / LPAREN Declarator RPAREN
|
||||
/// / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
|
||||
/// / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
|
||||
fn parseDirectDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// BracketDeclarator
|
||||
/// <- Keyword_static TypeQualifier* AssignmentExpr
|
||||
/// / TypeQualifier+ (ASTERISK / Keyword_static AssignmentExpr)
|
||||
/// / TypeQualifier+ AssignmentExpr?
|
||||
/// / AssignmentExpr
|
||||
fn parseBracketDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// ParamDecl <- DeclarationSpecifiers (Declarator / AbstractDeclarator)
|
||||
fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// AbstractDeclarator <- Pointer? DirectAbstractDeclarator?
|
||||
fn parseAbstractDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// DirectAbstractDeclarator
|
||||
/// <- IDENTIFIER
|
||||
/// / LPAREN DirectAbstractDeclarator RPAREN
|
||||
/// / DirectAbstractDeclarator? LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
|
||||
/// / DirectAbstractDeclarator? LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
|
||||
fn parseDirectAbstractDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Expr <- AssignmentExpr (COMMA Expr)*
|
||||
fn parseExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// AssignmentExpr
|
||||
/// <- ConditionalExpr
|
||||
/// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA /
|
||||
/// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL /
|
||||
/// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr
|
||||
fn parseAssignmentExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// ConstExpr <- ConditionalExpr
|
||||
/// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)?
|
||||
fn parseConditionalExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)*
|
||||
fn parseLogicalOrExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)*
|
||||
fn parseLogicalAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)*
|
||||
fn parseBinOrExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// BinXorExpr <- BinAndExpr (CARET BinXorExpr)*
|
||||
fn parseBinXorExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)*
|
||||
fn parseBinAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)*
|
||||
fn parseEqualityExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)*
|
||||
fn parseComparisionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)*
|
||||
fn parseShiftExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)*
|
||||
fn parseAdditiveExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)*
|
||||
fn parseMultiplicativeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// UnaryExpr
|
||||
/// <- LPAREN TypeName RPAREN UnaryExpr
|
||||
/// / Keyword_sizeof LAPERN TypeName RPAREN
|
||||
/// / Keyword_sizeof UnaryExpr
|
||||
/// / Keyword_alignof LAPERN TypeName RPAREN
|
||||
/// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr
|
||||
/// / PrimaryExpr PostFixExpr*
|
||||
fn parseUnaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// PrimaryExpr
|
||||
/// <- IDENTIFIER
|
||||
/// / INTEGERLITERAL / FLITERAL / STRINGLITERAL / CHARLITERAL
|
||||
/// / LPAREN Expr RPAREN
|
||||
/// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN
|
||||
fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Generic
|
||||
/// <- TypeName COLON AssignmentExpr
|
||||
/// / Keyword_default COLON AssignmentExpr
|
||||
fn parseGeneric(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// PostFixExpr
|
||||
/// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE
|
||||
/// / LBRACKET Expr RBRACKET
|
||||
/// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN
|
||||
/// / (PERIOD / ARROW) IDENTIFIER
|
||||
/// / (PLUSPLUS / MINUSMINUS)
|
||||
fn parsePostFixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA?
|
||||
fn parseInitializers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Initializer
|
||||
/// <- LBRACE Initializers RBRACE
|
||||
/// / AssignmentExpr
|
||||
fn parseInitializer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Designator
|
||||
/// <- LBRACKET Initializers RBRACKET
|
||||
/// / PERIOD IDENTIFIER
|
||||
fn parseDesignator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
|
||||
fn parseCompoundStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// Stmt
|
||||
/// <- CompoundStmt
|
||||
/// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)?
|
||||
/// / Keyword_switch LPAREN Expr RPAREN Stmt
|
||||
/// / Keyword_while LPAREN Expr RPAREN Stmt
|
||||
/// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON
|
||||
/// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt
|
||||
/// / Keyword_default COLON Stmt
|
||||
/// / Keyword_case ConstExpr COLON Stmt
|
||||
/// / Keyword_goto IDENTIFIER SEMICOLON
|
||||
/// / Keyword_continue SEMICOLON
|
||||
/// / Keyword_break SEMICOLON
|
||||
/// / Keyword_return Expr? SEMICOLON
|
||||
/// / IDENTIFIER COLON Stmt
|
||||
/// / ExprStmt
|
||||
fn parseStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
||||
|
||||
/// ExprStmt <- Expr? SEMICOLON
|
||||
fn parseExprStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
Loading…
x
Reference in New Issue
Block a user