authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 18:58:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 18:58:28-07:00
log2bb2e61ee288a02e184e5b8422859a4afcbb4813
treef7b77f8ce8837d9909250b9dec3326d963976d6d
parentff028525e5421ee93182bbf19102d34d434286f3

parser: allow missing fn name and missing param names

now these problems are caught in analyzer this is for purpose of function type, see #14

4 files changed, 138 insertions(+), 97 deletions(-)

doc/langref.md+90-74
......@@ -3,153 +3,153 @@
33## Grammar
44
55```
6Root : many(TopLevelDecl) "EOF"
6Root = many(TopLevelDecl) "EOF"
77
8TopLevelDecl : many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl)
8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl)
99
10CImportDecl : "c_import" Block
10CImportDecl = "c_import" Block
1111
12ErrorValueDecl : "error" "Symbol" ";"
12ErrorValueDecl = "error" "Symbol" ";"
1313
14GlobalVarDecl : VariableDeclaration ";"
14GlobalVarDecl = VariableDeclaration ";"
1515
16VariableDeclaration : ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression
16VariableDeclaration = ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression
1717
18ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
18ContainerDecl = ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
1919
20StructMember: many(Directive) option(VisibleMod) (StructField | FnDef)
20StructMember = many(Directive) option(VisibleMod) (StructField | FnDef)
2121
22StructField : "Symbol" option(":" Expression) ",")
22StructField = "Symbol" option(":" Expression) ",")
2323
24Import : "import" "String" ";"
24Import = "import" "String" ";"
2525
26RootExportDecl : "export" "Symbol" "String" ";"
26RootExportDecl = "export" "Symbol" "String" ";"
2727
28ExternDecl : "extern" FnProto ";"
28ExternDecl = "extern" FnProto ";"
2929
30FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
30FnProto = "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression)
3131
32Directive : "#" "Symbol" "(" "String" ")"
32Directive = "#" "Symbol" "(" "String" ")"
3333
34VisibleMod : "pub" | "export"
34VisibleMod = "pub" | "export"
3535
36FnDef : FnProto Block
36FnDef = FnProto Block
3737
38ParamDeclList : "(" list(ParamDecl, ",") ")"
38ParamDeclList = "(" list(ParamDecl, ",") ")"
3939
40ParamDecl : option("noalias") "Symbol" ":" PrefixOpExpression | "..."
40ParamDecl = option("noalias") option("Symbol" ":") PrefixOpExpression | "..."
4141
42Block : "{" list(option(Statement), ";") "}"
42Block = "{" list(option(Statement), ";") "}"
4343
44Statement : Label | VariableDeclaration ";" | NonBlockExpression ";" | BlockExpression
44Statement = Label | VariableDeclaration ";" | NonBlockExpression ";" | BlockExpression
4545
46Label: "Symbol" ":"
46Label = "Symbol" ":"
4747
48Expression : BlockExpression | NonBlockExpression
48Expression = BlockExpression | NonBlockExpression
4949
50NonBlockExpression : ReturnExpression | AssignmentExpression
50NonBlockExpression = ReturnExpression | AssignmentExpression
5151
52AsmExpression : "asm" option("volatile") "(" "String" option(AsmOutput) ")"
52AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"
5353
54AsmOutput : ":" list(AsmOutputItem, ",") option(AsmInput)
54AsmOutput = ":" list(AsmOutputItem, ",") option(AsmInput)
5555
56AsmInput : ":" list(AsmInputItem, ",") option(AsmClobbers)
56AsmInput = ":" list(AsmInputItem, ",") option(AsmClobbers)
5757
58AsmOutputItem : "[" "Symbol" "]" "String" "(" ("Symbol" | "->" PrefixOpExpression) ")"
58AsmOutputItem = "[" "Symbol" "]" "String" "(" ("Symbol" | "->" PrefixOpExpression) ")"
5959
60AsmInputItem : "[" "Symbol" "]" "String" "(" Expression ")"
60AsmInputItem = "[" "Symbol" "]" "String" "(" Expression ")"
6161
62AsmClobbers: ":" list("String", ",")
62AsmClobbers= ":" list("String", ",")
6363
64UnwrapExpression : BoolOrExpression (UnwrapMaybe | UnwrapError) | BoolOrExpression
64UnwrapExpression = BoolOrExpression (UnwrapMaybe | UnwrapError) | BoolOrExpression
6565
66UnwrapMaybe : "??" BoolOrExpression
66UnwrapMaybe = "??" BoolOrExpression
6767
68UnwrapError : "%%" option("|" "Symbol" "|") BoolOrExpression
68UnwrapError = "%%" option("|" "Symbol" "|") BoolOrExpression
6969
70AssignmentExpression : UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
70AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
7171
72AssignmentOperator : "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||="
72AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||="
7373
74BlockExpression : IfExpression | Block | WhileExpression | ForExpression | SwitchExpression
74BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression
7575
76SwitchExpression : "switch" "(" Expression ")" "{" many(SwitchProng) "}"
76SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
7777
78SwitchProng : (list(SwitchItem, ",") | "else") option(":" "(" "Symbol" ")") "=>" Expression ","
78SwitchProng = (list(SwitchItem, ",") | "else") option(":" "(" "Symbol" ")") "=>" Expression ","
7979
80SwitchItem : Expression | (Expression "..." Expression)
80SwitchItem = Expression | (Expression "..." Expression)
8181
82WhileExpression : "while" "(" Expression ")" Expression
82WhileExpression = "while" "(" Expression ")" Expression
8383
84ForExpression : "for" "(" "Symbol" "," Expression option("," "Symbol") ")" Expression
84ForExpression = "for" "(" "Symbol" "," Expression option("," "Symbol") ")" Expression
8585
86BoolOrExpression : BoolAndExpression "||" BoolOrExpression | BoolAndExpression
86BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
8787
88ReturnExpression : option("%" | "?") "return" option(Expression)
88ReturnExpression = option("%" | "?") "return" option(Expression)
8989
90IfExpression : IfVarExpression | IfBoolExpression
90IfExpression = IfVarExpression | IfBoolExpression
9191
92IfBoolExpression : "if" "(" Expression ")" Expression option(Else)
92IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
9393
94IfVarExpression : "if" "(" ("const" | "var") "Symbol" option(":" PrefixOpExpression) "?=" Expression ")" Expression Option(Else)
94IfVarExpression = "if" "(" ("const" | "var") "Symbol" option(":" PrefixOpExpression) "?=" Expression ")" Expression Option(Else)
9595
96Else : "else" Expression
96Else = "else" Expression
9797
98BoolAndExpression : ComparisonExpression "&&" BoolAndExpression | ComparisonExpression
98BoolAndExpression = ComparisonExpression "&&" BoolAndExpression | ComparisonExpression
9999
100ComparisonExpression : BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression
100ComparisonExpression = BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression
101101
102ComparisonOperator : "==" | "!=" | "<" | ">" | "<=" | ">="
102ComparisonOperator = "==" | "!=" | "<" | ">" | "<=" | ">="
103103
104BinaryOrExpression : BinaryXorExpression "|" BinaryOrExpression | BinaryXorExpression
104BinaryOrExpression = BinaryXorExpression "|" BinaryOrExpression | BinaryXorExpression
105105
106BinaryXorExpression : BinaryAndExpression "^" BinaryXorExpression | BinaryAndExpression
106BinaryXorExpression = BinaryAndExpression "^" BinaryXorExpression | BinaryAndExpression
107107
108BinaryAndExpression : BitShiftExpression "&" BinaryAndExpression | BitShiftExpression
108BinaryAndExpression = BitShiftExpression "&" BinaryAndExpression | BitShiftExpression
109109
110BitShiftExpression : AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
110BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
111111
112BitShiftOperator : "<<" | ">>"
112BitShiftOperator = "<<" | ">>"
113113
114AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
114AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
115115
116AdditionOperator : "+" | "-" | "++"
116AdditionOperator = "+" | "-" | "++"
117117
118MultiplyExpression : CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
118MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
119119
120CurlySuffixExpression : PrefixOpExpression option(ContainerInitExpression)
120CurlySuffixExpression = PrefixOpExpression option(ContainerInitExpression)
121121
122MultiplyOperator : "*" | "/" | "%"
122MultiplyOperator = "*" | "/" | "%"
123123
124PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
124PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
125125
126SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
126SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
127127
128FieldAccessExpression : "." "Symbol"
128FieldAccessExpression = "." "Symbol"
129129
130FnCallExpression : "(" list(Expression, ",") ")"
130FnCallExpression = "(" list(Expression, ",") ")"
131131
132ArrayAccessExpression : "[" Expression "]"
132ArrayAccessExpression = "[" Expression "]"
133133
134SliceExpression : "[" Expression "..." option(Expression) "]" option("const")
134SliceExpression = "[" Expression "..." option(Expression) "]" option("const")
135135
136ContainerInitExpression : "{" ContainerInitBody "}"
136ContainerInitExpression = "{" ContainerInitBody "}"
137137
138ContainerInitBody : list(StructLiteralField, ",") | list(Expression, ",")
138ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
139139
140StructLiteralField : "." "Symbol" "=" Expression
140StructLiteralField = "." "Symbol" "=" Expression
141141
142PrefixOp : "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"
142PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"
143143
144PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")
144PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol")
145145
146ArrayType : "[" option(Expression) "]" option("const") PrefixOpExpression
146ArrayType = "[" option(Expression) "]" option("const") PrefixOpExpression
147147
148GotoExpression: "goto" "Symbol"
148GotoExpression = "goto" "Symbol"
149149
150GroupedExpression : "(" Expression ")"
150GroupedExpression = "(" Expression ")"
151151
152KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"
152KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"
153153```
154154
155155## Operator Precedence
......@@ -204,9 +204,11 @@ c_ulonglong unsigned long long for ABI compatibility with C
204204```
205205
206206### Boolean Type
207
207208The boolean type has the name `bool` and represents either true or false.
208209
209210### Function Type
211
210212TODO
211213
212214### Fixed-Size Array Type
......@@ -222,6 +224,7 @@ A slice can be obtained with the slicing syntax: `array[start...end]`
222224Example: `"aoeu"[0...2]` has type `[]u8`.
223225
224226### Struct Type
227
225228TODO
226229
227230### Enum Type
......@@ -296,34 +299,44 @@ Hex floating point TODO TODO
296299```
297300
298301### Identifiers
302
299303TODO
300304
301305### Declarations
306
302307Declarations have type `void`.
303308
304309#### Function Declarations
310
305311TODO
306312
307313#### Variable Declarations
314
308315TODO
309316
310317#### Struct Declarations
318
311319TODO
312320
313321#### Enum Declarations
322
314323TODO
315324
316325
317326## Built-in Functions
327
318328Built-in functions are prefixed with `@`.
319329
320330### Typeof
331
321332TODO
322333
323334### Sizeof
335
324336TODO
325337
326338### Overflow Arithmetic
339
327340Overflow arithmetic functions have defined behavior on overflow or underflow. TODO what is that behaviour?
328341
329342The functions take an integer (TODO float?) type, two variables of the specified type, and a pointer to a variable of the specified type where the result is stored. The functions return a boolean value: true of overflow/underflow occurred, false otherwise.
......@@ -336,10 +349,13 @@ bool mul_with_overflow(type, a: type, b: type, x: &type) *x = a * b
336349```
337350
338351### Memory Operations
352
339353TODO memset and memcpy
340354
341355### Value Count
356
342357TODO
343358
344359### Max and Min Value
360
345361TODO
src/analyze.cpp+20-1
......@@ -457,6 +457,10 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
457457 assert(node->type == NodeTypeFnProto);
458458 AstNodeFnProto *fn_proto = &node->data.fn_proto;
459459
460 if (fn_proto->skip) {
461 return;
462 }
463
460464 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
461465 fn_table_entry->type_entry = fn_type;
462466 fn_type->data.fn.calling_convention = fn_table_entry->internal_linkage ? LLVMFastCallConv : LLVMCCallConv;
......@@ -932,6 +936,9 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
932936static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
933937 AstNode *proto_node)
934938{
939 if (proto_node->data.fn_proto.skip) {
940 return;
941 }
935942 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;
936943 AstNode *struct_node = proto_node->data.fn_proto.struct_node;
937944 bool is_extern = proto_node->data.fn_proto.is_extern;
......@@ -4307,6 +4314,10 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
43074314 buf_sprintf("byvalue struct parameters not yet supported on exported functions"));
43084315 }
43094316
4317 if (buf_len(&param_decl->name) == 0) {
4318 add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));
4319 }
4320
43104321 VariableTableEntry *var = add_local_var(g, param_decl_node, context, &param_decl->name, type, true);
43114322 var->src_arg_index = i;
43124323 param_decl_node->data.param_decl.variable = var;
......@@ -4682,6 +4693,15 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
46824693 }
46834694 case NodeTypeFnProto:
46844695 {
4696 // if the name is missing, we immediately announce an error
4697 Buf *name = &node->data.fn_proto.name;
4698 if (buf_len(name) == 0) {
4699 node->data.fn_proto.skip = true;
4700 add_node_error(g, node, buf_sprintf("missing function name"));
4701 break;
4702 }
4703
4704
46854705 // determine which other top level declarations this function prototype depends on.
46864706 TopLevelDecl *decl_node = &node->data.fn_proto.top_level_decl;
46874707 decl_node->deps.init(1);
......@@ -4692,7 +4712,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
46924712 }
46934713 collect_expr_decl_deps(g, import, node->data.fn_proto.return_type, decl_node);
46944714
4695 Buf *name = &node->data.fn_proto.name;
46964715 decl_node->name = name;
46974716 decl_node->import = import;
46984717 if (decl_node->deps.size() > 0) {
src/parser.cpp+21-22
......@@ -569,35 +569,33 @@ static void ast_parse_directives(ParseContext *pc, int *token_index,
569569}
570570
571571/*
572ParamDecl : option("noalias") "Symbol" ":" PrefixOpExpression | "..."
572ParamDecl = option("noalias") option("Symbol" ":") PrefixOpExpression | "..."
573573*/
574574static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) {
575 Token *first_token = &pc->tokens->at(*token_index);
575 Token *token = &pc->tokens->at(*token_index);
576576
577 if (first_token->id == TokenIdEllipsis) {
577 if (token->id == TokenIdEllipsis) {
578578 *token_index += 1;
579579 return nullptr;
580580 }
581581
582 AstNode *node = ast_create_node(pc, NodeTypeParamDecl, first_token);
583 Token *name_token;
582 AstNode *node = ast_create_node(pc, NodeTypeParamDecl, token);
584583
585 if (first_token->id == TokenIdKeywordNoAlias) {
584 if (token->id == TokenIdKeywordNoAlias) {
586585 node->data.param_decl.is_noalias = true;
587586 *token_index += 1;
588 name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
589 } else if (first_token->id == TokenIdSymbol) {
590 name_token = first_token;
591 *token_index += 1;
592 } else {
593 ast_invalid_token_error(pc, first_token);
587 token = &pc->tokens->at(*token_index);
594588 }
595589
596 ast_buf_from_token(pc, name_token, &node->data.param_decl.name);
590 buf_resize(&node->data.param_decl.name, 0);
597591
598 Token *colon = &pc->tokens->at(*token_index);
599 *token_index += 1;
600 ast_expect_token(pc, colon, TokenIdColon);
592 if (token->id == TokenIdSymbol) {
593 Token *next_token = &pc->tokens->at(*token_index + 1);
594 if (next_token->id == TokenIdColon) {
595 ast_buf_from_token(pc, token, &node->data.param_decl.name);
596 *token_index += 2;
597 }
598 }
601599
602600 node->data.param_decl.type = ast_parse_prefix_op_expr(pc, token_index, true);
603601
......@@ -2179,7 +2177,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
21792177}
21802178
21812179/*
2182FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
2180FnProto : "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression)
21832181*/
21842182static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,
21852183 ZigList<AstNode*> *directives, VisibMod visib_mod)
......@@ -2200,11 +2198,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
22002198 node->data.fn_proto.directives = directives;
22012199
22022200 Token *fn_name = &pc->tokens->at(*token_index);
2203 *token_index += 1;
2204 ast_expect_token(pc, fn_name, TokenIdSymbol);
2205
2206 ast_buf_from_token(pc, fn_name, &node->data.fn_proto.name);
2207
2201 if (fn_name->id == TokenIdSymbol) {
2202 *token_index += 1;
2203 ast_buf_from_token(pc, fn_name, &node->data.fn_proto.name);
2204 } else {
2205 buf_resize(&node->data.fn_proto.name, 0);
2206 }
22082207
22092208 ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args);
22102209
test/run_tests.cpp+7
......@@ -1859,6 +1859,13 @@ fn f(foo: Foo, index: i32) {
18591859 const result = members[index]();
18601860}
18611861 )SOURCE", 1, ".tmp_source.zig:21:34: error: expected 1 arguments, got 0");
1862
1863 add_compile_fail_case("missing function name and param name", R"SOURCE(
1864fn () {}
1865fn f(i32) {}
1866 )SOURCE", 2,
1867 ".tmp_source.zig:2:1: error: missing function name",
1868 ".tmp_source.zig:3:6: error: missing parameter name");
18621869}
18631870
18641871//////////////////////////////////////////////////////////////////////////////