std-c parser and ast organization
parent
73a53fa263
commit
a20c0b31de
|
@ -54,13 +54,47 @@ pub const Error = union(enum) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Root = struct {
|
pub const Node = struct {
|
||||||
decls: DeclList,
|
id: Id,
|
||||||
eof_token: TokenIndex,
|
|
||||||
|
|
||||||
pub const DeclList = SegmentedList(*Decl, 4);
|
pub const Id = enum {
|
||||||
|
Root,
|
||||||
|
JumpStmt,
|
||||||
|
ExprStmt,
|
||||||
|
Label,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Root = struct {
|
||||||
|
base: Node,
|
||||||
|
decls: DeclList,
|
||||||
|
eof: TokenIndex,
|
||||||
|
|
||||||
|
pub const DeclList = SegmentedList(*Node, 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const JumpStmt = struct {
|
||||||
|
base: Node = Node{ .id = .JumpStmt},
|
||||||
|
ltoken: TokenIndex,
|
||||||
|
kind: Kind,
|
||||||
|
semicolon: TokenIndex,
|
||||||
|
|
||||||
|
pub const Kind = union(enum) {
|
||||||
|
Break,
|
||||||
|
Continue,
|
||||||
|
Return: ?*Node,
|
||||||
|
Goto: TokenIndex,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ExprStmt = struct {
|
||||||
|
base: Node = Node{ .id = .ExprStmt},
|
||||||
|
expr: ?*Node,
|
||||||
|
semicolon: TokenIndex,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Label = struct {
|
||||||
|
base: Node = Node{ .id = .Label},
|
||||||
|
identifier: TokenIndex,
|
||||||
|
colon: TokenIndex,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Decl = struct {
|
|
||||||
|
|
||||||
};
|
|
|
@ -55,242 +55,356 @@ pub fn parse(allocator: *Allocator, source: []const u8) !*Tree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.root_node = try parseRoot(arena, &it, tree);
|
var parser = Parser{
|
||||||
|
.arena = arena,
|
||||||
|
.it = &it,
|
||||||
|
.tree = tree,
|
||||||
|
};
|
||||||
|
|
||||||
|
tree.root_node = try parser.root();
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Root <- ExternalDeclaration* eof
|
const Parser = struct {
|
||||||
fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!*Node {
|
arena: *Allocator,
|
||||||
const node = try arena.create(ast.Root);
|
it: *TokenIterator,
|
||||||
node.* = .{
|
tree: *Tree,
|
||||||
.decls = ast.Node.DeclList.init(arena),
|
|
||||||
.eof_token = undefined,
|
/// Root <- ExternalDeclaration* eof
|
||||||
};
|
fn root(parser: *Parser) Allocator.Error!*Node {
|
||||||
while (parseExternalDeclarations(arena, it, tree) catch |err| switch (err) {
|
const node = try arena.create(ast.Root);
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
node.* = .{
|
||||||
error.ParseError => return node,
|
.decls = ast.Node.DeclList.init(arena),
|
||||||
}) |decl| {
|
.eof = undefined,
|
||||||
try node.decls.push(decl);
|
};
|
||||||
}
|
while (parser.externalDeclarations() catch |err| switch (err) {
|
||||||
node.eof_token = eatToken(it, .Eof) orelse {
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
try tree.errors.push(.{
|
error.ParseError => return node,
|
||||||
.ExpectedDecl = .{ .token = it.index },
|
}) |decl| {
|
||||||
});
|
try node.decls.push(decl);
|
||||||
|
}
|
||||||
|
node.eof = eatToken(it, .Eof) orelse {
|
||||||
|
try tree.errors.push(.{
|
||||||
|
.ExpectedDecl = .{ .token = it.index },
|
||||||
|
});
|
||||||
|
return node;
|
||||||
|
};
|
||||||
return node;
|
return node;
|
||||||
};
|
}
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ExternalDeclaration
|
/// ExternalDeclaration
|
||||||
/// <- Declaration
|
/// <- Declaration
|
||||||
/// / DeclarationSpecifiers Declarator Declaration* CompoundStmt
|
/// / DeclarationSpecifiers Declarator Declaration* CompoundStmt
|
||||||
fn parseExternalDeclarations(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
fn externalDeclarations(parser: *Parser) !?*Node {
|
||||||
if (try parseDeclaration(arena, it, tree)) |decl| {}
|
if (try Declaration(parser)) |decl| {}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declaration
|
/// Declaration
|
||||||
/// <- DeclarationSpecifiers (Declarator (EQUAL Initializer)?)* SEMICOLON
|
/// <- DeclarationSpecifiers (Declarator (EQUAL Initializer)?)* SEMICOLON
|
||||||
/// \ StaticAssertDeclaration
|
/// \ StaticAssertDeclaration
|
||||||
fn parseDeclaration(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {}
|
fn declaration(parser: *Parser) !?*Node {}
|
||||||
|
|
||||||
/// StaticAssertDeclaration <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
|
/// StaticAssertDeclaration <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
|
||||||
fn parseStaticAssertDeclaration(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {}
|
fn staticAssertDeclaration(parser: *Parser) !?*Node {}
|
||||||
|
|
||||||
/// DeclarationSpecifiers
|
/// DeclarationSpecifiers
|
||||||
/// <- StorageClassSpecifier DeclarationSpecifiers?
|
/// <- StorageClassSpecifier DeclarationSpecifiers?
|
||||||
/// / TypeSpecifier DeclarationSpecifiers?
|
/// / TypeSpecifier DeclarationSpecifiers?
|
||||||
/// / TypeQualifier DeclarationSpecifiers?
|
/// / TypeQualifier DeclarationSpecifiers?
|
||||||
/// / FunctionSpecifier DeclarationSpecifiers?
|
/// / FunctionSpecifier DeclarationSpecifiers?
|
||||||
/// / AlignmentSpecifier DeclarationSpecifiers?
|
/// / AlignmentSpecifier DeclarationSpecifiers?
|
||||||
fn parseDeclarationSpecifiers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn declarationSpecifiers(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// StorageClassSpecifier
|
/// StorageClassSpecifier
|
||||||
/// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
|
/// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
|
||||||
fn parseStorageClassSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn storageClassSpecifier(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// TypeSpecifier
|
/// TypeSpecifier
|
||||||
/// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double
|
/// <- 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_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary /
|
||||||
/// / Keyword_atomic LPAREN TypeName RPAREN
|
/// / Keyword_atomic LPAREN TypeName RPAREN
|
||||||
/// / EnumSpecifier
|
/// / EnumSpecifier
|
||||||
/// / RecordSpecifier
|
/// / RecordSpecifier
|
||||||
/// / IDENTIFIER // typedef name
|
/// / IDENTIFIER // typedef name
|
||||||
fn parseTypeSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn typeSpecifier(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
|
/// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
|
||||||
fn parseTypeQualifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn typeQualifier(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// FunctionSpecifier <- Keyword_inline / Keyword_noreturn
|
/// FunctionSpecifier <- Keyword_inline / Keyword_noreturn
|
||||||
fn parseFunctionSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn functionSpecifier(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN
|
/// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN
|
||||||
fn parseAlignmentSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn alignmentSpecifier(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
|
/// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
|
||||||
fn parseEnumSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn enumSpecifier(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA?
|
/// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA?
|
||||||
fn parseEnumField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn enumField(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// RecordSpecifier <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)?
|
/// RecordSpecifier <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)?
|
||||||
fn parseRecordSpecifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn recordSpecifier(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// RecordField
|
/// RecordField
|
||||||
/// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
|
/// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
|
||||||
/// \ StaticAssertDeclaration
|
/// \ StaticAssertDeclaration
|
||||||
fn parseRecordField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn recordField(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// TypeName
|
/// TypeName
|
||||||
/// <- SpecifierQualifer AbstractDeclarator?
|
/// <- SpecifierQualifer AbstractDeclarator?
|
||||||
fn parseTypeName(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn typeName(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// SpecifierQualifer
|
/// SpecifierQualifer
|
||||||
/// <- TypeSpecifier SpecifierQualifer?
|
/// <- TypeSpecifier SpecifierQualifer?
|
||||||
/// / TypeQualifier SpecifierQualifer?
|
/// / TypeQualifier SpecifierQualifer?
|
||||||
fn parseSpecifierQualifer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn specifierQualifer(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// RecordDeclarator <- Declarator? (COLON ConstExpr)?
|
/// RecordDeclarator <- Declarator? (COLON ConstExpr)?
|
||||||
fn parseRecordDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn recordDeclarator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Declarator <- Pointer? DirectDeclarator
|
/// Declarator <- Pointer? DirectDeclarator
|
||||||
fn parseDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn declarator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Pointer <- ASTERISK TypeQualifier* Pointer?
|
/// Pointer <- ASTERISK TypeQualifier* Pointer?
|
||||||
fn parsePointer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn pointer(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// DirectDeclarator
|
/// DirectDeclarator
|
||||||
/// <- IDENTIFIER
|
/// <- IDENTIFIER
|
||||||
/// / LPAREN Declarator RPAREN
|
/// / LPAREN Declarator RPAREN
|
||||||
/// / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
|
/// / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
|
||||||
/// / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
|
/// / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
|
||||||
fn parseDirectDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn directDeclarator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// BracketDeclarator
|
/// BracketDeclarator
|
||||||
/// <- Keyword_static TypeQualifier* AssignmentExpr
|
/// <- Keyword_static TypeQualifier* AssignmentExpr
|
||||||
/// / TypeQualifier+ (ASTERISK / Keyword_static AssignmentExpr)
|
/// / TypeQualifier+ (ASTERISK / Keyword_static AssignmentExpr)
|
||||||
/// / TypeQualifier+ AssignmentExpr?
|
/// / TypeQualifier+ AssignmentExpr?
|
||||||
/// / AssignmentExpr
|
/// / AssignmentExpr
|
||||||
fn parseBracketDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn bracketDeclarator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// ParamDecl <- DeclarationSpecifiers (Declarator / AbstractDeclarator)
|
/// ParamDecl <- DeclarationSpecifiers (Declarator / AbstractDeclarator)
|
||||||
fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn paramDecl(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// AbstractDeclarator <- Pointer? DirectAbstractDeclarator?
|
/// AbstractDeclarator <- Pointer? DirectAbstractDeclarator?
|
||||||
fn parseAbstractDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn abstractDeclarator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// DirectAbstractDeclarator
|
/// DirectAbstractDeclarator
|
||||||
/// <- IDENTIFIER
|
/// <- IDENTIFIER
|
||||||
/// / LPAREN DirectAbstractDeclarator RPAREN
|
/// / LPAREN DirectAbstractDeclarator RPAREN
|
||||||
/// / DirectAbstractDeclarator? LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
|
/// / DirectAbstractDeclarator? LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
|
||||||
/// / DirectAbstractDeclarator? LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
|
/// / DirectAbstractDeclarator? LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
|
||||||
fn parseDirectAbstractDeclarator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn directAbstractDeclarator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Expr <- AssignmentExpr (COMMA Expr)*
|
/// Expr <- AssignmentExpr (COMMA Expr)*
|
||||||
fn parseExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn expr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// AssignmentExpr
|
/// AssignmentExpr
|
||||||
/// <- ConditionalExpr
|
/// <- ConditionalExpr // TODO recursive?
|
||||||
/// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA /
|
/// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA /
|
||||||
/// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL /
|
/// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL /
|
||||||
/// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr
|
/// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr
|
||||||
fn parseAssignmentExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn assignmentExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// ConstExpr <- ConditionalExpr
|
/// ConstExpr <- ConditionalExpr
|
||||||
/// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)?
|
/// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)?
|
||||||
fn parseConditionalExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn conditionalExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)*
|
/// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)*
|
||||||
fn parseLogicalOrExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn logicalOrExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)*
|
/// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)*
|
||||||
fn parseLogicalAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn logicalAndExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)*
|
/// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)*
|
||||||
fn parseBinOrExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn binOrExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// BinXorExpr <- BinAndExpr (CARET BinXorExpr)*
|
/// BinXorExpr <- BinAndExpr (CARET BinXorExpr)*
|
||||||
fn parseBinXorExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn binXorExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)*
|
/// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)*
|
||||||
fn parseBinAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn binAndExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)*
|
/// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)*
|
||||||
fn parseEqualityExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn equalityExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)*
|
/// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)*
|
||||||
fn parseComparisionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn comparisionExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)*
|
/// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)*
|
||||||
fn parseShiftExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn shiftExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)*
|
/// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)*
|
||||||
fn parseAdditiveExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn additiveExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)*
|
/// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)*
|
||||||
fn parseMultiplicativeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn multiplicativeExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// UnaryExpr
|
/// UnaryExpr
|
||||||
/// <- LPAREN TypeName RPAREN UnaryExpr
|
/// <- LPAREN TypeName RPAREN UnaryExpr
|
||||||
/// / Keyword_sizeof LAPERN TypeName RPAREN
|
/// / Keyword_sizeof LAPERN TypeName RPAREN
|
||||||
/// / Keyword_sizeof UnaryExpr
|
/// / Keyword_sizeof UnaryExpr
|
||||||
/// / Keyword_alignof LAPERN TypeName RPAREN
|
/// / Keyword_alignof LAPERN TypeName RPAREN
|
||||||
/// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr
|
/// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr
|
||||||
/// / PrimaryExpr PostFixExpr*
|
/// / PrimaryExpr PostFixExpr*
|
||||||
fn parseUnaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn unaryExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// PrimaryExpr
|
/// PrimaryExpr
|
||||||
/// <- IDENTIFIER
|
/// <- IDENTIFIER
|
||||||
/// / INTEGERLITERAL / FLITERAL / STRINGLITERAL / CHARLITERAL
|
/// / INTEGERLITERAL / FLITERAL / STRINGLITERAL / CHARLITERAL
|
||||||
/// / LPAREN Expr RPAREN
|
/// / LPAREN Expr RPAREN
|
||||||
/// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN
|
/// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN
|
||||||
fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn primaryExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Generic
|
/// Generic
|
||||||
/// <- TypeName COLON AssignmentExpr
|
/// <- TypeName COLON AssignmentExpr
|
||||||
/// / Keyword_default COLON AssignmentExpr
|
/// / Keyword_default COLON AssignmentExpr
|
||||||
fn parseGeneric(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn generic(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// PostFixExpr
|
/// PostFixExpr
|
||||||
/// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE
|
/// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE
|
||||||
/// / LBRACKET Expr RBRACKET
|
/// / LBRACKET Expr RBRACKET
|
||||||
/// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN
|
/// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN
|
||||||
/// / (PERIOD / ARROW) IDENTIFIER
|
/// / (PERIOD / ARROW) IDENTIFIER
|
||||||
/// / (PLUSPLUS / MINUSMINUS)
|
/// / (PLUSPLUS / MINUSMINUS)
|
||||||
fn parsePostFixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn postFixExpr(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA?
|
/// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA?
|
||||||
fn parseInitializers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn initializers(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Initializer
|
/// Initializer
|
||||||
/// <- LBRACE Initializers RBRACE
|
/// <- LBRACE Initializers RBRACE
|
||||||
/// / AssignmentExpr
|
/// / AssignmentExpr
|
||||||
fn parseInitializer(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn initializer(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Designator
|
/// Designator
|
||||||
/// <- LBRACKET Initializers RBRACKET
|
/// <- LBRACKET Initializers RBRACKET
|
||||||
/// / PERIOD IDENTIFIER
|
/// / PERIOD IDENTIFIER
|
||||||
fn parseDesignator(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn designator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
|
/// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
|
||||||
fn parseCompoundStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn compoundStmt(parser: *Parser) !?*Node {}
|
||||||
|
|
||||||
/// Stmt
|
/// Stmt
|
||||||
/// <- CompoundStmt
|
/// <- CompoundStmt
|
||||||
/// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)?
|
/// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)?
|
||||||
/// / Keyword_switch LPAREN Expr RPAREN Stmt
|
/// / Keyword_switch LPAREN Expr RPAREN Stmt
|
||||||
/// / Keyword_while LPAREN Expr RPAREN Stmt
|
/// / Keyword_while LPAREN Expr RPAREN Stmt
|
||||||
/// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON
|
/// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON
|
||||||
/// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt
|
/// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt
|
||||||
/// / Keyword_default COLON Stmt
|
/// / Keyword_default COLON Stmt
|
||||||
/// / Keyword_case ConstExpr COLON Stmt
|
/// / Keyword_case ConstExpr COLON Stmt
|
||||||
/// / Keyword_goto IDENTIFIER SEMICOLON
|
/// / Keyword_goto IDENTIFIER SEMICOLON
|
||||||
/// / Keyword_continue SEMICOLON
|
/// / Keyword_continue SEMICOLON
|
||||||
/// / Keyword_break SEMICOLON
|
/// / Keyword_break SEMICOLON
|
||||||
/// / Keyword_return Expr? SEMICOLON
|
/// / Keyword_return Expr? SEMICOLON
|
||||||
/// / IDENTIFIER COLON Stmt
|
/// / IDENTIFIER COLON Stmt
|
||||||
/// / ExprStmt
|
/// / ExprStmt
|
||||||
fn parseStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn stmt(parser: *Parser) !?*Node {
|
||||||
|
if (parser.compoundStmt()) |node| return node;
|
||||||
|
// if (parser.eatToken(.Keyword_if)) |tok| {}
|
||||||
|
// if (parser.eatToken(.Keyword_switch)) |tok| {}
|
||||||
|
// if (parser.eatToken(.Keyword_while)) |tok| {}
|
||||||
|
// if (parser.eatToken(.Keyword_do)) |tok| {}
|
||||||
|
// if (parser.eatToken(.Keyword_for)) |tok| {}
|
||||||
|
// if (parser.eatToken(.Keyword_default)) |tok| {}
|
||||||
|
// if (parser.eatToken(.Keyword_case)) |tok| {}
|
||||||
|
if (parser.eatToken(.Keyword_goto)) |tok| {
|
||||||
|
const node = try parser.arena.create(Node.JumpStmt);
|
||||||
|
node.* = .{
|
||||||
|
.ltoken = tok,
|
||||||
|
.kind = .Goto,
|
||||||
|
.semicolon = parser.expectToken(.Semicolon),
|
||||||
|
};
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
if (parser.eatToken(.Keyword_continue)) |tok| {
|
||||||
|
const node = try parser.arena.create(Node.JumpStmt);
|
||||||
|
node.* = .{
|
||||||
|
.ltoken = tok,
|
||||||
|
.kind = .Continue,
|
||||||
|
.semicolon = parser.expectToken(.Semicolon),
|
||||||
|
};
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
if (parser.eatToken(.Keyword_break)) |tok| {
|
||||||
|
const node = try parser.arena.create(Node.JumpStmt);
|
||||||
|
node.* = .{
|
||||||
|
.ltoken = tok,
|
||||||
|
.kind = .Break,
|
||||||
|
.semicolon = parser.expectToken(.Semicolon),
|
||||||
|
};
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
if (parser.eatToken(.Keyword_return)) |tok| {
|
||||||
|
const node = try parser.arena.create(Node.JumpStmt);
|
||||||
|
node.* = .{
|
||||||
|
.ltoken = tok,
|
||||||
|
.kind = .{ .Return = try parser.expr() },
|
||||||
|
.semicolon = parser.expectToken(.Semicolon),
|
||||||
|
};
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
if (parser.eatToken(.Identifier)) |tok| {
|
||||||
|
if (parser.eatToken(.Colon)) |col| {
|
||||||
|
const node = try parser.arena.create(Node.Label);
|
||||||
|
node.* = .{
|
||||||
|
.identifier = tok,
|
||||||
|
.semicolon = parser.expectToken(.Colon),
|
||||||
|
};
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
putBackToken(tok);
|
||||||
|
}
|
||||||
|
if (parser.exprStmt()) |node| return node;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// ExprStmt <- Expr? SEMICOLON
|
/// ExprStmt <- Expr? SEMICOLON
|
||||||
fn parseExprStmt(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node {}
|
fn exprStmt(parser: *Parser) !*Node {
|
||||||
|
const node = try parser.arena.create(Node.ExprStmt);
|
||||||
|
node.* = .{
|
||||||
|
.expr = try parser.expr(),
|
||||||
|
.semicolon = parser.expectToken(.Semicolon),
|
||||||
|
};
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eatToken(parser: *Parser, id: Token.Id) ?TokenIndex {
|
||||||
|
while (true) {
|
||||||
|
const next_tok = parser.it.next() orelse return null;
|
||||||
|
if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) {
|
||||||
|
if (next_tok.id == id) {
|
||||||
|
return parser.it.index;
|
||||||
|
}
|
||||||
|
parser.it.prev();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expectToken(parser: *Parser, id: Token.Id) Error!TokenIndex {
|
||||||
|
while (true) {
|
||||||
|
const next_tok = parser.it.next() orelse return error.ParseError;
|
||||||
|
if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) {
|
||||||
|
if (next_tok.id != id) {
|
||||||
|
try tree.errors.push(.{
|
||||||
|
.ExpectedToken = .{ .token = parser.it.index, .expected_id = id },
|
||||||
|
});
|
||||||
|
return error.ParseError;
|
||||||
|
}
|
||||||
|
return parser.it.index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn putBackToken(it: *TokenIterator, putting_back: TokenIndex) void {
|
||||||
|
while (true) {
|
||||||
|
const prev_tok = it.prev() orelse return;
|
||||||
|
if (next_tok.id == .LineComment or next_tok.id == .MultiLineComment) continue;
|
||||||
|
assert(it.list.at(putting_back) == prev_tok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue