mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Grammar updates. Updated enum member parsing.
This commit is contained in:
@@ -28,7 +28,8 @@ void yyerror(char *s);
|
|||||||
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
|
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
|
||||||
%token FN FAULT MACRO GENERIC CT_IF CT_ENDIF CT_ELSE CT_SWITCH CT_CASE CT_DEFAULT CT_FOR CT_FOREACH CT_ENDFOREACH
|
%token FN FAULT MACRO GENERIC CT_IF CT_ENDIF CT_ELSE CT_SWITCH CT_CASE CT_DEFAULT CT_FOR CT_FOREACH CT_ENDFOREACH
|
||||||
%token CT_ENDFOR CT_ENDSWITCH BUILTIN IMPLIES INITIALIZE FINALIZE CT_ECHO CT_ASSERT CT_EVALTYPE CT_VATYPE
|
%token CT_ENDFOR CT_ENDSWITCH BUILTIN IMPLIES INITIALIZE FINALIZE CT_ECHO CT_ASSERT CT_EVALTYPE CT_VATYPE
|
||||||
%token TRY CATCH SCOPE PUBLIC DEFER ATTRIBUTE TRY_Q CATCH_Q LVEC RVEC OPTELSE CT_TYPEFROM CT_TYPEOF
|
%token TRY CATCH SCOPE PUBLIC DEFER ATTRIBUTE TRY_Q CATCH_Q LVEC RVEC OPTELSE CT_TYPEFROM CT_TYPEOF TLOCAL
|
||||||
|
%token CT_VASPLAT
|
||||||
|
|
||||||
%token FN_BLOCK_START FN_BLOCK_END
|
%token FN_BLOCK_START FN_BLOCK_END
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ path
|
|||||||
| path IDENT SCOPE
|
| path IDENT SCOPE
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
import_path
|
import_path
|
||||||
: IDENT
|
: IDENT
|
||||||
| import_path SCOPE IDENT
|
| import_path SCOPE IDENT
|
||||||
@@ -203,23 +205,44 @@ assignment_operator
|
|||||||
| SUB_MOD_ASSIGN
|
| SUB_MOD_ASSIGN
|
||||||
;
|
;
|
||||||
|
|
||||||
constant_expression
|
constant_expr
|
||||||
: conditional_expression
|
: conditional_expression
|
||||||
;
|
;
|
||||||
|
|
||||||
|
param_path_element
|
||||||
|
: '[' expression ']'
|
||||||
|
| '.' IDENT
|
||||||
|
;
|
||||||
|
|
||||||
|
param_path
|
||||||
|
: param_path_element
|
||||||
|
| param_path param_path_element
|
||||||
|
;
|
||||||
|
|
||||||
|
arg : param_path '=' expression
|
||||||
|
| expression
|
||||||
|
| CT_VASPLAT '(' constant_expr ')'
|
||||||
|
| ELLIPSIS expression
|
||||||
|
;
|
||||||
|
|
||||||
|
arg_list
|
||||||
|
: arg
|
||||||
|
| arg_list ',' arg
|
||||||
|
;
|
||||||
|
|
||||||
enumerators
|
enumerators
|
||||||
: enumerator
|
: enumerator
|
||||||
| enumerators ',' enumerator
|
| enumerators ',' enumerator
|
||||||
;
|
;
|
||||||
enumerator_list
|
|
||||||
|
enum_list
|
||||||
: enumerators
|
: enumerators
|
||||||
| enumerators ','
|
| enumerators ','
|
||||||
;
|
;
|
||||||
|
|
||||||
enumerator
|
enumerator
|
||||||
: CONST_IDENT
|
: CONST_IDENT
|
||||||
| CONST_IDENT '=' constant_expression
|
| CONST_IDENT '(' arg_list ')'
|
||||||
;
|
;
|
||||||
|
|
||||||
identifier_list
|
identifier_list
|
||||||
@@ -244,6 +267,12 @@ declaration
|
|||||||
| optional_type IDENT
|
| optional_type IDENT
|
||||||
;
|
;
|
||||||
|
|
||||||
|
enum_param_decl
|
||||||
|
: type
|
||||||
|
| type IDENT
|
||||||
|
| type IDENT '=' expression
|
||||||
|
;
|
||||||
|
|
||||||
param_declaration
|
param_declaration
|
||||||
: type
|
: type
|
||||||
| type IDENT
|
| type IDENT
|
||||||
@@ -266,6 +295,7 @@ parameter_list
|
|||||||
| parameter_list ',' param_declaration
|
| parameter_list ',' param_declaration
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Updated for 0.5 */
|
||||||
base_type
|
base_type
|
||||||
: VOID
|
: VOID
|
||||||
| BOOL
|
| BOOL
|
||||||
@@ -280,28 +310,30 @@ base_type
|
|||||||
| INT128
|
| INT128
|
||||||
| UINT128
|
| UINT128
|
||||||
| FLOAT
|
| FLOAT
|
||||||
|
| DOUBLE
|
||||||
| FLOAT16
|
| FLOAT16
|
||||||
| FLOAT128
|
| FLOAT128
|
||||||
| DOUBLE
|
|
||||||
| TYPE_IDENT
|
| TYPE_IDENT
|
||||||
| path TYPE_IDENT
|
| path TYPE_IDENT
|
||||||
| CT_TYPE_IDENT
|
| CT_TYPE_IDENT
|
||||||
| CT_TYPEOF '(' expression ')'
|
| CT_TYPEOF '(' expression ')'
|
||||||
| CT_TYPEFROM '(' constant_expression ')'
|
| CT_TYPEFROM '(' constant_expr ')'
|
||||||
| CT_VATYPE '(' constant_expression ')'
|
| CT_VATYPE '(' constant_expr ')'
|
||||||
| CT_EVALTYPE '(' constant_expression ')'
|
| CT_EVALTYPE '(' constant_expr ')'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Updated for 0.5 */
|
||||||
type
|
type
|
||||||
: base_type
|
: base_type
|
||||||
| type '*'
|
| type '*'
|
||||||
| type '[' constant_expression ']'
|
| type '[' constant_expr ']'
|
||||||
| type '[' ']'
|
| type '[' ']'
|
||||||
| type '[' '*' ']'
|
| type '[' '*' ']'
|
||||||
| type LVEC constant_expression RVEC
|
| type LVEC constant_expr RVEC
|
||||||
| type LVEC '*' RVEC
|
| type LVEC '*' RVEC
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Updated for 0.5 */
|
||||||
optional_type
|
optional_type
|
||||||
: type
|
: type
|
||||||
| type '!'
|
| type '!'
|
||||||
@@ -312,6 +344,43 @@ initializer
|
|||||||
| initializer_list
|
| initializer_list
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/* Updated for 0.5 */
|
||||||
|
local_decl_after_type
|
||||||
|
: CT_IDENT
|
||||||
|
| CT_IDENT '=' constant_expr
|
||||||
|
| IDENT opt_attributes
|
||||||
|
| IDENT opt_attributes '=' expression
|
||||||
|
;
|
||||||
|
|
||||||
|
local_decl_storage
|
||||||
|
: STATIC
|
||||||
|
| TLOCAL
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Updated for 0.5 */
|
||||||
|
local_decl
|
||||||
|
: const_declaration
|
||||||
|
| local_decl_storage optional_type local_decl_after_type
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Updated for 0.5 */
|
||||||
|
decl_or_expr
|
||||||
|
: var_decl
|
||||||
|
| optional_type local_decl_after_type
|
||||||
|
| expression
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Updated for 0.5 */
|
||||||
|
var_decl
|
||||||
|
: VAR IDENT '=' expression
|
||||||
|
| VAR CT_IDENT '=' expression
|
||||||
|
| VAR CT_IDENT
|
||||||
|
| VAR CT_TYPE_IDENT '=' expression
|
||||||
|
| VAR CT_TYPE_IDENT
|
||||||
|
;
|
||||||
|
|
||||||
initializer_values
|
initializer_values
|
||||||
: initializer
|
: initializer
|
||||||
| initializer_values ',' initializer
|
| initializer_values ',' initializer
|
||||||
@@ -319,11 +388,11 @@ initializer_values
|
|||||||
|
|
||||||
initializer_list
|
initializer_list
|
||||||
: '{' initializer_values '}'
|
: '{' initializer_values '}'
|
||||||
| '{' initializer_values ',' '}'
|
| '{' initializer_values ',' '}'
|
||||||
;
|
;
|
||||||
|
|
||||||
ct_case_statement
|
ct_case_statement
|
||||||
: CT_CASE expression ':' opt_stmt_list
|
: CT_CASE constant_expr ':' opt_stmt_list
|
||||||
| CT_DEFAULT ':' opt_stmt_list
|
| CT_DEFAULT ':' opt_stmt_list
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -338,7 +407,7 @@ ct_for_stmt
|
|||||||
;
|
;
|
||||||
|
|
||||||
ct_foreach_stmt
|
ct_foreach_stmt
|
||||||
: CT_FOREACH '(' CT_IDENT ':' expression ')' opt_stmt_list CT_ENDFOREACH
|
: CT_FOREACH '(' CT_IDENT ':' constant_expr ')' opt_stmt_list CT_ENDFOREACH
|
||||||
|
|
||||||
ct_statement
|
ct_statement
|
||||||
: ct_if opt_stmt_list CT_ENDIF
|
: ct_if opt_stmt_list CT_ENDIF
|
||||||
@@ -428,12 +497,12 @@ decl_expr_list
|
|||||||
;
|
;
|
||||||
|
|
||||||
ct_assert_stmt
|
ct_assert_stmt
|
||||||
: CT_ASSERT '(' expression ',' expression ')' ';'
|
: CT_ASSERT '(' constant_expr ',' constant_expr ')' ';'
|
||||||
| CT_ASSERT '(' expression ')' ';'
|
| CT_ASSERT '(' constant_expr ')' ';'
|
||||||
;
|
;
|
||||||
|
|
||||||
ct_echo_stmt
|
ct_echo_stmt
|
||||||
: CT_ECHO '(' expression ')' ';'
|
: CT_ECHO '(' constant_expr ')' ';'
|
||||||
|
|
||||||
bitstruct_declaration
|
bitstruct_declaration
|
||||||
: BITSTRUCT IDENT ':' type opt_attributes bitstruct_body
|
: BITSTRUCT IDENT ':' type opt_attributes bitstruct_body
|
||||||
@@ -449,8 +518,8 @@ bitstruct_defs
|
|||||||
;
|
;
|
||||||
|
|
||||||
bitstruct_def
|
bitstruct_def
|
||||||
: type IDENT ':' constant_expression DOTDOT constant_expression ';'
|
: type IDENT ':' constant_expr DOTDOT constant_expr ';'
|
||||||
| type IDENT ':' constant_expression ';'
|
| type IDENT ':' constant_expr ';'
|
||||||
;
|
;
|
||||||
|
|
||||||
static_declaration
|
static_declaration
|
||||||
@@ -482,41 +551,49 @@ jump_statement
|
|||||||
| RETURN expression ';'
|
| RETURN expression ';'
|
||||||
;
|
;
|
||||||
|
|
||||||
path_ident
|
/* Updated for 0.5 */
|
||||||
: IDENT
|
attribute_name
|
||||||
| path IDENT
|
: AT_IDENT
|
||||||
;
|
| AT_TYPE_IDENT
|
||||||
|
| path AT_TYPE_IDENT
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
attribute_operator_expr
|
||||||
|
: '&' '[' ']'
|
||||||
|
| '[' ']' '='
|
||||||
|
| '[' ']'
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
attr_param
|
||||||
|
: attribute_operator_expr
|
||||||
|
| constant_expr
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
attribute_param_list
|
||||||
|
: attr_param
|
||||||
|
| attribute_param_list ',' attr_param
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
attribute
|
attribute
|
||||||
: '@' path_ident
|
: attribute_name
|
||||||
| '@' path_ident '(' constant_expression ')'
|
| attribute_name '(' attribute_param_list ')'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
attribute_list
|
attribute_list
|
||||||
: attribute
|
: attribute
|
||||||
| attribute_list attribute
|
| attribute_list attribute
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
opt_attributes
|
opt_attributes
|
||||||
: attribute_list
|
: attribute_list
|
||||||
|
|
|
|
||||||
;
|
;
|
||||||
|
|
||||||
func_name
|
|
||||||
: path TYPE_IDENT '.' IDENT
|
|
||||||
| TYPE_IDENT '.' IDENT
|
|
||||||
| IDENT
|
|
||||||
;
|
|
||||||
|
|
||||||
func_declaration
|
|
||||||
: FN optional_type func_name opt_parameter_type_list opt_attributes
|
|
||||||
;
|
|
||||||
|
|
||||||
func_definition
|
|
||||||
: func_declaration compound_statement
|
|
||||||
| func_declaration ';'
|
|
||||||
| func_declaration IMPLIES expression ';'
|
|
||||||
;
|
|
||||||
|
|
||||||
macro_declaration
|
macro_declaration
|
||||||
: MACRO type IDENT '(' macro_argument_list ')' compound_statement
|
: MACRO type IDENT '(' macro_argument_list ')' compound_statement
|
||||||
@@ -524,14 +601,16 @@ macro_declaration
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
struct_or_union
|
struct_or_union
|
||||||
: STRUCT
|
: STRUCT
|
||||||
| UNION
|
| UNION
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
struct_declaration
|
struct_declaration
|
||||||
: struct_or_union TYPE_IDENT opt_attributes struct_body
|
: struct_or_union TYPE_IDENT opt_attributes struct_body
|
||||||
;
|
;
|
||||||
|
|
||||||
struct_body
|
struct_body
|
||||||
: '{' struct_declaration_list '}'
|
: '{' struct_declaration_list '}'
|
||||||
@@ -548,10 +627,24 @@ struct_member_declaration
|
|||||||
| struct_or_union opt_attributes struct_body
|
| struct_or_union opt_attributes struct_body
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
enum_params
|
||||||
|
: enum_param_decl
|
||||||
|
| enum_params ',' enum_param_decl
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
enum_spec
|
||||||
|
: ':' type
|
||||||
|
| ':' type '(' ')'
|
||||||
|
| ':' type '(' enum_params ')'
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
enum_declaration
|
enum_declaration
|
||||||
: ENUM TYPE_IDENT ':' type opt_attributes '{' enumerator_list '}'
|
: ENUM TYPE_IDENT enum_spec opt_attributes '{' enum_list '}'
|
||||||
| ENUM TYPE_IDENT opt_attributes '{' enumerator_list '}'
|
;
|
||||||
;
|
|
||||||
|
|
||||||
faults
|
faults
|
||||||
: CONST_IDENT
|
: CONST_IDENT
|
||||||
@@ -563,10 +656,70 @@ fault_declaration
|
|||||||
| FAULT opt_attributes '{' faults ',' '}'
|
| FAULT opt_attributes '{' faults ',' '}'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
func_header
|
||||||
|
: optional_type type '.' IDENT
|
||||||
|
| optional_type IDENT
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
macro_name
|
||||||
|
: IDENT
|
||||||
|
| AT_IDENT
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
macro_header
|
||||||
|
: optional_type type '.' macro_name
|
||||||
|
| optional_type macro_name
|
||||||
|
| type '.' macro_name
|
||||||
|
| macro_name
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
fn_parameter_list
|
||||||
|
: '(' parameters ')'
|
||||||
|
| '(' ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
parameters
|
||||||
|
: parameter '=' expression
|
||||||
|
| parameter
|
||||||
|
| parameters ',' parameter
|
||||||
|
| parameters ',' parameter '=' expression
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
|
parameter
|
||||||
|
: type IDENT opt_attributes
|
||||||
|
| ELLIPSIS
|
||||||
|
| type ELLIPSIS IDENT opt_attributes
|
||||||
|
| type ELLIPSIS CT_IDENT
|
||||||
|
| IDENT ELLIPSIS
|
||||||
|
| type '&' IDENT opt_attributes
|
||||||
|
| '&' IDENT opt_attributes
|
||||||
|
| type HASH_IDENT opt_attributes
|
||||||
|
| HASH_IDENT opt_attributes
|
||||||
|
| type CT_IDENT
|
||||||
|
| CT_IDENT
|
||||||
|
| CT_IDENT ELLIPSIS
|
||||||
|
| type opt_attributes
|
||||||
|
;
|
||||||
|
|
||||||
|
function_definition
|
||||||
|
: FN func_header fn_parameter_list opt_attributes ';'
|
||||||
|
| FN func_header fn_parameter_list opt_attributes IMPLIES expression ';'
|
||||||
|
| FN func_header fn_parameter_list opt_attributes compound_statement
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
const_declaration
|
const_declaration
|
||||||
: CONST CONST_IDENT opt_attributes '=' initializer ';'
|
: CONST CONST_IDENT opt_attributes '=' expression
|
||||||
| CONST type CONST_IDENT opt_attributes '=' initializer ';'
|
| CONST type CONST_IDENT opt_attributes '=' expression
|
||||||
;
|
;
|
||||||
|
|
||||||
func_typedef
|
func_typedef
|
||||||
: FN optional_type opt_parameter_type_list
|
: FN optional_type opt_parameter_type_list
|
||||||
@@ -579,9 +732,24 @@ typedef_declaration
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
multi_declaration
|
||||||
|
: ',' IDENT
|
||||||
|
| multi_declaration ',' IDENT
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_multi_declaration
|
||||||
|
: multi_declaration
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
global_storage
|
||||||
|
: TLOCAL
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
global_declaration
|
global_declaration
|
||||||
: type IDENT opt_attributes ';'
|
: global_storage optional_type IDENT opt_multi_declaration opt_attributes ';'
|
||||||
| type IDENT opt_attributes '=' initializer ';'
|
| global_storage optional_type IDENT '=' constant_expr ';'
|
||||||
;
|
;
|
||||||
|
|
||||||
ct_if
|
ct_if
|
||||||
@@ -620,22 +788,22 @@ conditional_compilation
|
|||||||
| ct_switch tl_ct_switch_body CT_ENDSWITCH
|
| ct_switch tl_ct_switch_body CT_ENDSWITCH
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
module_param
|
module_param
|
||||||
: CT_IDENT
|
: CONST_IDENT
|
||||||
| HASH_IDENT
|
|
||||||
| TYPE_IDENT
|
| TYPE_IDENT
|
||||||
| CT_TYPE_IDENT
|
|
||||||
| IDENT
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
module_params
|
module_params
|
||||||
: module_param
|
: module_param
|
||||||
| module_params ',' module_param
|
| module_params ',' module_param
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Checked for 0.5 */
|
||||||
module
|
module
|
||||||
: MODULE import_path opt_attributes';'
|
: MODULE import_path opt_attributes ';'
|
||||||
| MODULE import_path '<' module_params '>' ';'
|
| MODULE import_path '<' module_params '>' opt_attributes ';'
|
||||||
;
|
;
|
||||||
|
|
||||||
import_decl
|
import_decl
|
||||||
@@ -654,14 +822,14 @@ top_level_statements
|
|||||||
|
|
||||||
|
|
||||||
top_level
|
top_level
|
||||||
: func_definition
|
: function_definition
|
||||||
| module
|
| module
|
||||||
| import_decl
|
| import_decl
|
||||||
| conditional_compilation
|
| conditional_compilation
|
||||||
| struct_declaration
|
| struct_declaration
|
||||||
| enum_declaration
|
| enum_declaration
|
||||||
| fault_declaration
|
| fault_declaration
|
||||||
| const_declaration
|
| const_declaration ';'
|
||||||
| global_declaration
|
| global_declaration
|
||||||
| macro_declaration
|
| macro_declaration
|
||||||
| typedef_declaration
|
| typedef_declaration
|
||||||
|
|||||||
@@ -1142,7 +1142,7 @@ struct Expr_
|
|||||||
ExprVariant variant_expr;
|
ExprVariant variant_expr;
|
||||||
ExprPointerOffset pointer_offset_expr;
|
ExprPointerOffset pointer_offset_expr;
|
||||||
ExprAsmArg expr_asm_arg;
|
ExprAsmArg expr_asm_arg;
|
||||||
OperatorOverload expr_operator_chars;
|
OperatorOverload overload_expr;
|
||||||
TypeInfo *type_expr; // 8
|
TypeInfo *type_expr; // 8
|
||||||
ExprConst const_expr; // 32
|
ExprConst const_expr; // 32
|
||||||
ExprArgv argv_expr; // 16
|
ExprArgv argv_expr; // 16
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
static bool context_next_is_path_prefix_start(ParseContext *c);
|
static bool context_next_is_path_prefix_start(ParseContext *c);
|
||||||
static Decl *parse_const_declaration(ParseContext *c, bool is_global);
|
static Decl *parse_const_declaration(ParseContext *c, bool is_global);
|
||||||
static inline Decl *parse_func_definition(ParseContext *c, AstId docs, bool is_interface);
|
static inline Decl *parse_func_definition(ParseContext *c, AstId contracts, bool is_interface);
|
||||||
static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl);
|
static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl);
|
||||||
static inline Decl *parse_static_top_level(ParseContext *c);
|
static inline Decl *parse_static_top_level(ParseContext *c);
|
||||||
static Decl *parse_include(ParseContext *c);
|
static Decl *parse_include(ParseContext *c);
|
||||||
@@ -502,9 +502,11 @@ bool parse_path_prefix(ParseContext *c, Path** path_ref)
|
|||||||
* | FLOAT16
|
* | FLOAT16
|
||||||
* | FLOAT128
|
* | FLOAT128
|
||||||
* | TYPE_IDENT
|
* | TYPE_IDENT
|
||||||
* | ident_scope TYPE_IDENT
|
* | path_prefix TYPE_IDENT
|
||||||
* | CT_TYPE_IDENT
|
* | CT_TYPE_IDENT
|
||||||
* | CT_TYPEOF '(' expr ')'
|
* | CT_TYPEOF '(' expr ')'
|
||||||
|
* | CT_TYPEFROM '(' expr ')'
|
||||||
|
* | CT_VATYPE '(' expr ')'
|
||||||
* | CT_EVALTYPE '(' expr ')'
|
* | CT_EVALTYPE '(' expr ')'
|
||||||
* ;
|
* ;
|
||||||
*
|
*
|
||||||
@@ -785,10 +787,7 @@ TypeInfo *parse_optional_type(ParseContext *c)
|
|||||||
// --- Decl parsing
|
// --- Decl parsing
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse ident ('=' expr)?
|
* after_type ::= (CT_IDENT | IDENT) attributes? ('=' decl_initializer)?
|
||||||
* @param is_static
|
|
||||||
* @param type
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type)
|
Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type)
|
||||||
{
|
{
|
||||||
@@ -859,25 +858,30 @@ Decl *parse_local_decl(ParseContext *c)
|
|||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decl_or_expr ::= var_decl | type local_decl_after_type | expression
|
||||||
|
*/
|
||||||
Expr *parse_decl_or_expr(ParseContext *c, Decl **decl_ref)
|
Expr *parse_decl_or_expr(ParseContext *c, Decl **decl_ref)
|
||||||
{
|
{
|
||||||
|
// var-initialization is done separately.
|
||||||
if (tok_is(c, TOKEN_VAR))
|
if (tok_is(c, TOKEN_VAR))
|
||||||
{
|
{
|
||||||
ASSIGN_DECL_OR_RET(*decl_ref, parse_var_decl(c), poisoned_expr);
|
ASSIGN_DECL_OR_RET(*decl_ref, parse_var_decl(c), poisoned_expr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
TypeInfo *type_info;
|
|
||||||
Expr *expr = parse_expr(c);
|
Expr *expr = parse_expr(c);
|
||||||
|
|
||||||
|
// If it's not a type info, we assume an expr.
|
||||||
if (expr->expr_kind != EXPR_TYPEINFO) return expr;
|
if (expr->expr_kind != EXPR_TYPEINFO) return expr;
|
||||||
|
|
||||||
|
// Otherwise we expect a declaration.
|
||||||
ASSIGN_DECL_OR_RET(*decl_ref, parse_local_decl_after_type(c, expr->type_expr), poisoned_expr);
|
ASSIGN_DECL_OR_RET(*decl_ref, parse_local_decl_after_type(c, expr->type_expr), poisoned_expr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* const_decl
|
* const_decl ::= 'const' type? CONST_IDENT attributes? '=' const_expr
|
||||||
* : 'const' type? IDENT '=' const_expr
|
|
||||||
* ;
|
|
||||||
*/
|
*/
|
||||||
static Decl *parse_const_declaration(ParseContext *c, bool is_global)
|
static Decl *parse_const_declaration(ParseContext *c, bool is_global)
|
||||||
{
|
{
|
||||||
@@ -885,14 +889,19 @@ static Decl *parse_const_declaration(ParseContext *c, bool is_global)
|
|||||||
|
|
||||||
TypeInfo *type_info = NULL;
|
TypeInfo *type_info = NULL;
|
||||||
|
|
||||||
|
// If not a const ident, assume we want the type
|
||||||
if (c->tok != TOKEN_CONST_IDENT)
|
if (c->tok != TOKEN_CONST_IDENT)
|
||||||
{
|
{
|
||||||
ASSIGN_TYPE_OR_RET(type_info, parse_type(c), poisoned_decl);
|
ASSIGN_TYPE_OR_RET(type_info, parse_type(c), poisoned_decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the decl
|
||||||
Decl *decl = decl_new_var(symstr(c), c->span, type_info, VARDECL_CONST);
|
Decl *decl = decl_new_var(symstr(c), c->span, type_info, VARDECL_CONST);
|
||||||
|
|
||||||
|
// Check the name
|
||||||
if (!consume_const_name(c, "const")) return poisoned_decl;
|
if (!consume_const_name(c, "const")) return poisoned_decl;
|
||||||
|
|
||||||
|
// Differentiate between global and local attributes, global have visibility
|
||||||
if (is_global)
|
if (is_global)
|
||||||
{
|
{
|
||||||
if (!parse_attributes_for_global(c, decl)) return false;
|
if (!parse_attributes_for_global(c, decl)) return false;
|
||||||
@@ -901,17 +910,22 @@ static Decl *parse_const_declaration(ParseContext *c, bool is_global)
|
|||||||
{
|
{
|
||||||
if (!parse_attributes(c, &decl->attributes, NULL)) return poisoned_decl;
|
if (!parse_attributes(c, &decl->attributes, NULL)) return poisoned_decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Required initializer
|
||||||
CONSUME_OR_RET(TOKEN_EQ, poisoned_decl);
|
CONSUME_OR_RET(TOKEN_EQ, poisoned_decl);
|
||||||
|
|
||||||
if (!parse_decl_initializer(c, decl)) return poisoned_decl;
|
if (!parse_decl_initializer(c, decl)) return poisoned_decl;
|
||||||
|
|
||||||
RANGE_EXTEND_PREV(decl);
|
RANGE_EXTEND_PREV(decl);
|
||||||
|
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* var_decl ::= VAR (IDENT '=' expression) | (CT_IDENT ('=' expression)?) | (CT_TYPE_IDENT ('=' expression)?)
|
||||||
|
*/
|
||||||
Decl *parse_var_decl(ParseContext *c)
|
Decl *parse_var_decl(ParseContext *c)
|
||||||
{
|
{
|
||||||
|
// CT variants will naturally be macro only, for runtime variables it is enforced in the semantic
|
||||||
|
// analyser. The runtime variables must have an initializer unlike the CT ones.
|
||||||
advance_and_verify(c, TOKEN_VAR);
|
advance_and_verify(c, TOKEN_VAR);
|
||||||
Decl *decl;
|
Decl *decl;
|
||||||
switch (c->tok)
|
switch (c->tok)
|
||||||
@@ -957,34 +971,43 @@ Decl *parse_var_decl(ParseContext *c)
|
|||||||
|
|
||||||
// --- Parse parameters & throws & attributes
|
// --- Parse parameters & throws & attributes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* attribute ::= (AT_IDENT | path_prefix? AT_TYPE_IDENT) attr_params?
|
||||||
|
* attr_params ::= '(' attr_param (',' attr_param)* ')'
|
||||||
|
* attr_param ::= const_expr | '&' '[' ']' || '[' ']' '='?
|
||||||
|
*/
|
||||||
bool parse_attribute(ParseContext *c, Attr **attribute_ref)
|
bool parse_attribute(ParseContext *c, Attr **attribute_ref)
|
||||||
{
|
{
|
||||||
bool had_error;
|
bool had_error;
|
||||||
Path *path;
|
Path *path;
|
||||||
if (!parse_path_prefix(c, &path)) return false;
|
if (!parse_path_prefix(c, &path)) return false;
|
||||||
|
|
||||||
|
// Something not starting with `@` in attribute position:
|
||||||
if (!tok_is(c, TOKEN_AT_IDENT) && !tok_is(c, TOKEN_AT_TYPE_IDENT))
|
if (!tok_is(c, TOKEN_AT_IDENT) && !tok_is(c, TOKEN_AT_TYPE_IDENT))
|
||||||
{
|
{
|
||||||
if (path)
|
// Started a path? If so hard error
|
||||||
{
|
if (path) RETURN_SEMA_ERROR_HERE("Expected an attribute name.");
|
||||||
SEMA_ERROR_HERE("Expected an attribute name.");
|
|
||||||
return false;
|
// Otherwise assume no attributes
|
||||||
}
|
|
||||||
*attribute_ref = NULL;
|
*attribute_ref = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Attr *attr = CALLOCS(Attr);
|
|
||||||
|
|
||||||
|
// Create an attribute
|
||||||
|
Attr *attr = CALLOCS(Attr);
|
||||||
attr->name = symstr(c);
|
attr->name = symstr(c);
|
||||||
attr->span = c->span;
|
attr->span = c->span;
|
||||||
attr->path = path;
|
attr->path = path;
|
||||||
|
|
||||||
|
// Pre-defined idents
|
||||||
if (tok_is(c, TOKEN_AT_IDENT))
|
if (tok_is(c, TOKEN_AT_IDENT))
|
||||||
{
|
{
|
||||||
|
// Error for foo::bar::@inline
|
||||||
|
if (path) RETURN_SEMA_ERROR_HERE("Only user-defined attribute names can have a module path prefix.");
|
||||||
|
|
||||||
|
// Check attribute it exists, theoretically we could defer this to semantic analysis
|
||||||
AttributeType type = attribute_by_name(attr->name);
|
AttributeType type = attribute_by_name(attr->name);
|
||||||
if (type == ATTRIBUTE_NONE)
|
if (type == ATTRIBUTE_NONE) RETURN_SEMA_ERROR_HERE("This is not a known valid attribute name.");
|
||||||
{
|
|
||||||
SEMA_ERROR_HERE("This is not a known valid attribute name.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
attr->attr_kind = type;
|
attr->attr_kind = type;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -992,9 +1015,9 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref)
|
|||||||
attr->is_custom = true;
|
attr->is_custom = true;
|
||||||
}
|
}
|
||||||
advance(c);
|
advance(c);
|
||||||
|
|
||||||
Expr **list = NULL;
|
Expr **list = NULL;
|
||||||
|
|
||||||
|
// Consume the optional (expr | attr_param, ...)
|
||||||
if (try_consume(c, TOKEN_LPAREN))
|
if (try_consume(c, TOKEN_LPAREN))
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
@@ -1009,16 +1032,16 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref)
|
|||||||
advance(c);
|
advance(c);
|
||||||
CONSUME_OR_RET(TOKEN_LBRACKET, false);
|
CONSUME_OR_RET(TOKEN_LBRACKET, false);
|
||||||
CONSUME_OR_RET(TOKEN_RBRACKET, false);
|
CONSUME_OR_RET(TOKEN_RBRACKET, false);
|
||||||
expr->expr_operator_chars = OVERLOAD_ELEMENT_REF;
|
expr->overload_expr = OVERLOAD_ELEMENT_REF;
|
||||||
RANGE_EXTEND_PREV(expr);
|
RANGE_EXTEND_PREV(expr);
|
||||||
break;
|
break;
|
||||||
case TOKEN_LBRACKET:
|
case TOKEN_LBRACKET:
|
||||||
// []
|
// [] and []=
|
||||||
expr = EXPR_NEW_TOKEN(EXPR_OPERATOR_CHARS);
|
expr = EXPR_NEW_TOKEN(EXPR_OPERATOR_CHARS);
|
||||||
expr->resolve_status = RESOLVE_DONE;
|
expr->resolve_status = RESOLVE_DONE;
|
||||||
advance(c);
|
advance(c);
|
||||||
CONSUME_OR_RET(TOKEN_RBRACKET, false);
|
CONSUME_OR_RET(TOKEN_RBRACKET, false);
|
||||||
expr->expr_operator_chars = try_consume(c, TOKEN_EQ) ? OVERLOAD_ELEMENT_SET : OVERLOAD_ELEMENT_AT;
|
expr->overload_expr = try_consume(c, TOKEN_EQ) ? OVERLOAD_ELEMENT_SET : OVERLOAD_ELEMENT_AT;
|
||||||
RANGE_EXTEND_PREV(expr);
|
RANGE_EXTEND_PREV(expr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1033,11 +1056,13 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
attr->exprs = list;
|
attr->exprs = list;
|
||||||
|
|
||||||
*attribute_ref = attr;
|
*attribute_ref = attr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse global attributes, setting visibility defaults from the parent unit.
|
||||||
|
*/
|
||||||
static bool parse_attributes_for_global(ParseContext *c, Decl *decl)
|
static bool parse_attributes_for_global(ParseContext *c, Decl *decl)
|
||||||
{
|
{
|
||||||
Visibility visibility = c->unit->default_visibility;
|
Visibility visibility = c->unit->default_visibility;
|
||||||
@@ -1049,13 +1074,9 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* attribute_list
|
* attribute_list ::= attribute*
|
||||||
* : attribute
|
|
||||||
* | attribute_list attribute
|
|
||||||
* ;
|
|
||||||
*
|
*
|
||||||
* attribute
|
* Patch visibility attributes immediately.
|
||||||
* : path AT_IDENT | AT_TYPE_IDENT ('(' constant_expression ')')?
|
|
||||||
*
|
*
|
||||||
* @return true if parsing succeeded, false if recovery is needed
|
* @return true if parsing succeeded, false if recovery is needed
|
||||||
*/
|
*/
|
||||||
@@ -1070,6 +1091,9 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visib
|
|||||||
Visibility parsed_visibility = -1;
|
Visibility parsed_visibility = -1;
|
||||||
if (!attr->is_custom)
|
if (!attr->is_custom)
|
||||||
{
|
{
|
||||||
|
// This is important: if we would allow user defined attributes,
|
||||||
|
// ordering between visibility of attributes would be complex.
|
||||||
|
// since there is little
|
||||||
switch (attr->attr_kind)
|
switch (attr->attr_kind)
|
||||||
{
|
{
|
||||||
case ATTRIBUTE_PUBLIC:
|
case ATTRIBUTE_PUBLIC:
|
||||||
@@ -1086,27 +1110,15 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visib
|
|||||||
}
|
}
|
||||||
if (parsed_visibility != -1)
|
if (parsed_visibility != -1)
|
||||||
{
|
{
|
||||||
if (!visibility_ref)
|
if (!visibility_ref) RETURN_SEMA_ERROR(attr, "'%s' cannot be used here.");
|
||||||
{
|
if (visibility != -1) RETURN_SEMA_ERROR(attr, "Only a single visibility attribute may be added.");
|
||||||
SEMA_ERROR(attr, "'%s' cannot be used here.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (visibility != -1)
|
|
||||||
{
|
|
||||||
SEMA_ERROR(attr, "Only a single visibility attribute may be added.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*visibility_ref = visibility = parsed_visibility;
|
*visibility_ref = visibility = parsed_visibility;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const char *name = attr->name;
|
const char *name = attr->name;
|
||||||
FOREACH_BEGIN(Attr *other_attr, *attributes_ref)
|
FOREACH_BEGIN(Attr *other_attr, *attributes_ref)
|
||||||
if (other_attr->name == name)
|
if (other_attr->name == name) RETURN_SEMA_ERROR(attr, "Repeat of attribute '%s' here.", name);
|
||||||
{
|
|
||||||
SEMA_ERROR(attr, "Repeat of attribute '%s' here.", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FOREACH_END();
|
FOREACH_END();
|
||||||
vec_add(*attributes_ref, attr);
|
vec_add(*attributes_ref, attr);
|
||||||
}
|
}
|
||||||
@@ -1115,13 +1127,8 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visib
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* global_declaration
|
* global_declaration ::= TLOCAL? optional_type IDENT (('=' expression)? | (',' IDENT)* opt_attributes) ';'
|
||||||
* : global? optional_type IDENT ';'
|
|
||||||
* | global? optional_type IDENT '=' expression ';'
|
|
||||||
* | global? optional_type func_definition
|
|
||||||
* ;
|
|
||||||
*
|
*
|
||||||
* @param visibility
|
|
||||||
* @return true if parsing succeeded
|
* @return true if parsing succeeded
|
||||||
*/
|
*/
|
||||||
static inline Decl *parse_global_declaration(ParseContext *c)
|
static inline Decl *parse_global_declaration(ParseContext *c)
|
||||||
@@ -1130,7 +1137,6 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
|||||||
|
|
||||||
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), poisoned_decl);
|
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), poisoned_decl);
|
||||||
|
|
||||||
|
|
||||||
if (tok_is(c, TOKEN_CONST_IDENT))
|
if (tok_is(c, TOKEN_CONST_IDENT))
|
||||||
{
|
{
|
||||||
SEMA_ERROR_HERE("This looks like a constant variable, did you forget 'const'?");
|
SEMA_ERROR_HERE("This looks like a constant variable, did you forget 'const'?");
|
||||||
@@ -1139,9 +1145,11 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
|||||||
|
|
||||||
Decl *decl;
|
Decl *decl;
|
||||||
Decl **decls = NULL;
|
Decl **decls = NULL;
|
||||||
|
// Parse IDENT (',' IDENT)*
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
decl = decl_new_var_current(c, type, VARDECL_GLOBAL);
|
decl = decl_new_var_current(c, type, VARDECL_GLOBAL);
|
||||||
|
// Update threadlocal setting
|
||||||
decl->var.is_threadlocal = threadlocal;
|
decl->var.is_threadlocal = threadlocal;
|
||||||
if (!try_consume(c, TOKEN_IDENT))
|
if (!try_consume(c, TOKEN_IDENT))
|
||||||
{
|
{
|
||||||
@@ -1161,6 +1169,7 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
|||||||
|
|
||||||
if (!parse_attributes_for_global(c, decl)) return poisoned_decl;
|
if (!parse_attributes_for_global(c, decl)) return poisoned_decl;
|
||||||
|
|
||||||
|
// If we get '=' we can't have multiple idents.
|
||||||
if (try_consume(c, TOKEN_EQ))
|
if (try_consume(c, TOKEN_EQ))
|
||||||
{
|
{
|
||||||
if (decls)
|
if (decls)
|
||||||
@@ -1172,12 +1181,13 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
|||||||
}
|
}
|
||||||
else if (!decl->attributes && tok_is(c, TOKEN_LPAREN) && !threadlocal)
|
else if (!decl->attributes && tok_is(c, TOKEN_LPAREN) && !threadlocal)
|
||||||
{
|
{
|
||||||
// Guess we forgot `fn`?
|
// Guess we forgot `fn`? -> improve error reporting.
|
||||||
sema_error_at(type->span, "This looks like the beginning of a function declaration but it's missing the initial `fn`. Did you forget it?");
|
sema_error_at(type->span, "This looks like the beginning of a function declaration but it's missing the initial `fn`. Did you forget it?");
|
||||||
return poisoned_decl;
|
return poisoned_decl;
|
||||||
}
|
}
|
||||||
CONSUME_EOS_OR_RET(poisoned_decl);
|
CONSUME_EOS_OR_RET(poisoned_decl);
|
||||||
Attr **attributes = decl->attributes;
|
Attr **attributes = decl->attributes;
|
||||||
|
// Copy the attributes to the other variables.
|
||||||
if (attributes)
|
if (attributes)
|
||||||
{
|
{
|
||||||
FOREACH_BEGIN(Decl *d, decls)
|
FOREACH_BEGIN(Decl *d, decls)
|
||||||
@@ -1185,6 +1195,7 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
|||||||
d->attributes = copy_attributes_single(attributes);
|
d->attributes = copy_attributes_single(attributes);
|
||||||
FOREACH_END();
|
FOREACH_END();
|
||||||
}
|
}
|
||||||
|
// If we have multiple decls, then we return that as a bundled decl_globals
|
||||||
if (decls)
|
if (decls)
|
||||||
{
|
{
|
||||||
decl = decl_calloc();
|
decl = decl_calloc();
|
||||||
@@ -1198,46 +1209,23 @@ static inline Decl *parse_global_declaration(ParseContext *c)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* param_declaration ::= type_expression '...'?) (IDENT ('=' initializer)?)?
|
* enum_param_decl ::= type IDENT ('=' expr)?
|
||||||
* ;
|
|
||||||
*/
|
*/
|
||||||
static inline bool parse_param_decl(ParseContext *c, Decl*** parameters, bool require_name)
|
static inline bool parse_enum_param_decl(ParseContext *c, Decl*** parameters)
|
||||||
{
|
{
|
||||||
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), false);
|
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), false);
|
||||||
if (type->optional)
|
if (type->optional) RETURN_SEMA_ERROR(type, "Parameters may not be optional.");
|
||||||
{
|
|
||||||
SEMA_ERROR(type, "Parameters may not be optional.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool vararg = try_consume(c, TOKEN_ELLIPSIS);
|
|
||||||
Decl *param = decl_new_var_current(c, type, VARDECL_PARAM);
|
Decl *param = decl_new_var_current(c, type, VARDECL_PARAM);
|
||||||
param->var.vararg = vararg;
|
|
||||||
if (!try_consume(c, TOKEN_IDENT))
|
if (!try_consume(c, TOKEN_IDENT))
|
||||||
{
|
{
|
||||||
param->name = NULL;
|
if (token_is_keyword(c->tok)) RETURN_SEMA_ERROR_HERE("Keywords cannot be used as member names.");
|
||||||
|
if (token_is_some_ident(c->tok)) RETURN_SEMA_ERROR_HERE("Expected a name starting with a lower-case letter.");
|
||||||
|
RETURN_SEMA_ERROR_HERE("Expected a member name here.");
|
||||||
}
|
}
|
||||||
const char *name = param->name;
|
if (try_consume(c, TOKEN_EQ))
|
||||||
|
|
||||||
if (!name && require_name)
|
|
||||||
{
|
|
||||||
if (!tok_is(c, TOKEN_COMMA) && !tok_is(c, TOKEN_RPAREN))
|
|
||||||
{
|
|
||||||
if (tok_is(c, TOKEN_CT_IDENT))
|
|
||||||
{
|
|
||||||
SEMA_ERROR_HERE("Compile time identifiers are only allowed as macro parameters.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sema_error_at_after(type->span, "Unexpected end of the parameter list, did you forget an ')'?");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
SEMA_ERROR(type, "The parameter must be named.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (name && try_consume(c, TOKEN_EQ))
|
|
||||||
{
|
{
|
||||||
if (!parse_decl_initializer(c, param)) return poisoned_decl;
|
if (!parse_decl_initializer(c, param)) return poisoned_decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec_add(*parameters, param);
|
vec_add(*parameters, param);
|
||||||
RANGE_EXTEND_PREV(param);
|
RANGE_EXTEND_PREV(param);
|
||||||
return true;
|
return true;
|
||||||
@@ -1463,6 +1451,7 @@ bool parse_parameters(ParseContext *c, Decl ***params_ref, Decl **body_params,
|
|||||||
}
|
}
|
||||||
Decl *param = decl_new_var(name, span, type, param_kind);
|
Decl *param = decl_new_var(name, span, type, param_kind);
|
||||||
param->var.type_info = type;
|
param->var.type_info = type;
|
||||||
|
if (!parse_attributes(c, ¶m->attributes, NULL)) return false;
|
||||||
if (!no_name)
|
if (!no_name)
|
||||||
{
|
{
|
||||||
if (try_consume(c, TOKEN_EQ))
|
if (try_consume(c, TOKEN_EQ))
|
||||||
@@ -1470,7 +1459,6 @@ bool parse_parameters(ParseContext *c, Decl ***params_ref, Decl **body_params,
|
|||||||
if (!parse_decl_initializer(c, param)) return poisoned_decl;
|
if (!parse_decl_initializer(c, param)) return poisoned_decl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!parse_attributes(c, ¶m->attributes, NULL)) return false;
|
|
||||||
if (ellipsis)
|
if (ellipsis)
|
||||||
{
|
{
|
||||||
var_arg_found = true;
|
var_arg_found = true;
|
||||||
@@ -1486,8 +1474,7 @@ bool parse_parameters(ParseContext *c, Decl ***params_ref, Decl **body_params,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* fn_parameter_list ::= '(' parameters ')'
|
||||||
* parameter_type_list ::= '(' parameters ')'
|
|
||||||
*/
|
*/
|
||||||
static inline bool parse_fn_parameter_list(ParseContext *c, Signature *signature, bool is_interface)
|
static inline bool parse_fn_parameter_list(ParseContext *c, Signature *signature, bool is_interface)
|
||||||
{
|
{
|
||||||
@@ -2081,8 +2068,8 @@ static inline bool parse_is_macro_name(ParseContext *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* func_header ::= type '!'? (type '.')? (IDENT | MACRO_IDENT)
|
* func_header ::= optional_type (type '.')? IDENT
|
||||||
* macro_header ::= (type '!'?)? (type '.')? (IDENT | MACRO_IDENT)
|
* macro_header ::= optional_type? (type '.')? (IDENT | MACRO_IDENT)
|
||||||
*/
|
*/
|
||||||
static inline bool parse_func_macro_header(ParseContext *c, Decl *decl)
|
static inline bool parse_func_macro_header(ParseContext *c, Decl *decl)
|
||||||
{
|
{
|
||||||
@@ -2229,31 +2216,25 @@ static inline Decl *parse_fault_declaration(ParseContext *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum_spec
|
* enum_spec ::= type ('(' enum_params ')')?
|
||||||
* : type
|
|
||||||
* | type '(' opt_parameter_type_list ')'
|
|
||||||
* ;
|
|
||||||
*/
|
*/
|
||||||
static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl*** parameters_ref)
|
static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl*** parameters_ref)
|
||||||
{
|
{
|
||||||
|
|
||||||
ASSIGN_TYPE_OR_RET(*type_ref, parse_optional_type(c), false);
|
ASSIGN_TYPE_OR_RET(*type_ref, parse_optional_type(c), false);
|
||||||
if ((*type_ref)->optional)
|
if ((*type_ref)->optional)
|
||||||
{
|
{
|
||||||
SEMA_ERROR(*type_ref, "An enum can't have an optional type.");
|
SEMA_ERROR(*type_ref, "An enum can't have an optional type.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// If no left parenthesis we're done.
|
||||||
if (!try_consume(c, TOKEN_LPAREN)) return true;
|
if (!try_consume(c, TOKEN_LPAREN)) return true;
|
||||||
|
|
||||||
|
// We allow (), but we might consider making it an error later on.
|
||||||
while (!try_consume(c, TOKEN_RPAREN))
|
while (!try_consume(c, TOKEN_RPAREN))
|
||||||
{
|
{
|
||||||
if (!parse_param_decl(c, parameters_ref, true)) return false;
|
if (!parse_enum_param_decl(c, parameters_ref)) return false;
|
||||||
Decl *last_parameter = VECLAST(*parameters_ref);
|
Decl *last_parameter = VECLAST(*parameters_ref);
|
||||||
assert(last_parameter);
|
assert(last_parameter);
|
||||||
if (last_parameter->var.vararg)
|
|
||||||
{
|
|
||||||
SEMA_ERROR_LAST("Vararg parameters are not allowed as enum parameters.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
last_parameter->var.index = vec_size(*parameters_ref) - 1;
|
last_parameter->var.index = vec_size(*parameters_ref) - 1;
|
||||||
if (!try_consume(c, TOKEN_COMMA))
|
if (!try_consume(c, TOKEN_COMMA))
|
||||||
{
|
{
|
||||||
@@ -2263,25 +2244,13 @@ static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl***
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expect current at enum name.
|
* Parse an enum declaration (after "enum")
|
||||||
*
|
|
||||||
* enum
|
|
||||||
* : ENUM type_ident '{' enum_body '}'
|
|
||||||
* | ENUM type_ident ':' enum_spec '{' enum_body '}'
|
|
||||||
* ;
|
|
||||||
*
|
|
||||||
* enum_body
|
|
||||||
* : enum_def
|
|
||||||
* | enum_def ',' enum_body
|
|
||||||
* | enum_body ','
|
|
||||||
* ;
|
|
||||||
*
|
|
||||||
* enum_def
|
|
||||||
* : CAPS_IDENT
|
|
||||||
* | CAPS_IDENT '(' expr_list ')'
|
|
||||||
* ;
|
|
||||||
*
|
*
|
||||||
|
* enum ::= ENUM TYPE_IDENT enum_spec? opt_attributes '{' enum_body '}'
|
||||||
|
* enum_body ::= enum_def (',' enum_def)* ','?
|
||||||
|
* enum_def ::= CONST_IDENT ('(' arg_list ')')?
|
||||||
*/
|
*/
|
||||||
static inline Decl *parse_enum_declaration(ParseContext *c)
|
static inline Decl *parse_enum_declaration(ParseContext *c)
|
||||||
{
|
{
|
||||||
@@ -2291,6 +2260,7 @@ static inline Decl *parse_enum_declaration(ParseContext *c)
|
|||||||
if (!consume_type_name(c, "enum")) return poisoned_decl;
|
if (!consume_type_name(c, "enum")) return poisoned_decl;
|
||||||
|
|
||||||
TypeInfo *type = NULL;
|
TypeInfo *type = NULL;
|
||||||
|
// Parse the spec
|
||||||
if (try_consume(c, TOKEN_COLON))
|
if (try_consume(c, TOKEN_COLON))
|
||||||
{
|
{
|
||||||
if (!parse_enum_spec(c, &type, &decl->enums.parameters)) return poisoned_decl;
|
if (!parse_enum_spec(c, &type, &decl->enums.parameters)) return poisoned_decl;
|
||||||
@@ -2302,7 +2272,6 @@ static inline Decl *parse_enum_declaration(ParseContext *c)
|
|||||||
CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl);
|
CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl);
|
||||||
|
|
||||||
decl->enums.type_info = type ? type : type_info_new_base(type_int, decl->span);
|
decl->enums.type_info = type ? type : type_info_new_base(type_int, decl->span);
|
||||||
|
|
||||||
while (!try_consume(c, TOKEN_RBRACE))
|
while (!try_consume(c, TOKEN_RBRACE))
|
||||||
{
|
{
|
||||||
Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, symstr(c), c->span);
|
Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, symstr(c), c->span);
|
||||||
@@ -2342,8 +2311,6 @@ static inline Decl *parse_enum_declaration(ParseContext *c)
|
|||||||
|
|
||||||
// --- Parse function
|
// --- Parse function
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts after 'fn'
|
* Starts after 'fn'
|
||||||
*
|
*
|
||||||
@@ -2365,12 +2332,12 @@ static inline Decl *parse_enum_declaration(ParseContext *c)
|
|||||||
* @param visibility
|
* @param visibility
|
||||||
* @return Decl*
|
* @return Decl*
|
||||||
*/
|
*/
|
||||||
static inline Decl *parse_func_definition(ParseContext *c, AstId docs, bool is_interface)
|
static inline Decl *parse_func_definition(ParseContext *c, AstId contracts, bool is_interface)
|
||||||
{
|
{
|
||||||
advance_and_verify(c, TOKEN_FN);
|
advance_and_verify(c, TOKEN_FN);
|
||||||
Decl *func = decl_calloc();
|
Decl *func = decl_calloc();
|
||||||
func->decl_kind = DECL_FUNC;
|
func->decl_kind = DECL_FUNC;
|
||||||
func->func_decl.docs = docs;
|
func->func_decl.docs = contracts;
|
||||||
if (!parse_func_macro_header(c, func)) return poisoned_decl;
|
if (!parse_func_macro_header(c, func)) return poisoned_decl;
|
||||||
if (func->name[0] == '@')
|
if (func->name[0] == '@')
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Ast* parse_compound_stmt(ParseContext *c);
|
|||||||
Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos);
|
Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos);
|
||||||
Ast *parse_jump_stmt_no_eos(ParseContext *c);
|
Ast *parse_jump_stmt_no_eos(ParseContext *c);
|
||||||
bool parse_attribute(ParseContext *c, Attr **attribute_ref);
|
bool parse_attribute(ParseContext *c, Attr **attribute_ref);
|
||||||
bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility);
|
bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref);
|
||||||
|
|
||||||
bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type);
|
bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type);
|
||||||
Expr *parse_ct_expression_list(ParseContext *c, bool allow_decl);
|
Expr *parse_ct_expression_list(ParseContext *c, bool allow_decl);
|
||||||
|
|||||||
@@ -1605,7 +1605,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
|
|||||||
decl->operator = OVERLOAD_LEN;
|
decl->operator = OVERLOAD_LEN;
|
||||||
break;
|
break;
|
||||||
case EXPR_OPERATOR_CHARS:
|
case EXPR_OPERATOR_CHARS:
|
||||||
decl->operator = expr->expr_operator_chars;
|
decl->operator = expr->overload_expr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto FAILED_OP_TYPE;
|
goto FAILED_OP_TYPE;
|
||||||
|
|||||||
4
test/test_suite/attributes/attribute_path.c3
Normal file
4
test/test_suite/attributes/attribute_path.c3
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
fn void test() abc::@inline // #error: Only user-defined attribute names
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
|
|
||||||
enum EnumWithErrorWithMissingName : int (int) // #error: The parameter must be named
|
enum EnumWithErrorWithMissingName : int (int) // #error: Expected a member name here
|
||||||
{
|
{
|
||||||
TEST
|
TEST
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EnumWithErrorData : int (int // #error: end of the parameter list
|
enum EnumWithErrorData : int (int
|
||||||
{
|
{ // #error: Expected a member name here
|
||||||
TEST
|
TEST
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EnumWithErrorData2 : int (int, int bar) // #error: The parameter must be named
|
enum EnumWithErrorData2 : int (int, int bar) // #error: Expected a member name here
|
||||||
{
|
{
|
||||||
TEST
|
TEST
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user