Commit 3ed6d7d245

Vexu <git@vexu.eu>
2020-01-06 13:41:53
std-c parser declarator
1 parent d5d52af
Changed files (2)
lib/std/c/ast.zig
@@ -41,6 +41,7 @@ pub const Error = union(enum) {
     ExpectedStmt: SingleTokenError("expected statement, found '{}'"),
     ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
     ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
+    ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),
     ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),
     InvalidTypeSpecifier: InvalidTypeSpecifier,
     DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
@@ -55,6 +56,7 @@ pub const Error = union(enum) {
             .ExpectedTypeName => |*x| return x.render(tokens, stream),
             .ExpectedDeclarator => |*x| return x.render(tokens, stream),
             .ExpectedFnBody => |*x| return x.render(tokens, stream),
+            .ExpectedInitializer => |*x| return x.render(tokens, stream),
             .InvalidTypeSpecifier => |*x| return x.render(tokens, stream),
             .DuplicateQualifier => |*x| return x.render(tokens, stream),
             .DuplicateSpecifier => |*x| return x.render(tokens, stream),
@@ -70,6 +72,7 @@ pub const Error = union(enum) {
             .ExpectedTypeName => |x| return x.token,
             .ExpectedDeclarator => |x| return x.token,
             .ExpectedFnBody => |x| return x.token,
+            .ExpectedInitializer => |x| return x.token,
             .InvalidTypeSpecifier => |x| return x.token,
             .DuplicateQualifier => |x| return x.token,
             .DuplicateSpecifier => |x| return x.token,
@@ -277,30 +280,48 @@ pub const Node = struct {
     };
 
     pub const Declarator = struct {
+        base: Node = Node{ .id = .Declarator },
         pointer: *Pointer,
-        identifier: ?TokenIndex,
-        kind: union(enum) {
-            Simple,
+        prefix: union(enum) {
+            None,
+            Identifer: TokenIndex,
             Complex: struct {
                 lparen: TokenIndex,
-                inner: *Declarator,
+                inner: *Node,
                 rparen: TokenIndex,
             },
-            Fn: ParamList,
-            Array: ArrayList,
+        },
+        suffix: union(enum) {
+            None,
+            Fn: struct {
+                lparen: TokenIndex,
+                params: Params,
+                rparen: TokenIndex,
+            },
+            Array: Arrays,
         },
 
-        pub const ArrayList = std.SegmentedList(*Array, 2);
-        pub const ParamList = std.SegmentedList(*Param, 4);
+        pub const Arrays = std.SegmentedList(*Array, 2);
+        pub const Params = std.SegmentedList(*Param, 4);
     };
 
-    pub const Array = union(enum) {
-        Unspecified,
-        Variable: TokenIndex,
-        Known: *Expr,
+    pub const Array = struct {
+        rbracket: TokenIndex,
+        inner: union(enum) {
+            Inferred,
+            Unspecified: TokenIndex,
+            Variable: struct {
+                asterisk: ?TokenIndex,
+                static: ?TokenIndex,
+                qual: TypeQual,
+                expr: *Expr,
+            },
+        },
+        rbracket: TokenIndex,
     };
 
     pub const Pointer = struct {
+        base: Node = Node{ .id = .Pointer },
         asterisk: TokenIndex,
         qual: TypeQual,
         pointer: ?*Pointer,
@@ -312,7 +333,7 @@ pub const Node = struct {
             Old: TokenIndex,
             Normal: struct {
                 decl_spec: *DeclSpec,
-                declarator: *Declarator,
+                declarator: *Node,
             },
         },
     };
@@ -320,7 +341,7 @@ pub const Node = struct {
     pub const Fn = struct {
         base: Node = Node{ .id = .Fn },
         decl_spec: DeclSpec,
-        declarator: *Declarator,
+        declarator: *Node,
         old_decls: OldDeclList,
         body: ?*CompoundStmt,
 
@@ -332,7 +353,7 @@ pub const Node = struct {
         decl_spec: DeclSpec,
         declarators: DeclaratorList,
 
-        pub const DeclaratorList = std.SegmentedList(*Declarator, 2);
+        pub const DeclaratorList = Root.DeclList;
     };
 
     pub const Var = struct {
@@ -344,7 +365,7 @@ pub const Node = struct {
     };
 
     pub const Initialized = struct {
-        declarator: *Declarator,
+        declarator: *Node,
         eq: TokenIndex,
         init: Initializer,
     };
lib/std/c/parse.zig
@@ -589,7 +589,7 @@ const Parser = struct {
     fn recordDeclarator(parser: *Parser) !*Node {}
 
     /// Pointer <- ASTERISK TypeQual* Pointer?
-    fn pointer(parser: *Parser) !?*Node.Pointer {
+    fn pointer(parser: *Parser) Error!?*Node {
         const asterisk = parser.eatToken(.Asterisk) orelse return null;
         const node = try parser.arena.create(Node.Pointer);
         node.* = .{
@@ -599,34 +599,129 @@ const Parser = struct {
         };
         while (try parser.typeQual(&node.qual)) {}
         node.pointer = try parser.pointer();
-        return node;
+        return &node.base;
     }
-    /// DirectDeclarator
-    ///     <- IDENTIFIER
+
+    const Named = enum {
+        Must,
+        Allowed,
+        Forbidden,
+    };
+
+    /// Declarator <- Pointer? DeclaratorSuffix
+    /// DeclaratorPrefix
+    ///     <- IDENTIFIER // if named != .Forbidden
     ///     / LPAREN Declarator RPAREN
-    ///     / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
-    ///     / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
-    fn directDeclarator(parser: *Parser) !*Node {}
+    ///     / (none) // if named != .Must
+    /// DeclaratorSuffix
+    ///     <. DeclaratorPrefix (LBRACKET ArrayDeclarator? RBRACKET)*
+    ///     / DeclaratorPrefix LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
+    fn declarator(parser: *Parser, named: Named) Error!?*Node {
+        const ptr = try parser.pointer();
+        var node: *Node.Declarator = undefined;
+        // prefix
+        if (parser.eatToken(.LParen)) |lparen| {
+            const inner = (try parser.declarator(named)) orelse return parser.err(.{
+                .ExpectedDeclarator = .{ .token = lparen + 1 },
+            });
+            node = try parser.arena.create(Node.Declarator);
+            node.* = .{
+                .pointer = ptr,
+                .prefix = .{
+                    .Comples = .{
+                        .lparen = lparen,
+                        .inner = inner,
+                        .rparen = try parser.expectToken(.RParen),
+                    },
+                },
+                .suffix = .None,
+            };
+        } else if (named != .Forbidden) {
+            if (parser.eatToken(.Identifier)) |tok| {
+                node = try parser.arena.create(Node.Declarator);
+                node.* = .{
+                    .pointer = ptr,
+                    .prefix = .{ .Simple = tok },
+                    .suffix = .None,
+                };
+            } else if (named == .Must) {
+                return parser.err(.{
+                    .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },
+                });
+            } else {
+                return ptr;
+            }
+        } else {
+            node = try parser.arena.create(Node.Declarator);
+            node.* = .{
+                .pointer = ptr,
+                .prefix = .None,
+                .suffix = .None,
+            };
+        }
+        // suffix
+        if (parser.eatToken(.LParen)) |lparen| {
+            node.suffix = .{
+                .Fn = .{
+                    .lparen = lparen,
+                    .params = .Node.Declarator.Params.init(parser.arena),
+                    .rparen = undefined,
+                },
+            };
+            try parser.ParamDecl(node);
+            node.suffix.Fn.rparen = try parser.expectToken(.RParen);
+        } else {
+            while (parser.arrayDeclarator()) |arr| {
+                if (node.suffix == .None)
+                    node.suffix = .{ .Array = .Node.Declarator.Arrays.init(parser.arena) };
+                try node.suffix.Array.push(arr);
+            }
+        }
+        if (parser.eatToken(.LParen) orelse parser.eatToken(.LBracket)) |tok|
+            return parser.err(.{
+                .InvalidDeclarator = .{ .token = tok },
+            });
+        return node;
+    }
 
-    /// BracketDeclarator
-    ///     <- Keyword_static TypeQual* AssignmentExpr
+    /// ArrayDeclarator
+    ///     <- ASTERISK
+    ///     / Keyword_static TypeQual* AssignmentExpr
     ///     / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
     ///     / TypeQual+ AssignmentExpr?
     ///     / AssignmentExpr
-    fn bracketDeclarator(parser: *Parser) !*Node {}
+    fn arrayDeclarator(parser: *Parser, dr: *Node.Declarator) !?*Node.Array {
+        const lbracket = parser.eatToken(.LBracket) orelse return null;
+        const arr = try parser.arena.create(Node.Array);
+        arr.* = .{
+            .lbracket = lbarcket,
+            .inner = .Inferred,
+            .rbracket = undefined,
+        };
+        if (parser.eatToken(.Asterisk)) |tok| {
+            arr.inner = .{ .Unspecified = tok };
+        } else {
+            // TODO
+        }
+        arr.rbracket = try parser.expectToken(.RBracket);
+        return arr;
+    }
 
+    /// Params <- ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?
     /// ParamDecl <- DeclSpec (Declarator / AbstractDeclarator)
-    fn paramDecl(parser: *Parser) !*Node {}
-
-    /// AbstractDeclarator <- Pointer? DirectAbstractDeclarator?
-    fn abstractDeclarator(parser: *Parser) !*Node {}
-
-    /// DirectAbstractDeclarator
-    ///     <- IDENTIFIER
-    ///     / LPAREN DirectAbstractDeclarator RPAREN
-    ///     / DirectAbstractDeclarator? LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
-    ///     / DirectAbstractDeclarator? LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
-    fn directAbstractDeclarator(parser: *Parser) !*Node {}
+    fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {
+        var old_style = false;
+        while (true) {
+            var ds = Node.DeclSpec;
+            if (try parser.declSpec(&ds)) {
+                //TODO
+            } else if (parser.eatToken(.Identifier)) {
+                old_style = true;
+            } else if (parser.eatToken(.Ellipsis)) {
+                // TODO
+            }
+        }
+    }
 
     /// Expr <- AssignmentExpr (COMMA Expr)*
     fn expr(parser: *Parser) !*Node {}