2001-09-28 07:09:38 +00:00
|
|
|
|
/*
|
2002-11-06 16:32:28 +00:00
|
|
|
|
qc-parse.y
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
2002-11-06 16:32:28 +00:00
|
|
|
|
parser for quakec
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
2002-11-06 16:32:28 +00:00
|
|
|
|
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
2002-11-06 16:32:28 +00:00
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
|
|
|
Date: 2001/06/12
|
2001-09-28 07:09:38 +00:00
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
|
|
*/
|
2023-10-08 01:57:57 +00:00
|
|
|
|
%define api.prefix {qc_yy}
|
2023-10-10 17:34:39 +00:00
|
|
|
|
%define api.pure full
|
|
|
|
|
%define api.push-pull push
|
2023-10-24 10:50:31 +00:00
|
|
|
|
%define api.token.prefix {QC_}
|
2023-10-08 01:57:57 +00:00
|
|
|
|
%locations
|
2023-10-10 17:34:39 +00:00
|
|
|
|
%parse-param {void *scanner}
|
2024-04-18 03:41:24 +00:00
|
|
|
|
%define api.value.type {rua_val_t}
|
|
|
|
|
%define api.location.type {rua_loc_t}
|
2023-10-10 17:34:39 +00:00
|
|
|
|
|
2023-10-08 01:57:57 +00:00
|
|
|
|
%{
|
2002-06-01 04:41:25 +00:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
# include "config.h"
|
|
|
|
|
#endif
|
2003-01-14 20:18:29 +00:00
|
|
|
|
|
2002-06-01 04:41:25 +00:00
|
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
|
# include <string.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
|
# include <strings.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
2001-10-24 22:50:06 +00:00
|
|
|
|
#include <QF/hash.h>
|
|
|
|
|
#include <QF/sys.h>
|
2020-03-04 07:31:28 +00:00
|
|
|
|
#include <QF/va.h>
|
2001-06-15 19:38:43 +00:00
|
|
|
|
|
2023-10-20 11:31:15 +00:00
|
|
|
|
#define QC_YYDEBUG 1
|
|
|
|
|
#define QC_YYERROR_VERBOSE 1
|
|
|
|
|
#undef QC_YYERROR_VERBOSE
|
|
|
|
|
|
2023-08-21 08:37:56 +00:00
|
|
|
|
#include "tools/qfcc/include/algebra.h"
|
2022-02-02 14:51:37 +00:00
|
|
|
|
#include "tools/qfcc/include/attribute.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/class.h"
|
|
|
|
|
#include "tools/qfcc/include/debug.h"
|
|
|
|
|
#include "tools/qfcc/include/def.h"
|
|
|
|
|
#include "tools/qfcc/include/diagnostic.h"
|
|
|
|
|
#include "tools/qfcc/include/emit.h"
|
|
|
|
|
#include "tools/qfcc/include/expr.h"
|
|
|
|
|
#include "tools/qfcc/include/function.h"
|
2024-08-28 01:18:21 +00:00
|
|
|
|
#include "tools/qfcc/include/grab.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/method.h"
|
|
|
|
|
#include "tools/qfcc/include/options.h"
|
|
|
|
|
#include "tools/qfcc/include/qfcc.h"
|
|
|
|
|
#include "tools/qfcc/include/reloc.h"
|
2023-10-20 11:31:15 +00:00
|
|
|
|
#include "tools/qfcc/include/rua-lang.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/shared.h"
|
2024-09-19 16:39:44 +00:00
|
|
|
|
#include "tools/qfcc/include/spirv.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
|
#include "tools/qfcc/include/strpool.h"
|
|
|
|
|
#include "tools/qfcc/include/struct.h"
|
|
|
|
|
#include "tools/qfcc/include/switch.h"
|
|
|
|
|
#include "tools/qfcc/include/symtab.h"
|
|
|
|
|
#include "tools/qfcc/include/type.h"
|
|
|
|
|
#include "tools/qfcc/include/value.h"
|
2001-10-25 06:41:52 +00:00
|
|
|
|
|
2023-10-08 01:57:57 +00:00
|
|
|
|
#include "tools/qfcc/source/qc-parse.h"
|
2001-06-18 22:51:49 +00:00
|
|
|
|
|
2023-10-10 17:34:39 +00:00
|
|
|
|
#define qc_yytext qc_yyget_text (scanner)
|
|
|
|
|
char *qc_yyget_text (void *scanner);
|
2001-06-18 22:51:49 +00:00
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
|
static void
|
2023-10-10 17:34:39 +00:00
|
|
|
|
yyerror (YYLTYPE *yylloc, void *scanner, const char *s)
|
2001-06-12 20:24:02 +00:00
|
|
|
|
{
|
2023-10-08 01:57:57 +00:00
|
|
|
|
#ifdef QC_YYERROR_VERBOSE
|
2012-10-26 07:01:41 +00:00
|
|
|
|
error (0, "%s %s\n", qc_yytext, s);
|
2003-02-25 07:48:12 +00:00
|
|
|
|
#else
|
2012-10-26 07:01:41 +00:00
|
|
|
|
error (0, "%s before %s", s, qc_yytext);
|
2003-02-25 07:48:12 +00:00
|
|
|
|
#endif
|
2001-06-12 20:24:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
|
static void
|
2023-10-10 17:34:39 +00:00
|
|
|
|
parse_error (void *scanner)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2012-10-26 07:01:41 +00:00
|
|
|
|
error (0, "parse error before %s", qc_yytext);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-10 17:34:39 +00:00
|
|
|
|
#define PARSE_ERROR do { parse_error (scanner); YYERROR; } while (0)
|
2002-05-15 19:10:23 +00:00
|
|
|
|
|
2024-08-30 04:13:13 +00:00
|
|
|
|
#define YYLLOC_DEFAULT(Current, Rhs, N) RUA_LOC_DEFAULT(Current, Rhs, N)
|
|
|
|
|
#define YYLOCATION_PRINT rua_print_location
|
2023-11-06 04:41:17 +00:00
|
|
|
|
|
2023-10-08 01:57:57 +00:00
|
|
|
|
int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
2001-06-21 07:08:34 +00:00
|
|
|
|
|
2001-06-12 19:44:26 +00:00
|
|
|
|
%}
|
|
|
|
|
|
2024-04-18 03:41:24 +00:00
|
|
|
|
%code requires { #define qc_yypstate rua_yypstate }
|
2001-06-12 20:24:02 +00:00
|
|
|
|
|
2012-11-04 01:27:41 +00:00
|
|
|
|
// these tokens are common between qc and qp
|
|
|
|
|
%left LOW
|
2007-04-28 08:49:07 +00:00
|
|
|
|
%nonassoc IFX
|
|
|
|
|
%nonassoc ELSE
|
|
|
|
|
%nonassoc BREAK_PRIMARY
|
|
|
|
|
%nonassoc ';'
|
|
|
|
|
%nonassoc CLASS_NOT_CATEGORY
|
2007-05-07 23:44:45 +00:00
|
|
|
|
%nonassoc STORAGEX
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
%left COMMA
|
2020-03-13 11:56:10 +00:00
|
|
|
|
%right <op> '=' ASX
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%right '?' ':'
|
|
|
|
|
%left OR
|
2024-04-19 03:44:57 +00:00
|
|
|
|
%left XOR
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%left AND
|
|
|
|
|
%left '|'
|
|
|
|
|
%left '^'
|
|
|
|
|
%left '&'
|
|
|
|
|
%left EQ NE
|
2022-01-09 05:02:16 +00:00
|
|
|
|
%left LT GT GE LE
|
2022-01-30 01:56:15 +00:00
|
|
|
|
%token NAND NOR XNOR
|
2012-11-04 01:27:41 +00:00
|
|
|
|
// end of tokens common between qc and qp
|
|
|
|
|
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%left SHL SHR
|
|
|
|
|
%left '+' '-'
|
2024-02-01 02:00:27 +00:00
|
|
|
|
%left '*' '/' '%' MOD SCALE GEOMETRIC QMUL QVMUL VQMUL
|
2023-08-17 07:22:49 +00:00
|
|
|
|
%left HADAMARD CROSS DOT WEDGE REGRESSIVE
|
2024-02-09 04:49:36 +00:00
|
|
|
|
%right <op> SIZEOF UNARY INCOP REVERSE STAR DUAL UNDUAL
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%left HYPERUNARY
|
|
|
|
|
%left '.' '(' '['
|
|
|
|
|
|
2023-10-22 11:56:12 +00:00
|
|
|
|
%token <expr> VALUE STRING TOKEN
|
2024-11-15 03:36:08 +00:00
|
|
|
|
%token TRUE FALSE
|
2024-04-19 03:44:57 +00:00
|
|
|
|
%token ELLIPSIS
|
|
|
|
|
%token RESERVED
|
|
|
|
|
// end of common tokens
|
2023-10-22 11:56:12 +00:00
|
|
|
|
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%token <symbol> CLASS_NAME NAME
|
|
|
|
|
|
2022-02-05 09:58:42 +00:00
|
|
|
|
%token LOCAL WHILE DO IF ELSE FOR BREAK CONTINUE
|
2024-04-19 03:44:57 +00:00
|
|
|
|
%token RETURN AT_RETURN
|
2023-08-21 08:37:56 +00:00
|
|
|
|
%token NIL GOTO SWITCH CASE DEFAULT ENUM ALGEBRA
|
2022-02-02 14:51:37 +00:00
|
|
|
|
%token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE
|
2023-10-02 14:33:37 +00:00
|
|
|
|
%token <op> STRUCT
|
2024-11-24 16:39:27 +00:00
|
|
|
|
%token HANDLE INTRINSIC
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%token <spec> TYPE_SPEC TYPE_NAME TYPE_QUAL
|
|
|
|
|
%token <spec> OBJECT_NAME
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE
|
|
|
|
|
%token PROTECTED PROTOCOL PUBLIC SELECTOR REFERENCE SELF THIS
|
|
|
|
|
|
2024-04-25 07:10:43 +00:00
|
|
|
|
%token GENERIC
|
2024-05-31 07:39:50 +00:00
|
|
|
|
%token AT_FUNCTION AT_FIELD AT_POINTER AT_ARRAY
|
2024-04-24 06:45:26 +00:00
|
|
|
|
%token AT_BASE AT_WIDTH AT_VECTOR AT_ROWS AT_COLS AT_MATRIX
|
|
|
|
|
%token AT_INT AT_UINT AT_BOOL AT_FLOAT
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <spec> storage_class save_storage
|
|
|
|
|
%type <spec> typespec typespec_reserved typespec_nonreserved
|
2023-10-02 14:33:37 +00:00
|
|
|
|
%type <spec> handle
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <spec> declspecs declspecs_nosc declspecs_nots
|
|
|
|
|
%type <spec> declspecs_ts
|
|
|
|
|
%type <spec> declspecs_nosc_ts declspecs_nosc_nots
|
|
|
|
|
%type <spec> declspecs_sc_ts declspecs_sc_nots defspecs
|
|
|
|
|
%type <spec> declarator notype_declarator after_type_declarator
|
|
|
|
|
%type <spec> param_declarator param_declarator_starttypename
|
|
|
|
|
%type <spec> param_declarator_nostarttypename
|
2023-03-08 17:22:23 +00:00
|
|
|
|
%type <spec> absdecl absdecl1 direct_absdecl typename ptr_spec copy_spec
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <spec> qc_comma
|
2024-04-25 07:10:43 +00:00
|
|
|
|
%type <symbol> generic_param
|
2024-04-26 06:20:13 +00:00
|
|
|
|
%type <op> type_func type_op
|
|
|
|
|
%type <expr> type_function type_param type_ref
|
2024-09-04 00:41:57 +00:00
|
|
|
|
%type <spec> type_ref_spec
|
2024-04-26 06:20:13 +00:00
|
|
|
|
%type <expr> generic_type
|
|
|
|
|
%type <mut_expr> type_list type_param_list
|
2011-02-01 12:23:03 +00:00
|
|
|
|
|
2022-02-02 14:51:37 +00:00
|
|
|
|
%type <attribute> attribute_list attribute
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <param> function_params
|
|
|
|
|
%type <param> qc_func_params qc_param_list qc_first_param qc_param
|
2011-02-01 12:23:03 +00:00
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <symbol> tag
|
|
|
|
|
%type <spec> struct_specifier struct_list
|
2023-08-21 08:37:56 +00:00
|
|
|
|
%type <spec> enum_specifier algebra_specifier
|
2011-02-01 12:23:03 +00:00
|
|
|
|
%type <symbol> optional_enum_list enum_list enumerator_list enumerator
|
|
|
|
|
%type <symbol> enum_init
|
|
|
|
|
%type <size> array_decl
|
|
|
|
|
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%type <expr> const string
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <spec> ivar_decl
|
|
|
|
|
%type <expr> decl
|
2011-02-01 12:23:03 +00:00
|
|
|
|
%type <spec> ivars
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <param> param_list parameter_list parameter
|
2011-01-25 03:07:02 +00:00
|
|
|
|
%type <symbol> methoddef
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%type <expr> var_initializer local_def
|
2011-02-07 12:29:04 +00:00
|
|
|
|
|
2023-09-27 03:41:31 +00:00
|
|
|
|
%type <mut_expr> opt_init_semi opt_expr comma_expr
|
|
|
|
|
%type <expr> expr
|
|
|
|
|
%type <expr> compound_init
|
2024-11-17 04:17:36 +00:00
|
|
|
|
%type <spec> opt_cast
|
2023-09-27 03:41:31 +00:00
|
|
|
|
%type <mut_expr> element_list expr_list
|
2023-05-26 15:59:43 +00:00
|
|
|
|
%type <designator> designator designator_spec
|
2020-03-11 06:46:57 +00:00
|
|
|
|
%type <element> element
|
2023-09-24 06:04:25 +00:00
|
|
|
|
%type <expr> method_optional_state_expr optional_state_expr
|
|
|
|
|
%type <expr> texpr vector_expr
|
2024-11-24 16:39:27 +00:00
|
|
|
|
%type <expr> intrinsic
|
2023-09-27 03:41:31 +00:00
|
|
|
|
%type <expr> statement
|
2024-10-07 00:55:21 +00:00
|
|
|
|
%type <mut_expr> statements compound_statement compound_statement_ns
|
2020-03-11 02:06:09 +00:00
|
|
|
|
%type <expr> else bool_label break_label continue_label
|
2023-09-27 03:41:31 +00:00
|
|
|
|
%type <expr> unary_expr ident_expr cast_expr
|
2024-08-30 04:51:31 +00:00
|
|
|
|
%type <mut_expr> arg_list
|
|
|
|
|
%type <expr> opt_arg_list arg_expr
|
2001-10-25 06:41:52 +00:00
|
|
|
|
%type <switch_block> switch_block
|
2020-03-11 02:31:54 +00:00
|
|
|
|
%type <symbol> identifier label
|
2011-02-01 12:23:03 +00:00
|
|
|
|
|
2023-09-27 03:41:31 +00:00
|
|
|
|
%type <mut_expr> identifier_list
|
2020-03-01 10:37:40 +00:00
|
|
|
|
%type <symbol> protocol_name_list selector reserved_word
|
2011-02-01 12:23:03 +00:00
|
|
|
|
%type <param> optional_param_list unaryselector keyworddecl
|
|
|
|
|
%type <param> keywordselector
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%type <method> methodproto methoddecl
|
|
|
|
|
%type <expr> obj_expr obj_messageexpr obj_string receiver
|
2004-11-11 00:34:00 +00:00
|
|
|
|
%type <protocol_list> protocolrefs protocol_list
|
2002-05-08 23:12:49 +00:00
|
|
|
|
%type <keywordarg> messageargs keywordarg keywordarglist selectorarg
|
|
|
|
|
%type <keywordarg> keywordnamelist keywordname
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%type <class> class_name new_class_name class_with_super
|
|
|
|
|
%type <class> classdef new_class_with_super
|
|
|
|
|
%type <category> category_name new_category_name
|
|
|
|
|
%type <protocol> protocol_name
|
2002-05-10 00:00:23 +00:00
|
|
|
|
%type <methodlist> methodprotolist methodprotolist2
|
2011-01-17 13:33:33 +00:00
|
|
|
|
%type <symtab> ivar_decl_list
|
2012-12-20 01:02:00 +00:00
|
|
|
|
%type <op> ci not
|
2002-05-08 05:15:19 +00:00
|
|
|
|
|
2001-06-15 07:16:18 +00:00
|
|
|
|
%{
|
|
|
|
|
|
2011-01-17 13:33:33 +00:00
|
|
|
|
static switch_block_t *switch_block;
|
2023-09-27 03:41:31 +00:00
|
|
|
|
static const expr_t *break_label;
|
|
|
|
|
static const expr_t *continue_label;
|
2024-08-10 11:04:58 +00:00
|
|
|
|
static bool generic_scope, generic_block;
|
|
|
|
|
static symtab_t *generic_symtab;
|
2024-11-04 07:31:35 +00:00
|
|
|
|
static expr_t *local_expr;
|
2024-08-10 11:04:58 +00:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
end_generic_scope (void)
|
|
|
|
|
{
|
|
|
|
|
generic_scope = false;
|
|
|
|
|
generic_symtab = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
restore_storage (specifier_t st)
|
|
|
|
|
{
|
|
|
|
|
if (generic_block && !st.is_generic) {
|
|
|
|
|
end_generic_scope ();
|
|
|
|
|
}
|
|
|
|
|
generic_block = st.is_generic;
|
|
|
|
|
current_storage = st.storage;
|
|
|
|
|
}
|
2011-01-17 13:33:33 +00:00
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
static specifier_t
|
2024-08-10 08:25:24 +00:00
|
|
|
|
type_spec (const type_t *type)
|
2011-02-01 12:23:03 +00:00
|
|
|
|
{
|
2024-08-10 08:25:24 +00:00
|
|
|
|
specifier_t spec = {
|
|
|
|
|
.type = type,
|
|
|
|
|
};
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
|
|
|
|
storage_spec (storage_class_t storage)
|
|
|
|
|
{
|
|
|
|
|
specifier_t spec = {
|
|
|
|
|
.storage = storage,
|
|
|
|
|
};
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
|
|
|
|
typedef_spec (void)
|
|
|
|
|
{
|
|
|
|
|
specifier_t spec = {
|
|
|
|
|
.storage = sc_global,
|
|
|
|
|
.is_typedef = true,
|
|
|
|
|
};
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
|
|
|
|
overload_spec (void)
|
|
|
|
|
{
|
|
|
|
|
specifier_t spec = {
|
|
|
|
|
.storage = current_storage,
|
|
|
|
|
.is_overload = true,
|
|
|
|
|
};
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
|
|
|
|
generic_spec (void)
|
|
|
|
|
{
|
|
|
|
|
specifier_t spec = {
|
|
|
|
|
.storage = current_storage,
|
|
|
|
|
.symtab = new_symtab (current_symtab, stab_local),
|
|
|
|
|
.is_generic = true,
|
|
|
|
|
};
|
2024-08-10 11:04:58 +00:00
|
|
|
|
generic_symtab = spec.symtab;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-11 11:31:08 +00:00
|
|
|
|
static int
|
|
|
|
|
storage_auto (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
return spec.storage == sc_global || spec.storage == sc_local;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 01:58:01 +00:00
|
|
|
|
static bool
|
|
|
|
|
spec_type (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
return spec.type || spec.type_expr;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
static specifier_t
|
|
|
|
|
spec_merge (specifier_t spec, specifier_t new)
|
|
|
|
|
{
|
2024-05-01 01:58:01 +00:00
|
|
|
|
if (spec_type (new)) {
|
2022-02-07 01:40:26 +00:00
|
|
|
|
// deal with "type <type_name>"
|
2024-05-01 01:58:01 +00:00
|
|
|
|
if (!spec_type (spec) || new.sym) {
|
2022-02-07 01:40:26 +00:00
|
|
|
|
spec.sym = new.sym;
|
2024-05-01 01:58:01 +00:00
|
|
|
|
if (!spec_type (spec)) {
|
2022-02-07 01:40:26 +00:00
|
|
|
|
spec.type = new.type;
|
2024-05-01 01:58:01 +00:00
|
|
|
|
spec.type_expr = new.type_expr;
|
2022-02-07 01:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
} else if (!spec.multi_type) {
|
2011-02-01 12:23:03 +00:00
|
|
|
|
error (0, "two or more data types in declaration specifiers");
|
2024-05-13 03:19:16 +00:00
|
|
|
|
spec.multi_type = true;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-11 11:31:08 +00:00
|
|
|
|
if (new.is_typedef || !storage_auto (new)) {
|
|
|
|
|
if ((spec.is_typedef || !storage_auto (spec)) && !spec.multi_store) {
|
2011-02-01 12:23:03 +00:00
|
|
|
|
error (0, "multiple storage classes in declaration specifiers");
|
2024-05-13 03:19:16 +00:00
|
|
|
|
spec.multi_store = true;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
|
|
|
|
spec.storage = new.storage;
|
|
|
|
|
spec.is_typedef = new.is_typedef;
|
|
|
|
|
}
|
2024-08-10 11:04:58 +00:00
|
|
|
|
if (new.is_generic) {
|
|
|
|
|
if (spec.is_generic && !spec.multi_generic) {
|
|
|
|
|
error (0, "multiple @generic in declaration");
|
|
|
|
|
spec.multi_generic = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-19 09:08:58 +00:00
|
|
|
|
if ((new.is_unsigned && spec.is_signed)
|
|
|
|
|
|| (new.is_signed && spec.is_unsigned)) {
|
|
|
|
|
if (!spec.multi_type) {
|
|
|
|
|
error (0, "both signed and unsigned in declaration specifiers");
|
2024-05-13 03:19:16 +00:00
|
|
|
|
spec.multi_type = true;
|
2022-01-19 09:08:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ((new.is_long && spec.is_short) || (new.is_short && spec.is_long)) {
|
|
|
|
|
if (!spec.multi_store) {
|
|
|
|
|
error (0, "both long and short in declaration specifiers");
|
2024-05-13 03:19:16 +00:00
|
|
|
|
spec.multi_store = true;
|
2022-01-19 09:08:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-22 05:15:08 +00:00
|
|
|
|
for (auto attr = &spec.attributes; *attr; attr = &(*attr)->next) {
|
|
|
|
|
if (!(*attr)->next) {
|
|
|
|
|
(*attr)->next = new.attributes;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-19 12:32:01 +00:00
|
|
|
|
spec.sym = new.sym;
|
2022-02-05 09:45:54 +00:00
|
|
|
|
spec.spec_bits |= new.spec_bits;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-04 14:44:07 +00:00
|
|
|
|
static const type_t *
|
|
|
|
|
resolve_type_spec (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
auto type = spec.type;
|
|
|
|
|
if (spec.type_expr) {
|
|
|
|
|
type = resolve_type (spec.type_expr);
|
|
|
|
|
}
|
|
|
|
|
return find_type (type);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-08 17:22:23 +00:00
|
|
|
|
static specifier_t
|
|
|
|
|
typename_spec (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
spec = default_type (spec, 0);
|
|
|
|
|
spec.sym->type = find_type (append_type (spec.sym->type, spec.type));
|
|
|
|
|
spec.type = spec.sym->type;
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
|
|
|
|
function_spec (specifier_t spec, param_t *params)
|
|
|
|
|
{
|
2024-08-17 07:08:35 +00:00
|
|
|
|
// empty param list in an abstract decl does not create a symbol
|
2023-03-08 17:22:23 +00:00
|
|
|
|
if (!spec.sym) {
|
|
|
|
|
spec.sym = new_symbol (0);
|
|
|
|
|
}
|
2024-05-31 04:51:38 +00:00
|
|
|
|
if (!spec.type_expr) {
|
|
|
|
|
spec = default_type (spec, spec.sym);
|
|
|
|
|
}
|
2023-03-08 17:22:23 +00:00
|
|
|
|
spec.sym->params = params;
|
2024-08-20 23:23:12 +00:00
|
|
|
|
if (spec.sym->type) {
|
|
|
|
|
if (is_func (spec.sym->type)) {
|
|
|
|
|
error (0, "'%s' declared as a function returning a function",
|
|
|
|
|
spec.sym->name);
|
|
|
|
|
} else if (is_array (spec.sym->type)) {
|
|
|
|
|
error (0, "declaration of '%s' as array of functions",
|
|
|
|
|
spec.sym->name);
|
2024-10-07 10:40:19 +00:00
|
|
|
|
} else if (!is_pointer (spec.sym->type)
|
|
|
|
|
&& !is_field (spec.sym->type)) {
|
2024-08-20 23:23:12 +00:00
|
|
|
|
internal_error (0, "unexpected type");
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-26 01:35:33 +00:00
|
|
|
|
spec.is_function = !spec.sym->type; //FIXME do proper void(*)() -> ev_func
|
2023-03-08 17:22:23 +00:00
|
|
|
|
spec.sym->type = append_type (spec.sym->type, parse_params (0, params));
|
2024-08-10 11:04:58 +00:00
|
|
|
|
spec.is_generic = generic_scope;
|
|
|
|
|
spec.is_generic_block = generic_block;
|
|
|
|
|
spec.symtab = generic_symtab;
|
2023-03-08 17:22:23 +00:00
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
|
|
|
|
array_spec (specifier_t spec, unsigned size)
|
|
|
|
|
{
|
|
|
|
|
spec = default_type (spec, spec.sym);
|
2024-08-20 23:23:12 +00:00
|
|
|
|
if (spec.sym->type) {
|
|
|
|
|
if (is_func (spec.sym->type)) {
|
|
|
|
|
error (0, "'%s' declared as function returning an array",
|
|
|
|
|
spec.sym->name);
|
2024-10-07 10:40:19 +00:00
|
|
|
|
} else if (!is_pointer (spec.sym->type)
|
2024-08-20 23:23:12 +00:00
|
|
|
|
&& !is_array (spec.sym->type)
|
|
|
|
|
&& !is_field (spec.sym->type)) {
|
|
|
|
|
internal_error (0, "unexpected type");
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-08 17:22:23 +00:00
|
|
|
|
spec.sym->type = append_type (spec.sym->type, array_type (0, size));
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
|
|
|
|
pointer_spec (specifier_t quals, specifier_t spec)
|
|
|
|
|
{
|
2024-08-20 23:23:12 +00:00
|
|
|
|
if (spec.sym->type) {
|
|
|
|
|
if (!is_func (spec.sym->type)
|
2024-10-07 10:40:19 +00:00
|
|
|
|
&& !is_pointer (spec.sym->type)
|
2024-08-20 23:23:12 +00:00
|
|
|
|
&& !is_array (spec.sym->type)
|
|
|
|
|
&& !is_field (spec.sym->type)) {
|
|
|
|
|
internal_error (0, "unexpected type");
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-08 17:22:23 +00:00
|
|
|
|
spec.sym->type = append_type (spec.sym->type, pointer_type (0));
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static specifier_t
|
2024-05-04 01:50:08 +00:00
|
|
|
|
qc_function_spec (specifier_t spec, param_t *params)
|
2023-03-08 17:22:23 +00:00
|
|
|
|
{
|
|
|
|
|
// .float () foo; is a field holding a function variable rather
|
|
|
|
|
// than a function that returns a float field.
|
2024-08-17 07:08:35 +00:00
|
|
|
|
// FIXME I think this breaks fields holding functions that return fields
|
|
|
|
|
// but that would require some messy ()s to get parsing anyway, and it can
|
|
|
|
|
// wait until such is needed (if ever).
|
|
|
|
|
const type_t *field_chain = nullptr;
|
|
|
|
|
const type_t *ret_type = spec.type;
|
|
|
|
|
while (ret_type && is_field (ret_type)) {
|
|
|
|
|
field_chain = field_type (field_chain);
|
|
|
|
|
ret_type = ret_type->fldptr.type;
|
2023-03-08 17:22:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-17 07:08:35 +00:00
|
|
|
|
// qc-style functions are known to be functions before the symbol is seen,
|
|
|
|
|
// so provide an unnamed symbol to hold any field type information
|
2023-03-08 17:22:23 +00:00
|
|
|
|
spec.sym = new_symbol (0);
|
2024-08-17 07:08:35 +00:00
|
|
|
|
spec.sym->type = field_chain;
|
2023-03-08 17:22:23 +00:00
|
|
|
|
spec.type = ret_type;
|
|
|
|
|
|
|
|
|
|
spec = function_spec (spec, params);
|
|
|
|
|
return spec;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-26 01:35:33 +00:00
|
|
|
|
static specifier_t
|
|
|
|
|
qc_set_symbol (specifier_t spec, symbol_t *sym)
|
2023-03-08 17:22:23 +00:00
|
|
|
|
{
|
2024-08-26 01:35:33 +00:00
|
|
|
|
// qc-style function declarations don't know the symbol name until the
|
|
|
|
|
// declaration is fully parsed, so spec.sym's name is null but its type
|
|
|
|
|
// carries any extra type information (field, pointer, array)
|
|
|
|
|
sym->params = spec.sym->params;
|
|
|
|
|
sym->type = spec.sym->type;
|
|
|
|
|
spec.sym = sym;
|
|
|
|
|
return spec;
|
2023-03-08 17:22:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static param_t *
|
|
|
|
|
make_ellipsis (void)
|
|
|
|
|
{
|
|
|
|
|
return new_param (0, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static param_t *
|
|
|
|
|
make_param (specifier_t spec)
|
|
|
|
|
{
|
2024-09-03 08:59:56 +00:00
|
|
|
|
//FIXME should not be sc_global
|
|
|
|
|
if (spec.storage == sc_global) {
|
|
|
|
|
spec.storage = sc_param;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
param_t *param;
|
2024-04-30 02:32:20 +00:00
|
|
|
|
if (spec.type_expr) {
|
2024-09-03 08:59:56 +00:00
|
|
|
|
param = new_generic_param (spec.type_expr, spec.sym->name);
|
2024-05-01 01:58:01 +00:00
|
|
|
|
} else {
|
|
|
|
|
spec = default_type (spec, spec.sym);
|
|
|
|
|
spec.type = find_type (append_type (spec.sym->type, spec.type));
|
2024-09-03 08:59:56 +00:00
|
|
|
|
param = new_param (0, spec.type, spec.sym->name);
|
2024-04-30 02:32:20 +00:00
|
|
|
|
}
|
2024-09-03 08:59:56 +00:00
|
|
|
|
if (spec.is_const) {
|
|
|
|
|
if (spec.storage == sc_out) {
|
|
|
|
|
error (0, "cannot use const with @out");
|
|
|
|
|
} else if (spec.storage == sc_inout) {
|
|
|
|
|
error (0, "cannot use const with @inout");
|
|
|
|
|
} else {
|
|
|
|
|
if (spec.storage != sc_in && spec.storage != sc_param) {
|
|
|
|
|
internal_error (0, "unexpected parameter storage: %d",
|
|
|
|
|
spec.storage);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
param->qual = pq_const;
|
|
|
|
|
} else {
|
|
|
|
|
if (spec.storage == sc_out) {
|
|
|
|
|
param->qual = pq_out;
|
|
|
|
|
} else if (spec.storage == sc_inout) {
|
|
|
|
|
param->qual = pq_inout;
|
|
|
|
|
} else {
|
|
|
|
|
if (spec.storage != sc_in && spec.storage != sc_param) {
|
|
|
|
|
internal_error (0, "unexpected parameter storage: %d",
|
|
|
|
|
spec.storage);
|
|
|
|
|
}
|
|
|
|
|
param->qual = pq_in;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return param;
|
2023-03-08 17:22:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static param_t *
|
2024-02-13 14:09:28 +00:00
|
|
|
|
make_selector (const char *selector, const type_t *type, const char *name)
|
2023-03-08 17:22:23 +00:00
|
|
|
|
{
|
|
|
|
|
param_t *param = new_param (selector, type, name);
|
|
|
|
|
return param;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static param_t *
|
|
|
|
|
make_qc_param (specifier_t spec, symbol_t *sym)
|
|
|
|
|
{
|
2024-09-02 06:59:06 +00:00
|
|
|
|
sym->type = nullptr;
|
|
|
|
|
spec.sym = sym;
|
|
|
|
|
return make_param (spec);
|
2023-03-08 17:22:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static param_t *
|
|
|
|
|
make_qc_func_param (specifier_t spec, param_t *params, symbol_t *sym)
|
|
|
|
|
{
|
2024-05-04 01:50:08 +00:00
|
|
|
|
spec = qc_function_spec (spec, params);
|
2023-03-08 17:22:23 +00:00
|
|
|
|
sym->type = append_type (spec.sym->type, spec.type);
|
|
|
|
|
param_t *param = new_param (0, sym->type, sym->name);
|
|
|
|
|
return param;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 07:31:28 +00:00
|
|
|
|
static int
|
|
|
|
|
is_anonymous_struct (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
if (spec.sym) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-05-25 12:22:50 +00:00
|
|
|
|
if (!is_struct (spec.type) && !is_union (spec.type)) {
|
2020-03-04 07:31:28 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2024-08-16 08:23:29 +00:00
|
|
|
|
if (!spec.type->symtab || spec.type->symtab->parent) {
|
2020-03-04 07:31:28 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
// struct and union type names always begin with "tag ". Untagged s/u
|
|
|
|
|
// are "tag .<filename>.<id>".
|
|
|
|
|
if (spec.type->name[4] != '.') {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 08:40:49 +00:00
|
|
|
|
static int
|
|
|
|
|
is_null_spec (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
static specifier_t null_spec;
|
|
|
|
|
return memcmp (&spec, &null_spec, sizeof (spec)) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-19 12:32:01 +00:00
|
|
|
|
static int
|
|
|
|
|
use_type_name (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
spec.sym = new_symbol (spec.sym->name);
|
|
|
|
|
spec.sym->type = spec.type;
|
2024-09-20 02:27:15 +00:00
|
|
|
|
spec.sym->sy_type = sy_name;
|
2023-02-04 07:44:48 +00:00
|
|
|
|
symbol_t *s = symtab_addsymbol (current_symtab, spec.sym);
|
|
|
|
|
// a different symbol being returned means that this is a redefinition
|
|
|
|
|
// of that symbol in the same scope. However, typedefs to the same type
|
|
|
|
|
// are allowed.
|
|
|
|
|
if (s != spec.sym && spec.is_typedef && s->sy_type == sy_type
|
|
|
|
|
&& type_same (s->type, spec.type)) {
|
|
|
|
|
spec.sym = s;
|
|
|
|
|
}
|
2022-01-19 12:32:01 +00:00
|
|
|
|
return !!spec.sym->table;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
static void __attribute__((used))
|
2022-01-19 12:18:34 +00:00
|
|
|
|
check_specifiers (specifier_t spec)
|
|
|
|
|
{
|
|
|
|
|
if (!is_null_spec (spec)) {
|
|
|
|
|
if (!spec.type && !spec.sym) {
|
|
|
|
|
warning (0, "useless specifiers");
|
|
|
|
|
} else if (spec.type && !spec.sym) {
|
|
|
|
|
if (is_anonymous_struct (spec)){
|
|
|
|
|
warning (0, "unnamed struct/union that defines "
|
|
|
|
|
"no instances");
|
2023-05-25 12:22:50 +00:00
|
|
|
|
} else if (!is_enum (spec.type)
|
|
|
|
|
&& !is_struct (spec.type) && !is_union (spec.type)) {
|
2022-01-19 12:18:34 +00:00
|
|
|
|
warning (0, "useless type name in empty declaration");
|
|
|
|
|
}
|
|
|
|
|
} else if (!spec.type && spec.sym) {
|
|
|
|
|
bug (0, "wha? %p %p", spec.type, spec.sym);
|
|
|
|
|
} else {
|
2022-01-19 12:32:01 +00:00
|
|
|
|
// a type name (id, typedef, etc) was used as a variable name.
|
2023-02-04 07:44:48 +00:00
|
|
|
|
// this is allowed in C, so long as it's in a different scope,
|
|
|
|
|
// or the types are the same
|
2022-01-19 12:32:01 +00:00
|
|
|
|
if (!use_type_name (spec)) {
|
|
|
|
|
error (0, "%s redeclared as different kind of symbol",
|
|
|
|
|
spec.sym->name);
|
|
|
|
|
}
|
2022-01-19 12:18:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-15 07:16:18 +00:00
|
|
|
|
%}
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
%expect 2
|
2004-02-08 23:46:40 +00:00
|
|
|
|
|
2001-06-12 19:44:26 +00:00
|
|
|
|
%%
|
|
|
|
|
|
2011-03-24 02:39:34 +00:00
|
|
|
|
program
|
|
|
|
|
: external_def_list
|
|
|
|
|
{
|
|
|
|
|
if (current_class) {
|
|
|
|
|
warning (0, "‘@end’ missing in implementation context");
|
|
|
|
|
class_finish (current_class);
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
external_def_list
|
2001-06-12 19:44:26 +00:00
|
|
|
|
: /* empty */
|
2011-01-22 06:52:57 +00:00
|
|
|
|
{
|
2024-08-10 11:04:58 +00:00
|
|
|
|
if (!generic_block) {
|
|
|
|
|
current_symtab = pr.symtab;
|
|
|
|
|
}
|
2011-01-22 06:52:57 +00:00
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
| external_def_list external_def
|
2024-04-25 07:10:43 +00:00
|
|
|
|
{
|
2024-08-10 11:04:58 +00:00
|
|
|
|
if (generic_scope && !generic_block) {
|
|
|
|
|
end_generic_scope ();
|
2024-04-25 07:10:43 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
| external_def_list obj_def
|
2023-02-08 02:18:42 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
external_def
|
|
|
|
|
: fndef
|
|
|
|
|
| datadef
|
|
|
|
|
| storage_class '{' save_storage
|
2012-12-22 11:04:11 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
current_storage = $1.storage;
|
2024-08-10 11:04:58 +00:00
|
|
|
|
generic_block = generic_scope;
|
2012-12-22 11:04:11 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
external_def_list '}' ';'
|
2012-12-22 11:04:11 +00:00
|
|
|
|
{
|
2024-08-10 11:04:58 +00:00
|
|
|
|
restore_storage ($3);
|
2012-12-22 11:04:11 +00:00
|
|
|
|
}
|
2001-06-12 19:44:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
fndef
|
|
|
|
|
: declspecs_ts declarator function_body
|
|
|
|
|
| declspecs_nots notype_declarator function_body
|
|
|
|
|
| defspecs notype_declarator function_body
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
datadef
|
|
|
|
|
: defspecs notype_initdecls ';'
|
|
|
|
|
| declspecs_nots notype_initdecls ';'
|
|
|
|
|
| declspecs_ts initdecls ';'
|
|
|
|
|
| declspecs_ts qc_func_params
|
2002-01-23 20:50:25 +00:00
|
|
|
|
{
|
2024-05-04 01:50:08 +00:00
|
|
|
|
$<spec>$ = qc_function_spec ($1, $2);
|
2002-01-23 20:50:25 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
qc_func_decls
|
|
|
|
|
| declspecs ';'
|
|
|
|
|
| error ';'
|
|
|
|
|
| error '}'
|
|
|
|
|
| ';'
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qc_func_params
|
|
|
|
|
: '(' copy_spec qc_param_list ')' { $$ = check_params ($3); }
|
|
|
|
|
| '(' copy_spec typespec_reserved ')'
|
2011-06-21 10:52:47 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
if (!is_void ($3.type)) {
|
|
|
|
|
PARSE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
$$ = 0;
|
2011-06-21 10:52:47 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| '(' copy_spec ')' { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qc_param_list
|
|
|
|
|
: qc_first_param
|
|
|
|
|
| qc_param_list ',' qc_param
|
2011-03-07 11:51:51 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = append_params ($1, $3);
|
2011-03-07 11:51:51 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
;
|
|
|
|
|
// quakec function parameters cannot use a typedef as the return type
|
|
|
|
|
// in the first parameter (really, they should't use any as standard quakec
|
2024-08-20 23:23:12 +00:00
|
|
|
|
// doesn't support typedef, but that seems overly restrictive), however,
|
2023-02-08 02:18:42 +00:00
|
|
|
|
// they can stil use a typedef first parameter. This is due to grammar issues
|
|
|
|
|
qc_first_param
|
|
|
|
|
: typespec identifier
|
2011-03-07 11:51:51 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_qc_param ($1, $2);
|
2011-03-07 11:51:51 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| typespec_reserved qc_func_params identifier
|
2011-03-07 11:51:51 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_qc_func_param ($1, $2, $3);
|
2011-03-07 11:51:51 +00:00
|
|
|
|
}
|
2024-09-18 05:33:02 +00:00
|
|
|
|
| ELLIPSIS
|
|
|
|
|
{
|
|
|
|
|
if (options.code.no_vararg) {
|
|
|
|
|
PARSE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
$$ = make_ellipsis ();
|
|
|
|
|
}
|
2002-01-21 19:09:23 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
qc_param
|
|
|
|
|
: typespec identifier
|
2020-02-19 01:50:15 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_qc_param ($1, $2);
|
2020-02-19 01:50:15 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| typespec qc_func_params identifier
|
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_qc_func_param ($1, $2, $3);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
2024-09-18 05:33:02 +00:00
|
|
|
|
| ELLIPSIS
|
|
|
|
|
{
|
|
|
|
|
if (options.code.no_vararg) {
|
|
|
|
|
PARSE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
$$ = make_ellipsis ();
|
|
|
|
|
}
|
2020-02-19 01:50:15 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
/* This rule is used only to get an action before both qc_func_decl and
|
|
|
|
|
qc_func_decl_term so that the function spec can be inherited.
|
|
|
|
|
*/
|
|
|
|
|
qc_comma
|
|
|
|
|
: ',' { $$ = $<spec>0; }
|
|
|
|
|
;
|
2011-02-02 06:13:34 +00:00
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
qc_func_decls
|
|
|
|
|
: qc_func_decl_list qc_comma qc_func_decl_term
|
|
|
|
|
| qc_func_decl_term
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qc_func_decl_term
|
|
|
|
|
: qc_nocode_func ';'
|
|
|
|
|
| qc_code_func ';'
|
|
|
|
|
| qc_code_func %prec IFX
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qc_func_decl_list
|
|
|
|
|
: qc_func_decl_list qc_comma qc_func_decl
|
|
|
|
|
| qc_func_decl
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qc_func_decl
|
|
|
|
|
: qc_nocode_func
|
|
|
|
|
| qc_code_func
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qc_nocode_func
|
|
|
|
|
: identifier '=' '#' expr
|
|
|
|
|
{
|
2024-08-26 01:35:33 +00:00
|
|
|
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
2024-08-26 01:31:57 +00:00
|
|
|
|
const expr_t *bi_val = $4;
|
2024-08-20 06:19:31 +00:00
|
|
|
|
|
2024-08-26 01:35:33 +00:00
|
|
|
|
symbol_t *sym = function_symbol (spec);
|
2024-08-26 01:31:57 +00:00
|
|
|
|
build_builtin_function (sym, bi_val, 0, spec.storage);
|
2011-02-09 01:25:23 +00:00
|
|
|
|
}
|
2024-11-24 16:39:27 +00:00
|
|
|
|
| identifier '=' intrinsic
|
|
|
|
|
{
|
|
|
|
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
|
|
|
|
build_intrinsic_function (spec, $3);
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| identifier '=' expr
|
|
|
|
|
{
|
2024-08-26 01:35:33 +00:00
|
|
|
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
2024-05-31 04:51:38 +00:00
|
|
|
|
const expr_t *expr = $3;
|
2024-08-26 01:35:33 +00:00
|
|
|
|
|
2024-11-04 07:31:35 +00:00
|
|
|
|
declare_symbol (spec, expr, current_symtab, local_expr);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| identifier
|
|
|
|
|
{
|
2024-08-26 01:35:33 +00:00
|
|
|
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
2024-11-04 07:31:35 +00:00
|
|
|
|
declare_symbol (spec, nullptr, current_symtab, local_expr);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qc_code_func
|
|
|
|
|
: identifier '=' optional_state_expr
|
2011-03-07 11:51:51 +00:00
|
|
|
|
save_storage
|
2011-02-09 01:25:23 +00:00
|
|
|
|
{
|
2024-05-05 07:45:05 +00:00
|
|
|
|
$<funcstate>$ = (funcstate_t) {
|
|
|
|
|
.symtab = current_symtab,
|
|
|
|
|
.function = current_func,
|
|
|
|
|
};
|
2024-08-26 01:35:33 +00:00
|
|
|
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
|
|
|
|
symbol_t *sym = function_symbol (spec);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
current_func = begin_function (sym, 0, current_symtab, 0,
|
|
|
|
|
spec.storage);
|
2022-01-21 01:20:02 +00:00
|
|
|
|
current_symtab = current_func->locals;
|
2012-12-02 01:11:30 +00:00
|
|
|
|
current_storage = sc_local;
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$1 = sym;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
2024-10-07 00:55:21 +00:00
|
|
|
|
compound_statement_ns
|
2011-02-01 12:23:03 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
build_code_function ($1, $3, $6);
|
2024-05-05 07:45:05 +00:00
|
|
|
|
current_symtab = $<funcstate>5.symtab;
|
|
|
|
|
current_func = $<funcstate>5.function;
|
2024-08-10 11:04:58 +00:00
|
|
|
|
restore_storage ($4);
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
2004-02-10 23:20:44 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
declarator
|
|
|
|
|
: after_type_declarator
|
|
|
|
|
| notype_declarator
|
2002-09-12 17:13:19 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
after_type_declarator
|
|
|
|
|
: '(' copy_spec after_type_declarator ')' { $$ = $3; }
|
|
|
|
|
| after_type_declarator function_params
|
2011-02-02 06:13:34 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = function_spec ($1, $2);
|
2011-02-02 06:13:34 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| after_type_declarator array_decl
|
2011-02-14 14:31:37 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = array_spec ($1, $2);
|
2011-02-14 14:31:37 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| '*' ptr_spec after_type_declarator
|
2011-02-03 01:48:12 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = pointer_spec ($2, $3);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| TYPE_NAME
|
|
|
|
|
{
|
|
|
|
|
$$ = $<spec>0;
|
|
|
|
|
$$.sym = new_symbol ($1.sym->name);
|
|
|
|
|
}
|
|
|
|
|
| OBJECT_NAME
|
|
|
|
|
{
|
|
|
|
|
$$ = $<spec>0;
|
|
|
|
|
$$.sym = new_symbol ($1.sym->name);
|
2011-02-03 01:48:12 +00:00
|
|
|
|
}
|
2004-02-11 00:36:34 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
copy_spec
|
|
|
|
|
: /* empty */
|
2013-01-07 05:35:34 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$<spec>$ = $<spec>-1;
|
2013-01-07 05:35:34 +00:00
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
ptr_spec
|
2023-03-08 17:22:23 +00:00
|
|
|
|
: copy_spec // for when no qualifiers are present
|
2022-02-02 14:51:37 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
notype_declarator
|
|
|
|
|
: '(' copy_spec notype_declarator ')' { $$ = $3; }
|
|
|
|
|
| notype_declarator function_params
|
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = function_spec ($1, $2);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| notype_declarator array_decl
|
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = array_spec ($1, $2);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| '*' ptr_spec notype_declarator
|
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = pointer_spec ($2, $3);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| NAME
|
|
|
|
|
{
|
|
|
|
|
$$ = $<spec>0;
|
|
|
|
|
$$.sym = new_symbol ($1->name);
|
|
|
|
|
}
|
2024-09-06 17:42:32 +00:00
|
|
|
|
| NOT
|
|
|
|
|
{
|
|
|
|
|
$$ = $<spec>0;
|
|
|
|
|
$$.sym = new_symbol ("NOT");
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
initdecls
|
|
|
|
|
: initdecl
|
|
|
|
|
| initdecls ',' { $<spec>$ = $<spec>0; } initdecl
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
initdecl
|
|
|
|
|
: declarator '=' var_initializer
|
2024-11-04 07:31:35 +00:00
|
|
|
|
{ declare_symbol ($1, $3, current_symtab, local_expr); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declarator
|
2024-11-04 07:31:35 +00:00
|
|
|
|
{ declare_symbol ($1, 0, current_symtab, local_expr); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_initdecls
|
|
|
|
|
: notype_initdecl
|
|
|
|
|
| notype_initdecls ',' { $<spec>$ = $<spec>0; } notype_initdecl
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_initdecl
|
|
|
|
|
: notype_declarator '=' var_initializer
|
2024-11-04 07:31:35 +00:00
|
|
|
|
{ declare_symbol ($1, $3, current_symtab, local_expr); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| notype_declarator
|
2024-11-04 07:31:35 +00:00
|
|
|
|
{ declare_symbol ($1, 0, current_symtab, local_expr); }
|
2022-02-02 14:51:37 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
/* various lists of type specifiers, storage class etc */
|
|
|
|
|
declspecs_ts
|
|
|
|
|
: declspecs_nosc_ts
|
|
|
|
|
| declspecs_sc_ts
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
declspecs_nots
|
|
|
|
|
: declspecs_nosc_nots
|
|
|
|
|
| declspecs_sc_nots
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
declspecs_nosc
|
|
|
|
|
: declspecs_nosc_nots
|
|
|
|
|
| declspecs_nosc_ts
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
declspecs
|
|
|
|
|
: declspecs_nosc_nots
|
|
|
|
|
| declspecs_nosc_ts
|
|
|
|
|
| declspecs_sc_nots
|
|
|
|
|
| declspecs_sc_ts
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
declspecs_nosc_nots
|
|
|
|
|
: TYPE_QUAL
|
|
|
|
|
| declspecs_nosc_nots TYPE_QUAL
|
2011-03-07 11:51:51 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = spec_merge ($1, $2);
|
2011-03-07 11:51:51 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
declspecs_nosc_ts
|
|
|
|
|
: typespec
|
|
|
|
|
| declspecs_nosc_ts TYPE_QUAL
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_nosc_ts typespec_reserved
|
2011-01-25 00:36:00 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_nosc_nots typespec
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
2011-01-25 00:36:00 +00:00
|
|
|
|
}
|
2002-09-12 17:13:19 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
declspecs_sc_nots
|
|
|
|
|
: storage_class
|
|
|
|
|
| declspecs_sc_nots TYPE_QUAL
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_nosc_nots storage_class
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_sc_nots storage_class
|
2011-02-02 13:59:08 +00:00
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
declspecs_sc_ts
|
|
|
|
|
: declspecs_sc_ts TYPE_QUAL
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_sc_ts typespec_reserved
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_sc_nots typespec
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_nosc_ts storage_class
|
|
|
|
|
{
|
|
|
|
|
$$ = spec_merge ($1, $2);
|
|
|
|
|
}
|
|
|
|
|
| declspecs_sc_ts storage_class
|
2020-02-27 08:50:11 +00:00
|
|
|
|
{
|
2022-02-07 01:40:26 +00:00
|
|
|
|
$$ = spec_merge ($1, $2);
|
2020-02-27 08:50:11 +00:00
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
typespec
|
|
|
|
|
: typespec_reserved
|
|
|
|
|
{
|
|
|
|
|
$$ = $1;
|
2023-02-11 11:31:08 +00:00
|
|
|
|
if (!$$.storage) {
|
|
|
|
|
$$.storage = current_storage;
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| typespec_nonreserved
|
|
|
|
|
{
|
|
|
|
|
$$ = $1;
|
2023-02-11 11:31:08 +00:00
|
|
|
|
if (!$$.storage) {
|
|
|
|
|
$$.storage = current_storage;
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
typespec_reserved
|
2023-02-04 09:26:54 +00:00
|
|
|
|
: TYPE_SPEC
|
2024-04-30 02:32:20 +00:00
|
|
|
|
| type_function
|
|
|
|
|
{
|
2024-05-01 01:58:01 +00:00
|
|
|
|
if (generic_scope) {
|
|
|
|
|
$$ = (specifier_t) {
|
|
|
|
|
.type_expr = $1,
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
auto type = resolve_type ($1);
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (type);
|
2024-05-01 01:58:01 +00:00
|
|
|
|
}
|
2024-04-30 02:32:20 +00:00
|
|
|
|
}
|
2023-08-25 13:06:44 +00:00
|
|
|
|
| algebra_specifier %prec LOW
|
|
|
|
|
| algebra_specifier '.' attribute
|
|
|
|
|
{
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (algebra_subtype ($1.type, $3));
|
2023-08-25 13:06:44 +00:00
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
| enum_specifier
|
|
|
|
|
| struct_specifier
|
2023-02-08 02:18:42 +00:00
|
|
|
|
// NOTE: fields don't parse the way they should. This is not a problem
|
|
|
|
|
// for basic types, but functions need special treatment
|
|
|
|
|
| '.' typespec_reserved
|
|
|
|
|
{
|
|
|
|
|
// avoid find_type()
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (field_type (0));
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$.type = append_type ($$.type, $2.type);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
typespec_nonreserved
|
2023-08-25 13:06:44 +00:00
|
|
|
|
: TYPE_NAME %prec LOW
|
|
|
|
|
| TYPE_NAME '.' attribute
|
|
|
|
|
{
|
|
|
|
|
if (!is_algebra ($1.type)) {
|
|
|
|
|
error (0, "%s does not have any subtypes",
|
|
|
|
|
get_type_string ($1.type));
|
|
|
|
|
$$ = $1;
|
|
|
|
|
} else {
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (algebra_subtype ($1.type, $3));
|
2023-08-25 13:06:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| OBJECT_NAME protocolrefs
|
2012-12-18 03:49:43 +00:00
|
|
|
|
{
|
2012-12-18 11:45:48 +00:00
|
|
|
|
if ($2) {
|
2024-08-16 08:23:29 +00:00
|
|
|
|
type_t type = *type_id.fldptr.type;
|
2012-12-20 04:12:05 +00:00
|
|
|
|
type.next = 0;
|
2012-12-18 11:45:48 +00:00
|
|
|
|
type.protos = $2;
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (pointer_type (find_type (&type)));
|
2012-12-18 11:45:48 +00:00
|
|
|
|
} else {
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (&type_id);
|
2012-12-18 11:45:48 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$.sym = $1.sym;
|
|
|
|
|
}
|
|
|
|
|
| CLASS_NAME protocolrefs
|
|
|
|
|
{
|
|
|
|
|
if ($2) {
|
|
|
|
|
type_t type = *$1->type;
|
|
|
|
|
type.next = 0;
|
|
|
|
|
type.protos = $2;
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (find_type (&type));
|
2023-02-08 02:18:42 +00:00
|
|
|
|
} else {
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec ($1->type);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
2020-02-27 08:50:11 +00:00
|
|
|
|
$$.sym = $1;
|
2012-12-18 03:49:43 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
// NOTE: fields don't parse the way they should. This is not a problem
|
|
|
|
|
// for basic types, but functions need special treatment
|
|
|
|
|
| '.' typespec_nonreserved
|
|
|
|
|
{
|
|
|
|
|
// avoid find_type()
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (field_type (0));
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$.type = append_type ($$.type, $2.type);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
defspecs
|
|
|
|
|
: /* empty */
|
|
|
|
|
{
|
|
|
|
|
$$ = (specifier_t) {};
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
save_storage
|
|
|
|
|
: /* emtpy */
|
|
|
|
|
{
|
|
|
|
|
$$.storage = current_storage;
|
2024-08-10 11:04:58 +00:00
|
|
|
|
$$.is_generic = generic_block;
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
function_body
|
2023-09-24 06:04:25 +00:00
|
|
|
|
: method_optional_state_expr
|
2023-02-08 02:18:42 +00:00
|
|
|
|
{
|
|
|
|
|
specifier_t spec = default_type ($<spec>0, $<spec>0.sym);
|
2024-08-26 01:35:33 +00:00
|
|
|
|
$<symbol>$ = function_symbol (spec);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
save_storage
|
|
|
|
|
{
|
2024-05-05 07:45:05 +00:00
|
|
|
|
$<funcstate>$ = (funcstate_t) {
|
|
|
|
|
.symtab = current_symtab,
|
|
|
|
|
.function = current_func,
|
|
|
|
|
};
|
2023-02-08 02:18:42 +00:00
|
|
|
|
current_func = begin_function ($<symbol>2, 0, current_symtab, 0,
|
|
|
|
|
$<spec>-1.storage);
|
|
|
|
|
current_symtab = current_func->locals;
|
|
|
|
|
current_storage = sc_local;
|
|
|
|
|
}
|
2024-10-07 00:55:21 +00:00
|
|
|
|
compound_statement_ns
|
2023-02-08 02:18:42 +00:00
|
|
|
|
{
|
|
|
|
|
build_code_function ($<symbol>2, $1, $5);
|
2024-05-05 07:45:05 +00:00
|
|
|
|
current_symtab = $<funcstate>4.symtab;
|
|
|
|
|
current_func = $<funcstate>4.function;
|
2024-08-10 11:04:58 +00:00
|
|
|
|
restore_storage ($3);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| '=' '#' expr ';'
|
|
|
|
|
{
|
2024-08-20 06:19:31 +00:00
|
|
|
|
specifier_t spec = $<spec>0;
|
2024-08-26 01:31:57 +00:00
|
|
|
|
const expr_t *bi_val = $3;
|
2024-08-20 06:19:31 +00:00
|
|
|
|
|
2024-08-26 01:35:33 +00:00
|
|
|
|
symbol_t *sym = function_symbol (spec);
|
2024-08-26 01:31:57 +00:00
|
|
|
|
build_builtin_function (sym, bi_val, 0, spec.storage);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
2024-11-24 16:39:27 +00:00
|
|
|
|
| '=' intrinsic
|
|
|
|
|
{
|
|
|
|
|
specifier_t spec = $<spec>0;
|
|
|
|
|
build_intrinsic_function (spec, $2);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
intrinsic
|
|
|
|
|
: INTRINSIC '(' expr_list ')' { $$ = new_intrinsic_expr ($3); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
storage_class
|
2024-08-10 08:25:24 +00:00
|
|
|
|
: EXTERN { $$ = storage_spec (sc_extern); }
|
|
|
|
|
| STATIC { $$ = storage_spec (sc_static); }
|
|
|
|
|
| SYSTEM { $$ = storage_spec (sc_system); }
|
|
|
|
|
| TYPEDEF { $$ = typedef_spec (); }
|
|
|
|
|
| OVERLOAD { $$ = overload_spec (); }
|
|
|
|
|
| GENERIC '(' { $<spec>$ = generic_spec (); }
|
2024-04-25 07:10:43 +00:00
|
|
|
|
generic_param_list ')'
|
|
|
|
|
{
|
2024-08-10 11:04:58 +00:00
|
|
|
|
$$ = $<spec>3;
|
|
|
|
|
|
2024-04-25 07:10:43 +00:00
|
|
|
|
if (generic_scope) {
|
|
|
|
|
error (0, "multiple @generic in declaration");
|
2024-08-10 11:04:58 +00:00
|
|
|
|
$$.multi_generic = true;
|
2024-04-25 07:10:43 +00:00
|
|
|
|
} else {
|
|
|
|
|
generic_scope = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| ATTRIBUTE '(' attribute_list ')'
|
|
|
|
|
{
|
2024-11-22 05:15:08 +00:00
|
|
|
|
$$ = (specifier_t) { .attributes = $3 };
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2024-04-25 07:10:43 +00:00
|
|
|
|
generic_param_list
|
|
|
|
|
: generic_param
|
|
|
|
|
{
|
|
|
|
|
auto spec = $<spec>0;
|
|
|
|
|
symtab_addsymbol (spec.symtab, $1);
|
|
|
|
|
}
|
|
|
|
|
| generic_param_list ',' generic_param
|
|
|
|
|
{
|
|
|
|
|
auto spec = $<spec>0;
|
|
|
|
|
symtab_addsymbol (spec.symtab, $3);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
generic_param
|
2024-04-26 06:20:13 +00:00
|
|
|
|
: NAME { $$ = type_parameter ($1, nullptr); }
|
|
|
|
|
| NAME '=' generic_type { $$ = type_parameter ($1, $3); }
|
2024-04-25 07:10:43 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
generic_type
|
2024-04-26 06:20:13 +00:00
|
|
|
|
: type_function { $$ = $1; }
|
2024-04-25 22:59:21 +00:00
|
|
|
|
| '[' type_list ']' { $$ = $2; }
|
2024-04-25 07:10:43 +00:00
|
|
|
|
;
|
|
|
|
|
|
2024-04-26 06:20:13 +00:00
|
|
|
|
type_function
|
|
|
|
|
: type_func '(' type_param_list ')' { $$ = type_function ($1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
type_func
|
|
|
|
|
: AT_FIELD { $$ = QC_AT_FIELD; }
|
2024-05-31 07:39:50 +00:00
|
|
|
|
| AT_FUNCTION { $$ = QC_AT_FUNCTION; }
|
2024-04-26 06:20:13 +00:00
|
|
|
|
| AT_POINTER { $$ = QC_AT_POINTER; }
|
|
|
|
|
| AT_ARRAY { $$ = QC_AT_ARRAY; }
|
|
|
|
|
| AT_BASE { $$ = QC_AT_BASE; }
|
|
|
|
|
| AT_VECTOR { $$ = QC_AT_VECTOR; }
|
|
|
|
|
| AT_MATRIX { $$ = QC_AT_MATRIX; }
|
|
|
|
|
| AT_INT { $$ = QC_AT_INT; }
|
|
|
|
|
| AT_UINT { $$ = QC_AT_UINT; }
|
|
|
|
|
| AT_BOOL { $$ = QC_AT_BOOL; }
|
|
|
|
|
| AT_FLOAT { $$ = QC_AT_FLOAT; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
type_op
|
|
|
|
|
: AT_WIDTH { $$ = QC_AT_WIDTH; }
|
|
|
|
|
| AT_ROWS { $$ = QC_AT_ROWS; }
|
|
|
|
|
| AT_COLS { $$ = QC_AT_COLS; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
type_param_list
|
|
|
|
|
: type_param { $$ = new_list_expr ($1); }
|
|
|
|
|
| type_param_list ',' type_param { $$ = expr_append_expr ($1, $3); }
|
2024-04-24 06:45:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
type_param
|
2024-04-26 06:20:13 +00:00
|
|
|
|
: type_function
|
2024-04-24 06:45:26 +00:00
|
|
|
|
| type_ref
|
2024-04-26 06:20:13 +00:00
|
|
|
|
| expr
|
2024-04-24 06:45:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2024-04-25 07:10:43 +00:00
|
|
|
|
type_list
|
2024-04-25 22:59:21 +00:00
|
|
|
|
: type_ref { $$ = new_list_expr ($1); }
|
|
|
|
|
| type_list ',' type_ref { $$ = expr_append_expr ($1, $3); }
|
2024-04-25 07:10:43 +00:00
|
|
|
|
;
|
|
|
|
|
|
2024-04-24 06:45:26 +00:00
|
|
|
|
type_ref
|
2024-09-04 00:41:57 +00:00
|
|
|
|
: type_ref_spec { $$ = new_type_expr ($1.type); }
|
2024-04-25 22:59:21 +00:00
|
|
|
|
| CLASS_NAME { $$ = new_type_expr ($1->type); }
|
2024-07-04 14:44:07 +00:00
|
|
|
|
| TYPE_NAME
|
|
|
|
|
{
|
|
|
|
|
if ($1.type_expr) {
|
|
|
|
|
$$ = $1.type_expr;
|
|
|
|
|
} else {
|
|
|
|
|
$$ = new_type_expr ($1.type);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-24 06:45:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2024-09-04 00:41:57 +00:00
|
|
|
|
type_ref_spec
|
|
|
|
|
: TYPE_SPEC
|
|
|
|
|
| type_ref_spec TYPE_SPEC { $$ = spec_merge ($1, $2); }
|
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
attribute_list
|
|
|
|
|
: attribute
|
|
|
|
|
| attribute_list ',' attribute
|
2011-02-07 23:20:32 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
if ($3) {
|
|
|
|
|
$3->next = $1;
|
|
|
|
|
$$ = $3;
|
2012-12-18 11:45:48 +00:00
|
|
|
|
} else {
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = $1;
|
2012-12-18 11:45:48 +00:00
|
|
|
|
}
|
2004-11-13 11:50:00 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
attribute
|
2023-08-25 13:06:44 +00:00
|
|
|
|
: NAME %prec LOW { $$ = new_attribute ($1->name, 0); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| NAME '(' expr_list ')' { $$ = new_attribute ($1->name, $3); }
|
2002-06-28 17:59:32 +00:00
|
|
|
|
;
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
tag : NAME ;
|
|
|
|
|
|
2023-08-21 08:37:56 +00:00
|
|
|
|
algebra_specifier
|
|
|
|
|
: ALGEBRA '(' TYPE_SPEC '(' expr_list ')' ')'
|
|
|
|
|
{
|
2024-08-10 08:25:24 +00:00
|
|
|
|
auto spec = type_spec (algebra_type ($3.type, $5));
|
2023-08-21 08:37:56 +00:00
|
|
|
|
$$ = spec;
|
|
|
|
|
}
|
|
|
|
|
| ALGEBRA '(' TYPE_SPEC ')'
|
|
|
|
|
{
|
2024-08-10 08:25:24 +00:00
|
|
|
|
auto spec = type_spec (algebra_type ($3.type, 0));
|
2023-08-21 08:37:56 +00:00
|
|
|
|
$$ = spec;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
enum_specifier
|
2011-02-03 01:48:12 +00:00
|
|
|
|
: ENUM tag optional_enum_list
|
|
|
|
|
{
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec ($3->type);
|
2011-02-03 01:48:12 +00:00
|
|
|
|
if (!$3->table)
|
|
|
|
|
symtab_addsymbol (current_symtab, $3);
|
|
|
|
|
}
|
|
|
|
|
| ENUM enum_list
|
|
|
|
|
{
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec ($2->type);
|
2011-02-03 01:48:12 +00:00
|
|
|
|
if (!$2->table)
|
|
|
|
|
symtab_addsymbol (current_symtab, $2);
|
|
|
|
|
}
|
2006-12-11 09:26:07 +00:00
|
|
|
|
;
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
optional_enum_list
|
2011-02-06 11:07:19 +00:00
|
|
|
|
: enum_list
|
2011-02-01 12:23:03 +00:00
|
|
|
|
| /* empty */ { $$ = find_enum ($<symbol>0); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
enum_list
|
2013-01-17 11:55:25 +00:00
|
|
|
|
: '{' enum_init enumerator_list optional_comma '}'
|
|
|
|
|
{
|
2020-02-18 16:28:09 +00:00
|
|
|
|
current_symtab = current_symtab->parent;
|
2013-01-17 11:55:25 +00:00
|
|
|
|
$$ = finish_enum ($3);
|
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
enum_init
|
2001-12-08 08:19:48 +00:00
|
|
|
|
: /* empty */
|
2011-02-01 12:23:03 +00:00
|
|
|
|
{
|
|
|
|
|
$$ = find_enum ($<symbol>-1);
|
|
|
|
|
start_enum ($$);
|
2024-08-16 08:23:29 +00:00
|
|
|
|
current_symtab = $$->type->symtab;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
enumerator_list
|
|
|
|
|
: enumerator { $$ = $<symbol>0; }
|
|
|
|
|
| enumerator_list ',' { $<symbol>$ = $<symbol>0; }
|
2011-06-21 10:52:47 +00:00
|
|
|
|
enumerator
|
|
|
|
|
{
|
|
|
|
|
$$ = $<symbol>0;
|
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
enumerator
|
|
|
|
|
: identifier { add_enum ($<symbol>0, $1, 0); }
|
2019-06-09 15:36:13 +00:00
|
|
|
|
| identifier '=' expr { add_enum ($<symbol>0, $1, $3); }
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
struct_specifier
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: STRUCT tag struct_list { $$ = $3; }
|
|
|
|
|
| STRUCT {$<symbol>$ = 0;} struct_list { $$ = $3; }
|
|
|
|
|
| STRUCT tag
|
2011-02-01 12:23:03 +00:00
|
|
|
|
{
|
2011-02-13 11:55:33 +00:00
|
|
|
|
symbol_t *sym;
|
2023-02-08 02:18:42 +00:00
|
|
|
|
|
2011-02-13 11:55:33 +00:00
|
|
|
|
sym = find_struct ($1, $2, 0);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
sym->type = find_type (sym->type);
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (sym->type);
|
2019-06-08 10:25:25 +00:00
|
|
|
|
if (!sym->table) {
|
2023-02-08 02:18:42 +00:00
|
|
|
|
symtab_t *tab = current_symtab;
|
|
|
|
|
while (tab->parent && tab->type == stab_struct) {
|
|
|
|
|
tab = tab->parent;
|
2020-03-02 11:16:29 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
symtab_addsymbol (tab, sym);
|
2019-06-08 10:25:25 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
2023-10-02 14:33:37 +00:00
|
|
|
|
| handle tag
|
[qfcc] Add a handle type for engine resources
I never liked the various hacks I had come up with for representing
resource handles in Ruamoko. Structs with an int were awkward to test,
pointers and ints could be modified, etc etc. The new @handle keyword (@
used to keep handle free for use) works just like struct, union and
enum in syntax, but creates an opaque type suitable for a 32-bit handle.
The backing type is a function so v6 progs can use it without (all the
necessary opcodes exist) and no modifications were needed for
type-checking in binary expressions, but only assignment and comparisons
are supported, and (of course) nil. Tested using cbuf_t and QFile: seems
to work as desired.
I had considered 64-bit handles, but really, if more than 4G resource
objects are needed, I'm not sure QF can handle the game. However, that
limit is per resource manager, not total.
2023-05-25 01:41:28 +00:00
|
|
|
|
{
|
2023-10-02 14:33:37 +00:00
|
|
|
|
specifier_t spec = default_type ($1, 0);
|
|
|
|
|
symbol_t *sym = find_handle ($2, spec.type);
|
[qfcc] Add a handle type for engine resources
I never liked the various hacks I had come up with for representing
resource handles in Ruamoko. Structs with an int were awkward to test,
pointers and ints could be modified, etc etc. The new @handle keyword (@
used to keep handle free for use) works just like struct, union and
enum in syntax, but creates an opaque type suitable for a 32-bit handle.
The backing type is a function so v6 progs can use it without (all the
necessary opcodes exist) and no modifications were needed for
type-checking in binary expressions, but only assignment and comparisons
are supported, and (of course) nil. Tested using cbuf_t and QFile: seems
to work as desired.
I had considered 64-bit handles, but really, if more than 4G resource
objects are needed, I'm not sure QF can handle the game. However, that
limit is per resource manager, not total.
2023-05-25 01:41:28 +00:00
|
|
|
|
sym->type = find_type (sym->type);
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (sym->type);
|
[qfcc] Add a handle type for engine resources
I never liked the various hacks I had come up with for representing
resource handles in Ruamoko. Structs with an int were awkward to test,
pointers and ints could be modified, etc etc. The new @handle keyword (@
used to keep handle free for use) works just like struct, union and
enum in syntax, but creates an opaque type suitable for a 32-bit handle.
The backing type is a function so v6 progs can use it without (all the
necessary opcodes exist) and no modifications were needed for
type-checking in binary expressions, but only assignment and comparisons
are supported, and (of course) nil. Tested using cbuf_t and QFile: seems
to work as desired.
I had considered 64-bit handles, but really, if more than 4G resource
objects are needed, I'm not sure QF can handle the game. However, that
limit is per resource manager, not total.
2023-05-25 01:41:28 +00:00
|
|
|
|
if (!sym->table) {
|
|
|
|
|
symtab_t *tab = current_symtab;
|
|
|
|
|
while (tab->parent && tab->type == stab_struct) {
|
|
|
|
|
tab = tab->parent;
|
|
|
|
|
}
|
|
|
|
|
symtab_addsymbol (tab, sym);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-10-02 14:33:37 +00:00
|
|
|
|
handle
|
2024-08-10 08:25:24 +00:00
|
|
|
|
: HANDLE { $$ = type_spec (&type_int); }
|
2023-10-02 14:33:37 +00:00
|
|
|
|
| HANDLE '(' TYPE_SPEC ')' { $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
struct_list
|
|
|
|
|
: '{'
|
|
|
|
|
{
|
|
|
|
|
int op = $<op>-1;
|
|
|
|
|
symbol_t *sym = $<symbol>0;
|
|
|
|
|
current_symtab = start_struct (&op, sym, current_symtab);
|
|
|
|
|
$<op>1 = op;
|
|
|
|
|
$<symbol>$ = sym;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
|
|
|
|
struct_defs '}'
|
|
|
|
|
{
|
2011-02-02 13:53:53 +00:00
|
|
|
|
symbol_t *sym;
|
2011-02-01 12:23:03 +00:00
|
|
|
|
symtab_t *symtab = current_symtab;
|
|
|
|
|
current_symtab = symtab->parent;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
if ($<op>1) {
|
|
|
|
|
sym = $<symbol>2;
|
|
|
|
|
sym = build_struct ($<op>1, sym, symtab, 0, 0);
|
2024-08-10 08:25:24 +00:00
|
|
|
|
$$ = type_spec (sym->type);
|
2019-06-08 10:25:25 +00:00
|
|
|
|
if (!sym->table)
|
|
|
|
|
symtab_addsymbol (current_symtab, sym);
|
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
struct_defs
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: component_decl_list
|
2004-11-02 07:02:00 +00:00
|
|
|
|
| DEFS '(' identifier ')'
|
2002-05-10 00:00:23 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$3 = check_undefined ($3);
|
2020-03-27 06:16:41 +00:00
|
|
|
|
if (!$3->type || !is_class ($3->type)) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
error (0, "`%s' is not a class", $3->name);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
} else {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
// replace the struct symbol table with one built from
|
|
|
|
|
// the class ivars and the current struct fields. ivars
|
|
|
|
|
// will replace any fields of the same name.
|
2024-08-16 08:23:29 +00:00
|
|
|
|
current_symtab = class_to_struct ($3->type->class,
|
2011-01-17 13:33:33 +00:00
|
|
|
|
current_symtab);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-08 08:19:48 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
component_decl_list
|
|
|
|
|
: component_decl_list2
|
|
|
|
|
| component_decl_list2 component_decl
|
2023-05-26 15:59:43 +00:00
|
|
|
|
{
|
|
|
|
|
warning (0, "no semicolon at end of struct or union");
|
|
|
|
|
}
|
2012-12-18 06:54:30 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
component_decl_list2
|
|
|
|
|
: /* empty */
|
|
|
|
|
| component_decl_list2 component_decl ';'
|
|
|
|
|
| component_decl_list2 ';'
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
component_decl
|
|
|
|
|
: declspecs_nosc_ts components
|
|
|
|
|
| declspecs_nosc_ts
|
2020-02-27 08:50:11 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
if (is_anonymous_struct ($1)) {
|
2020-03-04 07:31:28 +00:00
|
|
|
|
// type->name always begins with "tag "
|
2021-01-31 07:01:20 +00:00
|
|
|
|
$1.sym = new_symbol (va (0, ".anonymous.%s",
|
|
|
|
|
$1.type->name + 4));
|
2020-03-04 07:31:28 +00:00
|
|
|
|
$1.sym->type = $1.type;
|
2024-09-20 02:27:15 +00:00
|
|
|
|
$1.sym->sy_type = sy_offset;
|
2020-03-04 07:31:28 +00:00
|
|
|
|
$1.sym->visibility = vis_anonymous;
|
|
|
|
|
symtab_addsymbol (current_symtab, $1.sym);
|
|
|
|
|
if (!$1.sym->table) {
|
|
|
|
|
error (0, "duplicate field `%s'", $1.sym->name);
|
|
|
|
|
}
|
2020-02-27 08:50:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declspecs_nosc_nots components_notype
|
|
|
|
|
| declspecs_nosc_nots { internal_error (0, "not implemented"); }
|
2001-06-12 19:44:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
components
|
|
|
|
|
: component_declarator
|
|
|
|
|
| components ',' { $<spec>$ = $<spec>0; } component_declarator
|
2006-12-02 06:49:55 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
component_declarator
|
|
|
|
|
: declarator
|
2011-02-04 14:48:58 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
declare_field ($1, current_symtab);
|
2011-02-04 14:48:58 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declarator ':' expr
|
|
|
|
|
| ':' expr
|
2011-03-07 01:43:38 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
components_notype
|
|
|
|
|
: component_notype_declarator
|
|
|
|
|
| components_notype ',' component_notype_declarator
|
2002-01-21 19:03:29 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
component_notype_declarator
|
|
|
|
|
: notype_declarator { internal_error (0, "not implemented"); }
|
|
|
|
|
| notype_declarator ':' expr
|
|
|
|
|
| ':' expr
|
2004-02-08 23:46:40 +00:00
|
|
|
|
;
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
function_params
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: '(' copy_spec param_list ')' { $$ = check_params ($3); }
|
2011-02-13 08:07:14 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
param_list
|
|
|
|
|
: /* empty */ { $$ = 0; }
|
|
|
|
|
| parameter_list
|
|
|
|
|
| parameter_list ',' ELLIPSIS
|
2011-02-02 06:13:34 +00:00
|
|
|
|
{
|
2024-09-18 05:33:02 +00:00
|
|
|
|
if (options.code.no_vararg) {
|
|
|
|
|
PARSE_ERROR;
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = param_append_identifiers ($1, 0, 0);
|
2011-02-02 06:13:34 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| ELLIPSIS
|
2011-02-02 06:13:34 +00:00
|
|
|
|
{
|
2024-09-18 05:33:02 +00:00
|
|
|
|
if (options.code.no_vararg) {
|
|
|
|
|
PARSE_ERROR;
|
|
|
|
|
}
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_ellipsis ();
|
2011-02-02 06:13:34 +00:00
|
|
|
|
}
|
2011-01-17 13:33:33 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
parameter_list
|
|
|
|
|
: parameter
|
|
|
|
|
| parameter_list ',' parameter
|
2011-02-13 08:07:14 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = append_params ($1, $3);
|
2011-02-13 08:07:14 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
parameter
|
|
|
|
|
: declspecs_ts param_declarator
|
2002-08-18 04:08:02 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_param ($2);
|
2011-01-17 13:33:33 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declspecs_ts notype_declarator
|
2011-01-17 13:33:33 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_param ($2);
|
2011-01-17 13:33:33 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declspecs_ts absdecl
|
2011-01-17 13:33:33 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_param ($2);
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declspecs_nosc_nots notype_declarator
|
2011-02-01 12:23:03 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_param ($2);
|
2002-08-18 04:08:02 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declspecs_nosc_nots absdecl
|
2011-02-01 12:23:03 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = make_param ($2);
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
2011-01-17 13:33:33 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
absdecl
|
2023-03-08 17:22:23 +00:00
|
|
|
|
: /* empty */
|
|
|
|
|
{
|
|
|
|
|
$$ = $<spec>0;
|
|
|
|
|
$$.sym = new_symbol (0);
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| absdecl1
|
2002-05-01 21:35:39 +00:00
|
|
|
|
;
|
2011-02-07 23:16:36 +00:00
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
absdecl1
|
|
|
|
|
: direct_absdecl
|
|
|
|
|
| '*' ptr_spec absdecl
|
2011-06-21 10:52:47 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = pointer_spec ($2, $3);
|
2011-06-21 10:52:47 +00:00
|
|
|
|
}
|
2002-05-01 21:35:39 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
direct_absdecl
|
|
|
|
|
: '(' copy_spec absdecl1 ')' { $$ = $3; }
|
|
|
|
|
| direct_absdecl function_params
|
2011-01-17 13:33:33 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = function_spec ($1, $2);
|
2011-01-17 13:33:33 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| direct_absdecl array_decl
|
2011-03-07 11:04:05 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = array_spec ($1, $2);
|
2011-03-07 11:04:05 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| function_params
|
2011-06-21 10:52:47 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = function_spec ($<spec>0, $1);
|
2011-06-21 10:52:47 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| array_decl
|
2001-11-14 22:31:57 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = array_spec ($<spec>0, $1);
|
2001-11-14 22:31:57 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
param_declarator
|
|
|
|
|
: param_declarator_starttypename
|
|
|
|
|
| param_declarator_nostarttypename
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
param_declarator_starttypename
|
|
|
|
|
: param_declarator_starttypename function_params
|
|
|
|
|
{ $$ = $1; internal_error (0, "not implemented"); }
|
|
|
|
|
| param_declarator_starttypename array_decl
|
|
|
|
|
{ $$ = $1; internal_error (0, "not implemented"); }
|
|
|
|
|
| TYPE_NAME
|
|
|
|
|
{ $$ = $1; internal_error (0, "not implemented"); }
|
|
|
|
|
| OBJECT_NAME
|
|
|
|
|
{ $$ = $1; internal_error (0, "not implemented"); }
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
param_declarator_nostarttypename
|
|
|
|
|
: param_declarator_nostarttypename function_params
|
|
|
|
|
{ $$ = $1; internal_error (0, "not implemented"); }
|
|
|
|
|
| param_declarator_nostarttypename array_decl
|
|
|
|
|
{ $$ = $1; internal_error (0, "not implemented"); }
|
|
|
|
|
| '*' ptr_spec param_declarator_starttypename
|
|
|
|
|
{ $$ = $3; internal_error (0, "not implemented"); }
|
|
|
|
|
| '*' ptr_spec param_declarator_nostarttypename
|
|
|
|
|
{ $$ = $3; internal_error (0, "not implemented"); }
|
|
|
|
|
| '(' copy_spec param_declarator_nostarttypename ')' { $$ = $3; }
|
2011-02-01 12:23:03 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
typename
|
|
|
|
|
: declspecs_nosc absdecl
|
2004-11-13 11:50:00 +00:00
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
$$ = typename_spec ($2);
|
2004-11-13 11:50:00 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
array_decl
|
|
|
|
|
: '[' expr ']'
|
2011-01-26 05:48:22 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
if (is_int_val ($2) && expr_int ($2) > 0) {
|
|
|
|
|
$$ = expr_int ($2);
|
|
|
|
|
} else if (is_uint_val ($2) && expr_uint ($2) > 0) {
|
|
|
|
|
$$ = expr_uint ($2);
|
2011-02-22 03:07:31 +00:00
|
|
|
|
} else {
|
2023-02-08 02:18:42 +00:00
|
|
|
|
error (0, "invalid array size");
|
|
|
|
|
$$ = 0;
|
2011-02-22 03:07:31 +00:00
|
|
|
|
}
|
2011-01-26 05:48:22 +00:00
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| '[' ']' { $$ = 0; }
|
2004-02-10 23:20:44 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
decl
|
2023-09-25 07:03:29 +00:00
|
|
|
|
: declspecs_ts local_expr initdecls seq_semi
|
2011-01-22 06:52:57 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = local_expr;
|
|
|
|
|
local_expr = 0;
|
2011-01-22 06:52:57 +00:00
|
|
|
|
}
|
2023-09-25 07:03:29 +00:00
|
|
|
|
| declspecs_nots local_expr notype_initdecls seq_semi
|
2011-01-22 06:52:57 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = local_expr;
|
|
|
|
|
local_expr = 0;
|
2011-01-22 06:52:57 +00:00
|
|
|
|
}
|
2023-02-11 11:29:59 +00:00
|
|
|
|
| declspecs_ts local_expr qc_func_params
|
|
|
|
|
{
|
2024-05-04 01:50:08 +00:00
|
|
|
|
$<spec>$ = qc_function_spec ($1, $3);
|
2023-02-11 11:29:59 +00:00
|
|
|
|
}
|
|
|
|
|
qc_func_decls
|
|
|
|
|
{
|
|
|
|
|
$$ = local_expr;
|
|
|
|
|
local_expr = 0;
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declspecs ';' { $$ = 0; }
|
2004-02-10 03:25:24 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
local_expr
|
|
|
|
|
: /* emtpy */
|
|
|
|
|
{
|
|
|
|
|
$<spec>$ = $<spec>0;
|
2023-09-27 03:41:31 +00:00
|
|
|
|
local_expr = new_block_expr (0);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
2001-11-14 22:31:57 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-01 21:35:39 +00:00
|
|
|
|
var_initializer
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: expr { $$ = $1; }
|
|
|
|
|
| compound_init
|
2020-02-27 11:30:07 +00:00
|
|
|
|
{
|
2023-02-08 02:18:42 +00:00
|
|
|
|
if (!$1 && is_scalar ($<spec>-1.type)) {
|
2020-02-27 11:30:07 +00:00
|
|
|
|
error (0, "empty scalar initializer");
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
$$ = $1 ? $1 : new_nil_expr ();
|
2020-02-27 11:30:07 +00:00
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2020-03-11 06:46:57 +00:00
|
|
|
|
compound_init
|
2024-11-17 04:17:36 +00:00
|
|
|
|
: opt_cast '{' element_list optional_comma '}'
|
|
|
|
|
{
|
|
|
|
|
auto type = resolve_type_spec ($1);
|
|
|
|
|
$3->compound.type = type;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
}
|
|
|
|
|
| opt_cast '{' '}'
|
|
|
|
|
{
|
|
|
|
|
auto type = resolve_type_spec ($1);
|
|
|
|
|
if (type) {
|
|
|
|
|
auto elements = new_compound_init ();
|
|
|
|
|
elements->compound.type = type;
|
|
|
|
|
$$ = elements;
|
|
|
|
|
} else {
|
|
|
|
|
$$ = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
opt_cast
|
|
|
|
|
: '(' typename ')' { $$ = $2; }
|
|
|
|
|
| /*empty*/ { $$ = (specifier_t) {}; }
|
2020-03-11 06:46:57 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-09-24 06:04:25 +00:00
|
|
|
|
method_optional_state_expr
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: /* emtpy */ { $$ = 0; }
|
|
|
|
|
| SHR vector_expr { $$ = build_state_expr ($2); }
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
optional_state_expr
|
2011-01-25 03:07:02 +00:00
|
|
|
|
: /* emtpy */ { $$ = 0; }
|
2013-06-24 02:36:52 +00:00
|
|
|
|
| vector_expr { $$ = build_state_expr ($1); }
|
2004-02-11 01:43:33 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-01 21:35:39 +00:00
|
|
|
|
element_list
|
|
|
|
|
: element
|
|
|
|
|
{
|
2020-03-11 06:46:57 +00:00
|
|
|
|
$$ = new_compound_init ();
|
|
|
|
|
append_element ($$, $1);
|
2002-05-01 21:35:39 +00:00
|
|
|
|
}
|
2024-04-22 00:36:47 +00:00
|
|
|
|
| element_list ',' element
|
2002-05-01 21:35:39 +00:00
|
|
|
|
{
|
2020-03-11 06:46:57 +00:00
|
|
|
|
append_element ($$, $3);
|
2002-05-01 21:35:39 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
element
|
2023-05-26 15:59:43 +00:00
|
|
|
|
: designator '=' compound_init { $$ = new_element ($3, $1); }
|
|
|
|
|
| designator '=' expr { $$ = new_element ($3, $1); }
|
|
|
|
|
| compound_init { $$ = new_element ($1, 0); }
|
2020-03-11 10:42:38 +00:00
|
|
|
|
| expr { $$ = new_element ($1, 0); }
|
2002-05-01 21:35:39 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-05-26 15:59:43 +00:00
|
|
|
|
designator
|
|
|
|
|
: designator_spec
|
|
|
|
|
| designator designator_spec
|
|
|
|
|
{
|
|
|
|
|
designator_t *des = $1;
|
|
|
|
|
while (des->next) {
|
|
|
|
|
des = des->next;
|
|
|
|
|
}
|
|
|
|
|
des->next = $2;
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
designator_spec
|
|
|
|
|
: '.' ident_expr { $$ = new_designator ($2, 0); }
|
|
|
|
|
| '.' NAME { $$ = new_designator (new_symbol_expr ($2), 0); }
|
|
|
|
|
| '[' expr ']' { $$ = new_designator (0, $2); }
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
optional_comma
|
2002-05-01 21:35:39 +00:00
|
|
|
|
: /* empty */
|
|
|
|
|
| ','
|
|
|
|
|
;
|
|
|
|
|
|
2019-06-08 12:52:17 +00:00
|
|
|
|
push_scope
|
|
|
|
|
: /* empty */
|
2001-06-20 07:02:36 +00:00
|
|
|
|
{
|
2011-01-25 03:34:45 +00:00
|
|
|
|
if (!options.traditional) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
current_symtab = new_symtab (current_symtab, stab_local);
|
2011-01-25 03:34:45 +00:00
|
|
|
|
current_symtab->space = current_symtab->parent->space;
|
|
|
|
|
}
|
2001-10-24 06:39:49 +00:00
|
|
|
|
}
|
2019-06-08 12:52:17 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
pop_scope
|
|
|
|
|
: /* empty */
|
2001-10-24 06:39:49 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
if (!options.traditional)
|
|
|
|
|
current_symtab = current_symtab->parent;
|
2001-06-20 07:02:36 +00:00
|
|
|
|
}
|
2001-06-12 19:44:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2023-09-25 07:03:29 +00:00
|
|
|
|
flush_dag
|
|
|
|
|
: /* empty */
|
|
|
|
|
{
|
|
|
|
|
if (!no_flush_dag) {
|
|
|
|
|
edag_flush ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
seq_semi
|
|
|
|
|
: ';' flush_dag
|
|
|
|
|
;
|
|
|
|
|
|
2019-06-08 12:52:17 +00:00
|
|
|
|
compound_statement
|
2023-09-25 07:03:29 +00:00
|
|
|
|
: '{' push_scope flush_dag statements '}' pop_scope flush_dag { $$ = $4; }
|
2019-06-08 12:52:17 +00:00
|
|
|
|
;
|
|
|
|
|
|
2024-10-07 00:55:21 +00:00
|
|
|
|
compound_statement_ns
|
|
|
|
|
: '{' flush_dag statements '}' flush_dag { $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
2001-06-12 19:44:26 +00:00
|
|
|
|
statements
|
|
|
|
|
: /*empty*/
|
2001-06-20 07:02:36 +00:00
|
|
|
|
{
|
2023-09-27 03:41:31 +00:00
|
|
|
|
$$ = new_block_expr (0);
|
2001-06-20 07:02:36 +00:00
|
|
|
|
}
|
2023-09-25 07:03:29 +00:00
|
|
|
|
| statements flush_dag statement
|
2001-06-20 07:02:36 +00:00
|
|
|
|
{
|
2023-09-25 07:03:29 +00:00
|
|
|
|
$$ = append_expr ($1, $3);
|
2001-06-20 07:02:36 +00:00
|
|
|
|
}
|
2001-06-12 19:44:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2011-02-07 12:29:04 +00:00
|
|
|
|
local_def
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: LOCAL decl { $$ = $2; }
|
|
|
|
|
| decl
|
2012-11-20 08:11:39 +00:00
|
|
|
|
;
|
2011-02-07 12:29:04 +00:00
|
|
|
|
|
|
|
|
|
statement
|
|
|
|
|
: ';' { $$ = 0; }
|
|
|
|
|
| error ';' { $$ = 0; yyerrok; }
|
|
|
|
|
| compound_statement { $$ = $1; }
|
|
|
|
|
| local_def { $$ = $1; }
|
2020-03-13 00:58:52 +00:00
|
|
|
|
| RETURN opt_expr ';' { $$ = return_expr (current_func, $2); }
|
|
|
|
|
| RETURN compound_init ';' { $$ = return_expr (current_func, $2); }
|
2022-02-05 09:58:42 +00:00
|
|
|
|
| AT_RETURN expr ';' { $$ = at_return_expr (current_func, $2); }
|
2001-10-24 18:57:29 +00:00
|
|
|
|
| BREAK ';'
|
|
|
|
|
{
|
2001-10-25 06:41:52 +00:00
|
|
|
|
$$ = 0;
|
2001-10-24 18:57:29 +00:00
|
|
|
|
if (break_label)
|
2011-03-03 06:28:49 +00:00
|
|
|
|
$$ = goto_expr (break_label);
|
2001-10-24 18:57:29 +00:00
|
|
|
|
else
|
2001-10-25 06:41:52 +00:00
|
|
|
|
error (0, "break outside of loop or switch");
|
2001-10-24 18:57:29 +00:00
|
|
|
|
}
|
|
|
|
|
| CONTINUE ';'
|
|
|
|
|
{
|
2001-10-25 06:41:52 +00:00
|
|
|
|
$$ = 0;
|
2001-10-24 18:57:29 +00:00
|
|
|
|
if (continue_label)
|
2011-03-03 06:28:49 +00:00
|
|
|
|
$$ = goto_expr (continue_label);
|
2001-10-24 18:57:29 +00:00
|
|
|
|
else
|
2001-10-25 06:41:52 +00:00
|
|
|
|
error (0, "continue outside of loop");
|
|
|
|
|
}
|
2020-03-11 02:31:54 +00:00
|
|
|
|
| label
|
|
|
|
|
{
|
|
|
|
|
$$ = named_label_expr ($1);
|
|
|
|
|
}
|
2019-06-09 15:36:13 +00:00
|
|
|
|
| CASE expr ':'
|
2001-10-25 06:41:52 +00:00
|
|
|
|
{
|
|
|
|
|
$$ = case_label_expr (switch_block, $2);
|
|
|
|
|
}
|
|
|
|
|
| DEFAULT ':'
|
|
|
|
|
{
|
|
|
|
|
$$ = case_label_expr (switch_block, 0);
|
|
|
|
|
}
|
2023-09-25 07:03:29 +00:00
|
|
|
|
| SWITCH break_label '(' comma_expr switch_block ')' compound_statement
|
2001-10-25 06:41:52 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = switch_expr (switch_block, break_label, $7);
|
2011-03-05 15:29:29 +00:00
|
|
|
|
switch_block = $5;
|
2001-10-25 06:41:52 +00:00
|
|
|
|
break_label = $2;
|
2001-10-24 18:57:29 +00:00
|
|
|
|
}
|
2020-03-11 03:53:40 +00:00
|
|
|
|
| GOTO NAME
|
|
|
|
|
{
|
2023-09-27 03:41:31 +00:00
|
|
|
|
const expr_t *label = named_label_expr ($2);
|
2020-03-11 03:53:40 +00:00
|
|
|
|
$$ = goto_expr (label);
|
|
|
|
|
}
|
2023-09-25 07:03:29 +00:00
|
|
|
|
| IF not '(' texpr ')' flush_dag statement %prec IFX
|
2001-06-25 20:52:04 +00:00
|
|
|
|
{
|
2023-09-25 07:03:29 +00:00
|
|
|
|
$$ = build_if_statement ($2, $4, $7, 0, 0);
|
2001-06-25 20:52:04 +00:00
|
|
|
|
}
|
2023-09-25 07:03:29 +00:00
|
|
|
|
| IF not '(' texpr ')' flush_dag statement else statement
|
2001-06-25 20:52:04 +00:00
|
|
|
|
{
|
2023-09-25 07:03:29 +00:00
|
|
|
|
$$ = build_if_statement ($2, $4, $7, $8, $9);
|
2001-07-15 01:51:01 +00:00
|
|
|
|
}
|
2019-06-08 12:52:17 +00:00
|
|
|
|
| FOR push_scope break_label continue_label
|
2023-09-25 07:03:29 +00:00
|
|
|
|
'(' opt_init_semi opt_expr seq_semi opt_expr ')' flush_dag statement pop_scope
|
2001-06-25 20:52:04 +00:00
|
|
|
|
{
|
2019-06-09 04:54:03 +00:00
|
|
|
|
if ($6) {
|
2023-09-24 06:04:25 +00:00
|
|
|
|
$6 = build_block_expr ($6, false);
|
2019-06-09 04:54:03 +00:00
|
|
|
|
}
|
2023-09-25 07:03:29 +00:00
|
|
|
|
$$ = build_for_statement ($6, $7, $9, $12,
|
2011-01-17 13:33:33 +00:00
|
|
|
|
break_label, continue_label);
|
2019-06-08 12:52:17 +00:00
|
|
|
|
break_label = $3;
|
|
|
|
|
continue_label = $4;
|
2001-06-25 20:52:04 +00:00
|
|
|
|
}
|
2023-09-25 07:03:29 +00:00
|
|
|
|
| WHILE break_label continue_label not '(' texpr ')' flush_dag statement
|
2001-10-18 23:06:39 +00:00
|
|
|
|
{
|
2023-09-25 07:03:29 +00:00
|
|
|
|
$$ = build_while_statement ($4, $6, $9, break_label,
|
2013-06-25 01:46:51 +00:00
|
|
|
|
continue_label);
|
2011-01-17 13:33:33 +00:00
|
|
|
|
break_label = $2;
|
|
|
|
|
continue_label = $3;
|
2001-10-18 23:06:39 +00:00
|
|
|
|
}
|
2013-06-25 01:46:51 +00:00
|
|
|
|
| DO break_label continue_label statement WHILE not '(' texpr ')' ';'
|
2001-06-25 20:52:04 +00:00
|
|
|
|
{
|
2013-06-25 01:46:51 +00:00
|
|
|
|
$$ = build_do_while_statement ($4, $6, $8,
|
2011-01-17 13:33:33 +00:00
|
|
|
|
break_label, continue_label);
|
2001-10-24 18:57:29 +00:00
|
|
|
|
break_label = $2;
|
|
|
|
|
continue_label = $3;
|
2001-06-25 20:52:04 +00:00
|
|
|
|
}
|
2023-08-21 08:37:56 +00:00
|
|
|
|
| ALGEBRA '(' TYPE_SPEC '(' expr_list ')' ')'
|
|
|
|
|
{
|
|
|
|
|
auto algebra = algebra_type ($3.type, $5);
|
|
|
|
|
current_symtab = algebra_scope (algebra, current_symtab);
|
|
|
|
|
}
|
|
|
|
|
compound_statement
|
|
|
|
|
{
|
|
|
|
|
current_symtab = current_symtab->parent;
|
|
|
|
|
$$ = $9;
|
|
|
|
|
}
|
|
|
|
|
| ALGEBRA '(' TYPE_SPEC ')'
|
|
|
|
|
{
|
|
|
|
|
auto algebra = algebra_type ($3.type, 0);
|
|
|
|
|
current_symtab = algebra_scope (algebra, current_symtab);
|
|
|
|
|
}
|
|
|
|
|
compound_statement
|
|
|
|
|
{
|
|
|
|
|
current_symtab = current_symtab->parent;
|
|
|
|
|
$$ = $6;
|
|
|
|
|
}
|
|
|
|
|
| ALGEBRA '(' TYPE_NAME ')'
|
|
|
|
|
{
|
|
|
|
|
auto algebra = $3.type;
|
|
|
|
|
current_symtab = algebra_scope (algebra, current_symtab);
|
|
|
|
|
}
|
|
|
|
|
compound_statement
|
|
|
|
|
{
|
|
|
|
|
current_symtab = current_symtab->parent;
|
|
|
|
|
$$ = $6;
|
|
|
|
|
}
|
2020-03-11 07:07:58 +00:00
|
|
|
|
| comma_expr ';'
|
2001-06-25 20:52:04 +00:00
|
|
|
|
{
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
2001-06-12 19:44:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2012-12-20 01:02:00 +00:00
|
|
|
|
not
|
|
|
|
|
: NOT { $$ = 1; }
|
|
|
|
|
| /* empty */ { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2012-12-01 07:37:38 +00:00
|
|
|
|
else
|
2023-09-25 07:03:29 +00:00
|
|
|
|
: ELSE flush_dag
|
2012-12-01 07:37:38 +00:00
|
|
|
|
{
|
|
|
|
|
// this is only to get the the file and line number info
|
|
|
|
|
$$ = new_nil_expr ();
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2020-03-11 02:31:54 +00:00
|
|
|
|
label
|
|
|
|
|
: NAME ':'
|
|
|
|
|
;
|
|
|
|
|
|
2020-03-11 02:06:09 +00:00
|
|
|
|
bool_label
|
2003-10-22 08:05:17 +00:00
|
|
|
|
: /* empty */
|
|
|
|
|
{
|
|
|
|
|
$$ = new_label_expr ();
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2001-10-24 18:57:29 +00:00
|
|
|
|
break_label
|
|
|
|
|
: /* empty */
|
|
|
|
|
{
|
|
|
|
|
$$ = break_label;
|
|
|
|
|
break_label = new_label_expr ();
|
|
|
|
|
}
|
2002-04-27 02:51:00 +00:00
|
|
|
|
;
|
2001-10-24 18:57:29 +00:00
|
|
|
|
|
|
|
|
|
continue_label
|
|
|
|
|
: /* empty */
|
|
|
|
|
{
|
|
|
|
|
$$ = continue_label;
|
|
|
|
|
continue_label = new_label_expr ();
|
2001-10-25 06:41:52 +00:00
|
|
|
|
}
|
2002-04-27 02:51:00 +00:00
|
|
|
|
;
|
2001-10-25 06:41:52 +00:00
|
|
|
|
|
|
|
|
|
switch_block
|
|
|
|
|
: /* empty */
|
|
|
|
|
{
|
|
|
|
|
$$ = switch_block;
|
|
|
|
|
switch_block = new_switch_block ();
|
2011-03-05 15:29:29 +00:00
|
|
|
|
switch_block->test = $<expr>0;
|
2001-10-24 18:57:29 +00:00
|
|
|
|
}
|
2002-04-27 02:51:00 +00:00
|
|
|
|
;
|
2001-10-24 18:57:29 +00:00
|
|
|
|
|
2023-02-08 02:18:42 +00:00
|
|
|
|
opt_init_semi
|
2023-09-25 07:03:29 +00:00
|
|
|
|
: comma_expr seq_semi
|
2023-09-27 03:41:31 +00:00
|
|
|
|
| decl /* contains ; */ { $$ = (expr_t *) $1; }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| ';'
|
2019-06-08 12:52:17 +00:00
|
|
|
|
{
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2001-08-01 06:29:09 +00:00
|
|
|
|
opt_expr
|
2020-03-11 07:07:58 +00:00
|
|
|
|
: comma_expr
|
2001-08-01 06:29:09 +00:00
|
|
|
|
| /* empty */
|
|
|
|
|
{
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
2002-04-27 02:51:00 +00:00
|
|
|
|
;
|
2001-08-01 06:29:09 +00:00
|
|
|
|
|
2002-10-31 22:58:59 +00:00
|
|
|
|
unary_expr
|
2012-11-04 01:27:41 +00:00
|
|
|
|
: NAME { $$ = new_symbol_expr ($1); }
|
|
|
|
|
| ARGS { $$ = new_name_expr (".args"); }
|
|
|
|
|
| SELF { $$ = new_self_expr (); }
|
|
|
|
|
| THIS { $$ = new_this_expr (); }
|
|
|
|
|
| const { $$ = $1; }
|
2023-09-27 03:41:31 +00:00
|
|
|
|
| '(' expr ')' { $$ = $2; ((expr_t *) $$)->paren = 1; }
|
2012-11-04 01:27:41 +00:00
|
|
|
|
| unary_expr '(' opt_arg_list ')' { $$ = function_expr ($1, $3); }
|
|
|
|
|
| unary_expr '[' expr ']' { $$ = array_expr ($1, $3); }
|
2020-02-27 08:43:39 +00:00
|
|
|
|
| unary_expr '.' ident_expr { $$ = field_expr ($1, $3); }
|
2013-09-27 08:43:33 +00:00
|
|
|
|
| unary_expr '.' unary_expr { $$ = field_expr ($1, $3); }
|
2012-11-04 01:27:41 +00:00
|
|
|
|
| INCOP unary_expr { $$ = incop_expr ($1, $2, 0); }
|
|
|
|
|
| unary_expr INCOP { $$ = incop_expr ($2, $1, 1); }
|
2023-10-24 10:50:31 +00:00
|
|
|
|
| unary_expr REVERSE { $$ = unary_expr (QC_REVERSE, $1); }
|
|
|
|
|
| DUAL cast_expr %prec UNARY { $$ = unary_expr (QC_DUAL, $2); }
|
2024-04-18 00:46:10 +00:00
|
|
|
|
| UNDUAL cast_expr %prec UNARY { $$ = unary_expr (QC_UNDUAL, $2); }
|
2002-10-31 22:58:59 +00:00
|
|
|
|
| '+' cast_expr %prec UNARY { $$ = $2; }
|
|
|
|
|
| '-' cast_expr %prec UNARY { $$ = unary_expr ('-', $2); }
|
|
|
|
|
| '!' cast_expr %prec UNARY { $$ = unary_expr ('!', $2); }
|
|
|
|
|
| '~' cast_expr %prec UNARY { $$ = unary_expr ('~', $2); }
|
2022-01-25 14:39:17 +00:00
|
|
|
|
| '&' cast_expr %prec UNARY { $$ = address_expr ($2, 0); }
|
2022-01-25 03:28:53 +00:00
|
|
|
|
| '*' cast_expr %prec UNARY { $$ = deref_pointer_expr ($2); }
|
2004-11-02 07:02:00 +00:00
|
|
|
|
| SIZEOF unary_expr %prec UNARY { $$ = sizeof_expr ($2, 0); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| SIZEOF '(' typename ')' %prec HYPERUNARY
|
2011-02-01 12:23:03 +00:00
|
|
|
|
{
|
2024-07-04 14:44:07 +00:00
|
|
|
|
auto type = resolve_type_spec ($3);
|
|
|
|
|
$$ = sizeof_expr (0, type);
|
2011-02-01 12:23:03 +00:00
|
|
|
|
}
|
2024-04-26 06:20:13 +00:00
|
|
|
|
| type_op '(' type_param_list ')' { $$ = type_function ($1, $3); }
|
2013-06-24 06:37:08 +00:00
|
|
|
|
| vector_expr { $$ = new_vector_list ($1); }
|
2002-10-31 22:58:59 +00:00
|
|
|
|
| obj_expr { $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
2020-02-27 08:43:39 +00:00
|
|
|
|
ident_expr
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: OBJECT_NAME { $$ = new_symbol_expr ($1.sym); }
|
2020-02-27 08:43:39 +00:00
|
|
|
|
| CLASS_NAME { $$ = new_symbol_expr ($1); }
|
2023-02-04 09:26:54 +00:00
|
|
|
|
| TYPE_NAME { $$ = new_symbol_expr ($1.sym); }
|
2020-02-27 08:43:39 +00:00
|
|
|
|
;
|
|
|
|
|
|
2013-06-24 02:36:52 +00:00
|
|
|
|
vector_expr
|
2023-09-25 07:03:29 +00:00
|
|
|
|
: '[' expr ',' { no_flush_dag = true; } expr_list ']'
|
2013-06-24 02:36:52 +00:00
|
|
|
|
{
|
2023-09-27 08:37:38 +00:00
|
|
|
|
$$ = expr_prepend_expr ($5, $2);
|
2023-09-25 07:03:29 +00:00
|
|
|
|
no_flush_dag = false;
|
2013-06-24 02:36:52 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2002-10-31 22:58:59 +00:00
|
|
|
|
cast_expr
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: '(' typename ')' cast_expr
|
2011-02-03 01:53:59 +00:00
|
|
|
|
{
|
2024-07-04 14:44:07 +00:00
|
|
|
|
auto type = resolve_type_spec ($2);
|
|
|
|
|
$$ = cast_expr (type, $4);
|
2011-02-03 01:53:59 +00:00
|
|
|
|
}
|
2012-11-04 01:27:41 +00:00
|
|
|
|
| unary_expr %prec LOW
|
2002-10-31 22:58:59 +00:00
|
|
|
|
;
|
|
|
|
|
|
2001-06-12 19:44:26 +00:00
|
|
|
|
expr
|
2002-10-31 22:58:59 +00:00
|
|
|
|
: cast_expr
|
|
|
|
|
| expr '=' expr { $$ = assign_expr ($1, $3); }
|
2020-03-11 10:42:38 +00:00
|
|
|
|
| expr '=' compound_init { $$ = assign_expr ($1, $3); }
|
2001-08-20 06:22:28 +00:00
|
|
|
|
| expr ASX expr { $$ = asx_expr ($2, $1, $3); }
|
2023-09-25 07:03:29 +00:00
|
|
|
|
| expr '?' flush_dag expr ':' expr { $$ = conditional_expr ($1, $4, $6); }
|
2023-10-24 10:50:31 +00:00
|
|
|
|
| expr AND flush_dag bool_label expr{ $$ = bool_expr (QC_AND, $4, $1, $5); }
|
|
|
|
|
| expr OR flush_dag bool_label expr { $$ = bool_expr (QC_OR, $4, $1, $5); }
|
|
|
|
|
| expr EQ expr { $$ = binary_expr (QC_EQ, $1, $3); }
|
|
|
|
|
| expr NE expr { $$ = binary_expr (QC_NE, $1, $3); }
|
|
|
|
|
| expr LE expr { $$ = binary_expr (QC_LE, $1, $3); }
|
|
|
|
|
| expr GE expr { $$ = binary_expr (QC_GE, $1, $3); }
|
|
|
|
|
| expr LT expr { $$ = binary_expr (QC_LT, $1, $3); }
|
|
|
|
|
| expr GT expr { $$ = binary_expr (QC_GT, $1, $3); }
|
|
|
|
|
| expr SHL expr { $$ = binary_expr (QC_SHL, $1, $3); }
|
|
|
|
|
| expr SHR expr { $$ = binary_expr (QC_SHR, $1, $3); }
|
2001-08-11 21:15:24 +00:00
|
|
|
|
| expr '+' expr { $$ = binary_expr ('+', $1, $3); }
|
|
|
|
|
| expr '-' expr { $$ = binary_expr ('-', $1, $3); }
|
|
|
|
|
| expr '*' expr { $$ = binary_expr ('*', $1, $3); }
|
|
|
|
|
| expr '/' expr { $$ = binary_expr ('/', $1, $3); }
|
|
|
|
|
| expr '&' expr { $$ = binary_expr ('&', $1, $3); }
|
|
|
|
|
| expr '|' expr { $$ = binary_expr ('|', $1, $3); }
|
|
|
|
|
| expr '^' expr { $$ = binary_expr ('^', $1, $3); }
|
|
|
|
|
| expr '%' expr { $$ = binary_expr ('%', $1, $3); }
|
2023-10-24 10:50:31 +00:00
|
|
|
|
| expr MOD expr { $$ = binary_expr (QC_MOD, $1, $3); }
|
|
|
|
|
| expr GEOMETRIC expr { $$ = binary_expr (QC_GEOMETRIC, $1, $3); }
|
|
|
|
|
| expr HADAMARD expr { $$ = binary_expr (QC_HADAMARD, $1, $3); }
|
|
|
|
|
| expr CROSS expr { $$ = binary_expr (QC_CROSS, $1, $3); }
|
|
|
|
|
| expr DOT expr { $$ = binary_expr (QC_DOT, $1, $3); }
|
|
|
|
|
| expr WEDGE expr { $$ = binary_expr (QC_WEDGE, $1, $3); }
|
|
|
|
|
| expr REGRESSIVE expr { $$ = binary_expr (QC_REGRESSIVE, $1, $3); }
|
2002-10-31 22:58:59 +00:00
|
|
|
|
;
|
|
|
|
|
|
2007-05-13 08:39:07 +00:00
|
|
|
|
texpr
|
2019-06-09 15:36:13 +00:00
|
|
|
|
: expr { $$ = convert_bool ($1, 1); }
|
2007-05-13 08:39:07 +00:00
|
|
|
|
;
|
|
|
|
|
|
2020-03-11 07:07:58 +00:00
|
|
|
|
comma_expr
|
2020-03-11 10:42:38 +00:00
|
|
|
|
: expr_list
|
2019-06-09 07:56:20 +00:00
|
|
|
|
{
|
2023-09-24 06:04:25 +00:00
|
|
|
|
if ($1->list.head->next) {
|
|
|
|
|
$$ = build_block_expr ($1, true);
|
|
|
|
|
} else {
|
2023-09-27 03:41:31 +00:00
|
|
|
|
$$ = (expr_t *) $1->list.head->expr;
|
2019-06-09 07:56:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2020-03-11 10:42:38 +00:00
|
|
|
|
expr_list
|
2023-09-25 07:03:29 +00:00
|
|
|
|
: expr { $$ = new_list_expr ($1); }
|
2023-09-27 08:37:38 +00:00
|
|
|
|
| expr_list ',' flush_dag expr { $$ = expr_append_expr ($1, $4); }
|
2020-03-11 10:42:38 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-10-31 22:58:59 +00:00
|
|
|
|
opt_arg_list
|
|
|
|
|
: /* emtpy */ { $$ = 0; }
|
|
|
|
|
| arg_list { $$ = $1; }
|
2001-06-12 19:44:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
arg_list
|
2023-09-24 11:44:50 +00:00
|
|
|
|
: arg_expr { $$ = new_list_expr ($1); }
|
2023-09-27 08:37:38 +00:00
|
|
|
|
| arg_list ',' arg_expr { $$ = expr_prepend_expr ($1, $3); }
|
2001-06-12 19:44:26 +00:00
|
|
|
|
;
|
|
|
|
|
|
2020-03-11 10:42:38 +00:00
|
|
|
|
arg_expr
|
|
|
|
|
: expr
|
|
|
|
|
| compound_init
|
|
|
|
|
;
|
|
|
|
|
|
2001-06-13 07:16:39 +00:00
|
|
|
|
const
|
2012-12-18 04:59:45 +00:00
|
|
|
|
: VALUE
|
2024-11-15 03:36:08 +00:00
|
|
|
|
| TRUE
|
|
|
|
|
{
|
|
|
|
|
pr_type_t data = { .value = 1 };
|
|
|
|
|
auto val = new_type_value (&type_bool, &data);
|
|
|
|
|
$$ = new_value_expr (val, false);
|
|
|
|
|
}
|
|
|
|
|
| FALSE
|
|
|
|
|
{
|
|
|
|
|
pr_type_t data = { .value = 0 };
|
|
|
|
|
auto val = new_type_value (&type_bool, &data);
|
|
|
|
|
$$ = new_value_expr (val, false);
|
|
|
|
|
}
|
2002-09-11 16:21:26 +00:00
|
|
|
|
| NIL { $$ = new_nil_expr (); }
|
2011-01-17 13:33:33 +00:00
|
|
|
|
| string
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
string
|
|
|
|
|
: STRING
|
|
|
|
|
| string STRING { $$ = binary_expr ('+', $1, $2); }
|
2002-04-26 21:42:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
2004-11-02 07:02:00 +00:00
|
|
|
|
identifier
|
|
|
|
|
: NAME
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| OBJECT_NAME { $$ = $1.sym; }
|
2004-11-02 07:02:00 +00:00
|
|
|
|
| CLASS_NAME
|
2023-02-04 09:26:54 +00:00
|
|
|
|
| TYPE_NAME { $$ = $1.sym; }
|
2024-09-06 17:42:32 +00:00
|
|
|
|
| NOT { $$ = new_symbol ("not"); }
|
2004-11-02 07:02:00 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
// Objective-QC stuff
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
obj_def
|
2002-11-15 17:12:16 +00:00
|
|
|
|
: classdef { }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
| classdecl
|
2020-03-01 10:37:40 +00:00
|
|
|
|
| protocoldecl
|
2002-05-07 16:55:54 +00:00
|
|
|
|
| protocoldef
|
2002-05-15 19:10:23 +00:00
|
|
|
|
| { if (!current_class) PARSE_ERROR; } methoddef
|
2002-05-07 16:55:54 +00:00
|
|
|
|
| END
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
|
|
|
|
if (!current_class)
|
|
|
|
|
PARSE_ERROR;
|
2002-05-15 23:24:19 +00:00
|
|
|
|
else
|
|
|
|
|
class_finish (current_class);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
identifier_list
|
2004-11-02 07:02:00 +00:00
|
|
|
|
: identifier
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2023-09-27 03:41:31 +00:00
|
|
|
|
$$ = append_expr (new_block_expr (0), new_symbol_expr ($1));
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
2004-11-02 07:02:00 +00:00
|
|
|
|
| identifier_list ',' identifier
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = append_expr ($1, new_symbol_expr ($3));
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
classdecl
|
2002-08-20 21:13:18 +00:00
|
|
|
|
: CLASS identifier_list ';'
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2024-10-03 04:48:54 +00:00
|
|
|
|
for (auto li = $2->block.list.head; li; li = li->next) {
|
2023-09-24 02:54:06 +00:00
|
|
|
|
auto e = li->expr;
|
2023-09-23 09:01:49 +00:00
|
|
|
|
get_class (e->symbol, 1);
|
|
|
|
|
if (!e->symbol->table)
|
|
|
|
|
symtab_addsymbol (current_symtab, e->symbol);
|
2011-02-03 06:21:09 +00:00
|
|
|
|
}
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-08-18 04:08:02 +00:00
|
|
|
|
class_name
|
2007-04-28 08:49:07 +00:00
|
|
|
|
: identifier %prec CLASS_NOT_CATEGORY
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2020-03-05 12:10:15 +00:00
|
|
|
|
if (!$1->type) {
|
|
|
|
|
$$ = get_class ($1, 1);
|
|
|
|
|
if (!$1->table) {
|
|
|
|
|
symtab_addsymbol (current_symtab, $1);
|
|
|
|
|
}
|
2020-03-27 06:16:41 +00:00
|
|
|
|
} else if (!is_class ($1->type)) {
|
2020-03-05 12:10:15 +00:00
|
|
|
|
error (0, "`%s' is not a class", $1->name);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
$$ = get_class (0, 1);
|
2011-01-17 13:33:33 +00:00
|
|
|
|
} else {
|
2024-08-16 08:23:29 +00:00
|
|
|
|
$$ = $1->type->class;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
2002-05-10 00:00:23 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
new_class_name
|
2004-11-02 07:02:00 +00:00
|
|
|
|
: identifier
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2011-03-24 02:39:34 +00:00
|
|
|
|
if (current_class) {
|
|
|
|
|
warning (0, "‘@end’ missing in implementation context");
|
|
|
|
|
class_finish (current_class);
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = get_class ($1, 0);
|
|
|
|
|
if (!$$) {
|
|
|
|
|
$1 = check_redefined ($1);
|
2011-02-03 06:21:09 +00:00
|
|
|
|
$$ = get_class ($1, 1);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
2020-03-05 06:39:34 +00:00
|
|
|
|
$$->interface_declared = 1;
|
2010-12-31 06:56:31 +00:00
|
|
|
|
current_class = &$$->class_type;
|
2011-02-03 06:21:09 +00:00
|
|
|
|
if (!$1->table)
|
|
|
|
|
symtab_addsymbol (current_symtab, $1);
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
2002-05-30 21:18:58 +00:00
|
|
|
|
;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
|
2002-05-15 19:10:23 +00:00
|
|
|
|
class_with_super
|
|
|
|
|
: class_name ':' class_name
|
|
|
|
|
{
|
|
|
|
|
if ($1->super_class != $3)
|
2002-11-12 19:52:43 +00:00
|
|
|
|
error (0, "%s is not a super class of %s", $3->name, $1->name);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
new_class_with_super
|
|
|
|
|
: new_class_name ':' class_name
|
|
|
|
|
{
|
2020-03-05 06:39:34 +00:00
|
|
|
|
if (!$3->interface_declared) {
|
|
|
|
|
$3->interface_declared = 1;
|
2020-03-04 23:50:29 +00:00
|
|
|
|
error (0, "cannot find interface declaration for `%s', "
|
|
|
|
|
"superclass of `%s'", $3->name, $1->name);
|
|
|
|
|
}
|
2020-03-05 06:39:34 +00:00
|
|
|
|
$1->interface_declared = 1;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
$1->super_class = $3;
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
category_name
|
2004-11-02 07:02:00 +00:00
|
|
|
|
: identifier '(' identifier ')'
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = get_category ($1, $3->name, 0);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
if (!$$) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
error (0, "undefined category `%s (%s)'", $1->name, $3->name);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
$$ = get_category (0, 0, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
new_category_name
|
2004-11-02 07:02:00 +00:00
|
|
|
|
: identifier '(' identifier ')'
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2011-03-24 02:39:34 +00:00
|
|
|
|
if (current_class) {
|
|
|
|
|
warning (0, "‘@end’ missing in implementation context");
|
|
|
|
|
class_finish (current_class);
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = get_category ($1, $3->name, 1);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
if ($$->defined) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
error (0, "redefinition of category `%s (%s)'",
|
|
|
|
|
$1->name, $3->name);
|
2002-05-15 19:10:23 +00:00
|
|
|
|
$$ = get_category (0, 0, 1);
|
|
|
|
|
}
|
2010-12-31 06:56:31 +00:00
|
|
|
|
current_class = &$$->class_type;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2010-12-12 11:27:56 +00:00
|
|
|
|
class_reference
|
|
|
|
|
: identifier
|
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
emit_class_ref ($1->name);
|
2010-12-12 11:27:56 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
category_reference
|
|
|
|
|
: identifier '(' identifier ')'
|
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
emit_category_ref ($1->name, $3->name);
|
2010-12-12 11:27:56 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
protocol_name
|
2004-11-02 07:02:00 +00:00
|
|
|
|
: identifier
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = get_protocol ($1->name, 0);
|
2020-03-01 10:37:40 +00:00
|
|
|
|
if ($$ && $$->methods) {
|
|
|
|
|
error (0, "redefinition of protocol %s", $1->name);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
$$ = get_protocol (0, 1);
|
2020-03-01 10:37:40 +00:00
|
|
|
|
}
|
|
|
|
|
if (!$$) {
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = get_protocol ($1->name, 1);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
2020-03-01 10:37:40 +00:00
|
|
|
|
$$->methods = new_methodlist ();
|
2010-12-31 06:56:31 +00:00
|
|
|
|
current_class = &$$->class_type;
|
2002-05-08 21:24:24 +00:00
|
|
|
|
}
|
2002-05-30 21:18:58 +00:00
|
|
|
|
;
|
2002-05-10 00:00:23 +00:00
|
|
|
|
|
2002-05-15 19:10:23 +00:00
|
|
|
|
classdef
|
2002-05-22 17:13:52 +00:00
|
|
|
|
: INTERFACE new_class_name
|
2006-12-01 08:17:55 +00:00
|
|
|
|
protocolrefs { class_add_protocols ($2, $3); }
|
2009-12-21 05:53:00 +00:00
|
|
|
|
'{' { $<class>$ = $2; }
|
|
|
|
|
ivar_decl_list '}'
|
|
|
|
|
{
|
|
|
|
|
class_add_ivars ($2, $7);
|
|
|
|
|
$<class>$ = $2;
|
|
|
|
|
}
|
2002-11-14 18:17:43 +00:00
|
|
|
|
methodprotolist { class_add_methods ($2, $10); }
|
2006-12-01 08:17:55 +00:00
|
|
|
|
END
|
|
|
|
|
{
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2002-05-22 17:13:52 +00:00
|
|
|
|
| INTERFACE new_class_name
|
2011-02-03 06:21:09 +00:00
|
|
|
|
protocolrefs { class_add_protocols ($2, $3); }
|
2009-12-21 05:53:00 +00:00
|
|
|
|
{
|
|
|
|
|
class_add_ivars ($2, class_new_ivars ($2));
|
|
|
|
|
$<class>$ = $2;
|
|
|
|
|
}
|
2003-07-30 04:11:45 +00:00
|
|
|
|
methodprotolist { class_add_methods ($2, $6); }
|
2006-12-01 08:17:55 +00:00
|
|
|
|
END
|
|
|
|
|
{
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2002-05-22 17:13:52 +00:00
|
|
|
|
| INTERFACE new_class_with_super
|
2004-11-11 00:34:00 +00:00
|
|
|
|
protocolrefs { class_add_protocols ($2, $3);}
|
2009-12-21 05:53:00 +00:00
|
|
|
|
'{' { $<class>$ = $2; }
|
|
|
|
|
ivar_decl_list '}'
|
|
|
|
|
{
|
|
|
|
|
class_add_ivars ($2, $7);
|
|
|
|
|
$<class>$ = $2;
|
|
|
|
|
}
|
2002-11-14 18:17:43 +00:00
|
|
|
|
methodprotolist { class_add_methods ($2, $10); }
|
2006-12-01 08:17:55 +00:00
|
|
|
|
END
|
|
|
|
|
{
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2002-05-22 17:13:52 +00:00
|
|
|
|
| INTERFACE new_class_with_super
|
2004-11-11 00:34:00 +00:00
|
|
|
|
protocolrefs { class_add_protocols ($2, $3); }
|
2009-12-21 05:53:00 +00:00
|
|
|
|
{
|
|
|
|
|
class_add_ivars ($2, class_new_ivars ($2));
|
|
|
|
|
$<class>$ = $2;
|
|
|
|
|
}
|
2003-07-30 04:11:45 +00:00
|
|
|
|
methodprotolist { class_add_methods ($2, $6); }
|
2006-12-01 08:17:55 +00:00
|
|
|
|
END
|
|
|
|
|
{
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2002-05-22 17:13:52 +00:00
|
|
|
|
| INTERFACE new_category_name
|
2009-12-21 05:53:00 +00:00
|
|
|
|
protocolrefs
|
|
|
|
|
{
|
|
|
|
|
category_add_protocols ($2, $3);
|
|
|
|
|
$<class>$ = $2->class;
|
|
|
|
|
}
|
2002-11-14 18:17:43 +00:00
|
|
|
|
methodprotolist { category_add_methods ($2, $5); }
|
2006-12-01 08:17:55 +00:00
|
|
|
|
END
|
|
|
|
|
{
|
|
|
|
|
current_class = 0;
|
|
|
|
|
}
|
2002-11-14 18:17:43 +00:00
|
|
|
|
| IMPLEMENTATION class_name { class_begin (&$2->class_type); }
|
2009-12-21 05:53:00 +00:00
|
|
|
|
'{' { $<class>$ = $2; }
|
2006-12-01 08:17:55 +00:00
|
|
|
|
ivar_decl_list '}'
|
|
|
|
|
{
|
|
|
|
|
class_check_ivars ($2, $6);
|
|
|
|
|
}
|
2002-11-14 18:17:43 +00:00
|
|
|
|
| IMPLEMENTATION class_name { class_begin (&$2->class_type); }
|
|
|
|
|
| IMPLEMENTATION class_with_super { class_begin (&$2->class_type); }
|
2009-12-21 05:53:00 +00:00
|
|
|
|
'{' { $<class>$ = $2; }
|
2006-12-01 08:17:55 +00:00
|
|
|
|
ivar_decl_list '}'
|
|
|
|
|
{
|
|
|
|
|
class_check_ivars ($2, $6);
|
|
|
|
|
}
|
2002-11-14 18:17:43 +00:00
|
|
|
|
| IMPLEMENTATION class_with_super { class_begin (&$2->class_type); }
|
|
|
|
|
| IMPLEMENTATION category_name { class_begin (&$2->class_type); }
|
2010-12-12 11:27:56 +00:00
|
|
|
|
| REFERENCE class_reference ';' { }
|
|
|
|
|
| REFERENCE category_reference ';' { }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2020-03-01 10:37:40 +00:00
|
|
|
|
protocoldecl
|
|
|
|
|
: protocol
|
|
|
|
|
protocol_name_list ';'
|
|
|
|
|
{
|
|
|
|
|
while ($2) {
|
|
|
|
|
get_protocol ($2->name, 1);
|
|
|
|
|
$2 = $2->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
protocoldef
|
2020-03-01 10:37:40 +00:00
|
|
|
|
: protocol
|
2011-03-24 02:55:17 +00:00
|
|
|
|
protocol_name
|
2020-03-01 10:37:40 +00:00
|
|
|
|
protocolrefs { protocol_add_protocols ($2, $3); $<class>$ = 0; }
|
|
|
|
|
methodprotolist { protocol_add_methods ($2, $5); }
|
2011-03-24 02:55:17 +00:00
|
|
|
|
END
|
|
|
|
|
{
|
2020-03-01 10:37:40 +00:00
|
|
|
|
current_class = $<class_type>1;
|
2011-03-24 02:55:17 +00:00
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2020-03-01 10:37:40 +00:00
|
|
|
|
protocol
|
|
|
|
|
: PROTOCOL { $<class_type>$ = current_class; }
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
protocolrefs
|
|
|
|
|
: /* emtpy */ { $$ = 0; }
|
2009-12-21 05:53:00 +00:00
|
|
|
|
| LT { $<protocol_list>$ = new_protocol_list (); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
protocol_list GT { $$ = $3; }
|
2003-07-25 20:34:24 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
protocol_list
|
2004-11-02 07:02:00 +00:00
|
|
|
|
: identifier
|
2003-07-25 20:34:24 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = add_protocol ($<protocol_list>0, $1->name);
|
2003-07-25 20:34:24 +00:00
|
|
|
|
}
|
2004-11-02 07:02:00 +00:00
|
|
|
|
| protocol_list ',' identifier
|
2003-07-25 20:34:24 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = add_protocol ($1, $3->name);
|
2003-07-25 20:34:24 +00:00
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
ivar_decl_list
|
2011-02-03 09:02:49 +00:00
|
|
|
|
: /* empty */
|
2002-05-17 06:20:27 +00:00
|
|
|
|
{
|
2011-02-03 09:02:49 +00:00
|
|
|
|
symtab_t *tab, *ivars;
|
|
|
|
|
ivars = class_new_ivars ($<class>0);
|
|
|
|
|
for (tab = ivars; tab->parent; tab = tab->parent)
|
|
|
|
|
;
|
2011-02-14 12:25:55 +00:00
|
|
|
|
if (tab == current_symtab)
|
|
|
|
|
internal_error (0, "ivars already linked to parent scope");
|
2011-02-03 09:02:49 +00:00
|
|
|
|
$<symtab>$ = tab;
|
|
|
|
|
tab->parent = current_symtab;
|
|
|
|
|
current_symtab = ivars;
|
|
|
|
|
|
2002-05-17 17:58:57 +00:00
|
|
|
|
current_visibility = vis_protected;
|
2002-05-17 06:20:27 +00:00
|
|
|
|
}
|
|
|
|
|
ivar_decl_list_2
|
2002-05-15 19:10:23 +00:00
|
|
|
|
{
|
2011-02-14 12:45:18 +00:00
|
|
|
|
symtab_t *tab = $<symtab>1;
|
2011-01-17 13:33:33 +00:00
|
|
|
|
$$ = current_symtab;
|
2011-02-14 12:45:18 +00:00
|
|
|
|
current_symtab = tab->parent;
|
|
|
|
|
tab->parent = 0;
|
2011-01-17 13:33:33 +00:00
|
|
|
|
|
2011-02-14 12:45:18 +00:00
|
|
|
|
tab = $$->parent; // preserve the ivars inheritance chain
|
2022-07-31 07:56:18 +00:00
|
|
|
|
int base = 0;
|
|
|
|
|
if ($<class>0->super_class) {
|
|
|
|
|
base = type_size ($<class>0->super_class->type);
|
|
|
|
|
}
|
|
|
|
|
build_struct ('s', 0, $$, 0, base);
|
2011-02-14 12:45:18 +00:00
|
|
|
|
$$->parent = tab;
|
2020-03-03 01:42:05 +00:00
|
|
|
|
current_visibility = vis_public;
|
2002-05-15 19:10:23 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
ivar_decl_list_2
|
|
|
|
|
: ivar_decl_list_2 visibility_spec ivar_decls
|
2002-05-07 16:55:54 +00:00
|
|
|
|
| ivar_decls
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
visibility_spec
|
|
|
|
|
: PRIVATE { current_visibility = vis_private; }
|
|
|
|
|
| PROTECTED { current_visibility = vis_protected; }
|
|
|
|
|
| PUBLIC { current_visibility = vis_public; }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
ivar_decls
|
2002-05-07 16:55:54 +00:00
|
|
|
|
: /* empty */
|
|
|
|
|
| ivar_decls ivar_decl ';'
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
ivar_decl
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: declspecs_nosc_ts ivars
|
|
|
|
|
| declspecs_nosc_ts
|
2020-03-04 16:46:56 +00:00
|
|
|
|
{
|
|
|
|
|
if (is_anonymous_struct ($1)) {
|
|
|
|
|
// type->name always begins with "tag "
|
2021-01-31 07:01:20 +00:00
|
|
|
|
$1.sym = new_symbol (va (0, ".anonymous.%s",
|
|
|
|
|
$1.type->name + 4));
|
2020-03-04 16:46:56 +00:00
|
|
|
|
$1.sym->type = $1.type;
|
2024-09-20 02:27:15 +00:00
|
|
|
|
$1.sym->sy_type = sy_offset;
|
2020-03-04 16:46:56 +00:00
|
|
|
|
$1.sym->visibility = vis_anonymous;
|
|
|
|
|
symtab_addsymbol (current_symtab, $1.sym);
|
|
|
|
|
if (!$1.sym->table) {
|
|
|
|
|
error (0, "duplicate field `%s'", $1.sym->name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| declspecs_nosc_nots notype_ivars
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-10 00:00:23 +00:00
|
|
|
|
ivars
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: ivar_declarator { }
|
|
|
|
|
| ivars ',' { $<spec>$ = $<spec>0; } ivar_declarator
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_ivars
|
|
|
|
|
: notype_ivar_declarator { }
|
|
|
|
|
| notype_ivars ',' { $<spec>$ = $<spec>0; }
|
|
|
|
|
notype_ivar_declarator
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
ivar_declarator
|
|
|
|
|
: declarator
|
|
|
|
|
{
|
2023-03-08 17:22:23 +00:00
|
|
|
|
declare_field ($1, current_symtab);
|
2023-02-08 02:18:42 +00:00
|
|
|
|
}
|
|
|
|
|
| declarator ':' expr
|
|
|
|
|
| ':' expr
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_ivar_declarator
|
|
|
|
|
: notype_declarator { internal_error (0, "not implemented"); }
|
|
|
|
|
| notype_declarator ':' expr
|
|
|
|
|
| ':' expr
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
methoddef
|
2023-09-24 06:04:25 +00:00
|
|
|
|
: ci methoddecl method_optional_state_expr
|
2011-02-04 12:19:52 +00:00
|
|
|
|
{
|
|
|
|
|
method_t *method = $2;
|
|
|
|
|
|
|
|
|
|
method->instance = $1;
|
|
|
|
|
$2 = method = class_find_method (current_class, method);
|
|
|
|
|
$<symbol>$ = method_symbol (current_class, method);
|
|
|
|
|
}
|
2011-03-07 11:51:51 +00:00
|
|
|
|
save_storage
|
2011-02-04 12:19:52 +00:00
|
|
|
|
{
|
|
|
|
|
method_t *method = $2;
|
|
|
|
|
const char *nicename = method_name (method);
|
|
|
|
|
symbol_t *sym = $<symbol>4;
|
2011-02-06 23:32:52 +00:00
|
|
|
|
symtab_t *ivar_scope;
|
|
|
|
|
|
2024-05-05 07:45:05 +00:00
|
|
|
|
$<funcstate>$ = (funcstate_t) {
|
|
|
|
|
.symtab = current_symtab,
|
|
|
|
|
.function = current_func,
|
|
|
|
|
};
|
2011-02-06 23:32:52 +00:00
|
|
|
|
|
|
|
|
|
ivar_scope = class_ivar_scope (current_class, current_symtab);
|
2021-09-24 10:49:55 +00:00
|
|
|
|
current_func = begin_function (sym, nicename, ivar_scope, 1,
|
|
|
|
|
sc_static);
|
2011-02-06 23:32:52 +00:00
|
|
|
|
class_finish_ivar_scope (current_class, ivar_scope,
|
2022-01-21 01:20:02 +00:00
|
|
|
|
current_func->locals);
|
2024-08-26 06:50:27 +00:00
|
|
|
|
method->func = sym->metafunc->func;
|
|
|
|
|
method->def = method->func->def;
|
2022-01-21 01:20:02 +00:00
|
|
|
|
current_symtab = current_func->locals;
|
2012-12-02 01:11:30 +00:00
|
|
|
|
current_storage = sc_local;
|
2011-02-04 12:19:52 +00:00
|
|
|
|
}
|
2024-10-07 00:55:21 +00:00
|
|
|
|
compound_statement_ns
|
2011-02-04 12:19:52 +00:00
|
|
|
|
{
|
2011-03-07 11:51:51 +00:00
|
|
|
|
build_code_function ($<symbol>4, $3, $7);
|
2024-05-05 07:45:05 +00:00
|
|
|
|
current_symtab = $<funcstate>6.symtab;
|
|
|
|
|
current_func = $<funcstate>6.function;
|
2024-08-10 11:04:58 +00:00
|
|
|
|
restore_storage ($5);
|
2011-02-04 12:19:52 +00:00
|
|
|
|
}
|
|
|
|
|
| ci methoddecl '=' '#' const ';'
|
2011-02-04 10:50:24 +00:00
|
|
|
|
{
|
|
|
|
|
symbol_t *sym;
|
|
|
|
|
method_t *method = $2;
|
2024-08-26 01:31:57 +00:00
|
|
|
|
const expr_t *bi_val = $5;
|
2011-02-04 10:50:24 +00:00
|
|
|
|
|
|
|
|
|
method->instance = $1;
|
|
|
|
|
method = class_find_method (current_class, method);
|
|
|
|
|
sym = method_symbol (current_class, method);
|
2024-08-26 01:31:57 +00:00
|
|
|
|
build_builtin_function (sym, bi_val, 1, sc_static);
|
2024-08-26 06:50:27 +00:00
|
|
|
|
method->func = sym->metafunc->func;
|
|
|
|
|
method->def = method->func->def;
|
2011-02-04 10:50:24 +00:00
|
|
|
|
}
|
2004-02-09 07:35:19 +00:00
|
|
|
|
;
|
2002-05-17 18:35:54 +00:00
|
|
|
|
|
2004-02-09 07:35:19 +00:00
|
|
|
|
ci
|
|
|
|
|
: '+' { $$ = 0; }
|
|
|
|
|
| '-' { $$ = 1; }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
methodprotolist
|
2002-05-10 00:00:23 +00:00
|
|
|
|
: /* emtpy */ { $$ = 0; }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
| methodprotolist2
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
methodprotolist2
|
2002-11-14 18:17:43 +00:00
|
|
|
|
: { } methodproto
|
2002-05-10 00:00:23 +00:00
|
|
|
|
{
|
|
|
|
|
$$ = new_methodlist ();
|
2002-11-14 18:17:43 +00:00
|
|
|
|
add_method ($$, $2);
|
2002-05-10 00:00:23 +00:00
|
|
|
|
}
|
|
|
|
|
| methodprotolist2 methodproto
|
|
|
|
|
{
|
|
|
|
|
add_method ($1, $2);
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
methodproto
|
2024-08-20 23:26:31 +00:00
|
|
|
|
: ci methoddecl ';'
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{
|
2024-08-20 23:26:31 +00:00
|
|
|
|
$2->instance = $1;
|
2002-05-08 21:24:24 +00:00
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
2024-08-20 23:26:31 +00:00
|
|
|
|
| ci error ';'
|
2023-03-08 17:22:23 +00:00
|
|
|
|
{ $$ = new_method (&type_id, make_selector ("", 0, 0), 0); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
methoddecl
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: '(' typename ')' unaryselector
|
2024-07-04 14:44:07 +00:00
|
|
|
|
{
|
|
|
|
|
auto type = resolve_type_spec ($2);
|
|
|
|
|
$$ = new_method (type, $4, 0);
|
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
| unaryselector
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{ $$ = new_method (&type_id, $1, 0); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| '(' typename ')' keywordselector optional_param_list
|
2024-07-04 14:44:07 +00:00
|
|
|
|
{
|
|
|
|
|
auto type = resolve_type_spec ($2);
|
|
|
|
|
$$ = new_method (type, $4, $5);
|
|
|
|
|
}
|
2011-02-01 12:23:03 +00:00
|
|
|
|
| keywordselector optional_param_list
|
2002-05-08 21:24:24 +00:00
|
|
|
|
{ $$ = new_method (&type_id, $1, $2); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2011-02-01 12:23:03 +00:00
|
|
|
|
optional_param_list
|
2002-05-10 00:00:23 +00:00
|
|
|
|
: /* empty */ { $$ = 0; }
|
|
|
|
|
| ',' param_list { $$ = $2; }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 21:24:24 +00:00
|
|
|
|
unaryselector
|
2023-03-08 17:22:23 +00:00
|
|
|
|
: selector { $$ = make_selector ($1->name, 0, 0); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
keywordselector
|
|
|
|
|
: keyworddecl
|
2002-05-08 05:55:57 +00:00
|
|
|
|
| keywordselector keyworddecl { $2->next = $1; $$ = $2; }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2020-03-01 10:37:40 +00:00
|
|
|
|
protocol_name_list
|
|
|
|
|
: identifier
|
|
|
|
|
| protocol_name_list ',' identifier { $3->next = $1; $$ = $3; }
|
|
|
|
|
|
2002-05-07 16:55:54 +00:00
|
|
|
|
selector
|
2011-01-17 13:33:33 +00:00
|
|
|
|
: NAME { $$ = $1; }
|
|
|
|
|
| CLASS_NAME { $$ = $1; }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| OBJECT_NAME { $$ = new_symbol (qc_yytext); }
|
2023-02-04 09:26:54 +00:00
|
|
|
|
| TYPE_SPEC { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| TYPE_NAME { $$ = $1.sym; }
|
2002-05-08 23:12:49 +00:00
|
|
|
|
| reserved_word
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
reserved_word
|
2012-10-26 07:01:41 +00:00
|
|
|
|
: LOCAL { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| RETURN { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| WHILE { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| DO { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| IF { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| ELSE { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| FOR { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| BREAK { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| CONTINUE { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| SWITCH { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| CASE { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| DEFAULT { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| NIL { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| STRUCT { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| ENUM { $$ = new_symbol (qc_yytext); }
|
|
|
|
|
| TYPEDEF { $$ = new_symbol (qc_yytext); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
keyworddecl
|
2023-02-08 02:18:42 +00:00
|
|
|
|
: selector ':' '(' typename ')' identifier
|
2024-07-04 14:44:07 +00:00
|
|
|
|
{
|
|
|
|
|
auto type = resolve_type_spec ($4);
|
|
|
|
|
$$ = make_selector ($1->name, type, $6->name);
|
|
|
|
|
}
|
2004-11-02 07:02:00 +00:00
|
|
|
|
| selector ':' identifier
|
2023-03-08 17:22:23 +00:00
|
|
|
|
{ $$ = make_selector ($1->name, &type_id, $3->name); }
|
2023-02-08 02:18:42 +00:00
|
|
|
|
| ':' '(' typename ')' identifier
|
2024-07-04 14:44:07 +00:00
|
|
|
|
{
|
|
|
|
|
auto type = resolve_type_spec ($3);
|
|
|
|
|
$$ = make_selector ("", type, $5->name);
|
|
|
|
|
}
|
2004-11-02 07:02:00 +00:00
|
|
|
|
| ':' identifier
|
2023-03-08 17:22:23 +00:00
|
|
|
|
{ $$ = make_selector ("", &type_id, $2->name); }
|
2002-05-08 05:55:57 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
obj_expr
|
|
|
|
|
: obj_messageexpr
|
|
|
|
|
| SELECTOR '(' selectorarg ')' { $$ = selector_expr ($3); }
|
2011-01-17 13:33:33 +00:00
|
|
|
|
| PROTOCOL '(' identifier ')' { $$ = protocol_expr ($3->name); }
|
2024-07-04 14:44:07 +00:00
|
|
|
|
| ENCODE '(' typename ')'
|
|
|
|
|
{
|
|
|
|
|
auto type = resolve_type_spec ($3);
|
|
|
|
|
$$ = encode_expr (type);
|
|
|
|
|
}
|
2002-05-08 23:12:49 +00:00
|
|
|
|
| obj_string /* FIXME string object? */
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
obj_messageexpr
|
|
|
|
|
: '[' receiver messageargs ']' { $$ = message_expr ($2, $3); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
receiver
|
2019-06-09 15:36:13 +00:00
|
|
|
|
: expr
|
2011-02-06 05:33:52 +00:00
|
|
|
|
| CLASS_NAME
|
|
|
|
|
{
|
2011-02-13 07:05:09 +00:00
|
|
|
|
$$ = new_symbol_expr ($1);
|
2011-02-06 05:33:52 +00:00
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
messageargs
|
2011-01-17 13:33:33 +00:00
|
|
|
|
: selector { $$ = new_keywordarg ($1->name, 0); }
|
2002-05-08 23:12:49 +00:00
|
|
|
|
| keywordarglist
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
keywordarglist
|
|
|
|
|
: keywordarg
|
|
|
|
|
| keywordarglist keywordarg
|
|
|
|
|
{
|
|
|
|
|
$2->next = $1;
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
keywordarg
|
2011-01-17 13:33:33 +00:00
|
|
|
|
: selector ':' arg_list { $$ = new_keywordarg ($1->name, $3); }
|
2002-09-11 16:21:26 +00:00
|
|
|
|
| ':' arg_list { $$ = new_keywordarg ("", $2); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
selectorarg
|
2011-01-17 13:33:33 +00:00
|
|
|
|
: selector { $$ = new_keywordarg ($1->name, 0); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
| keywordnamelist
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
keywordnamelist
|
2002-05-07 16:55:54 +00:00
|
|
|
|
: keywordname
|
|
|
|
|
| keywordnamelist keywordname
|
2002-05-08 23:12:49 +00:00
|
|
|
|
{
|
|
|
|
|
$2->next = $1;
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
keywordname
|
2011-01-17 13:33:33 +00:00
|
|
|
|
: selector ':' { $$ = new_keywordarg ($1->name, new_nil_expr ()); }
|
|
|
|
|
| ':' { $$ = new_keywordarg ("", new_nil_expr ()); }
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2002-05-08 23:12:49 +00:00
|
|
|
|
obj_string
|
2011-01-17 13:33:33 +00:00
|
|
|
|
: '@' STRING
|
2002-05-08 23:12:49 +00:00
|
|
|
|
{
|
2011-01-17 13:33:33 +00:00
|
|
|
|
//FIXME string object
|
|
|
|
|
$$ = $2;
|
2002-05-08 23:12:49 +00:00
|
|
|
|
}
|
2002-05-07 16:55:54 +00:00
|
|
|
|
;
|
|
|
|
|
|
2001-06-12 19:44:26 +00:00
|
|
|
|
%%
|
2024-04-18 15:49:47 +00:00
|
|
|
|
|
|
|
|
|
// preprocessor directives in ruamoko and quakec
|
|
|
|
|
static directive_t rua_directives[] = {
|
|
|
|
|
{"include", PRE_INCLUDE},
|
|
|
|
|
{"embed", PRE_EMBED},
|
|
|
|
|
{"define", PRE_DEFINE},
|
|
|
|
|
{"undef", PRE_UNDEF},
|
|
|
|
|
{"error", PRE_ERROR},
|
|
|
|
|
{"warning", PRE_WARNING},
|
|
|
|
|
{"notice", PRE_NOTICE},
|
|
|
|
|
{"pragma", PRE_PRAGMA},
|
|
|
|
|
{"line", PRE_LINE},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static directive_t *
|
|
|
|
|
qc_directive (const char *token)
|
|
|
|
|
{
|
|
|
|
|
static hashtab_t *directive_tab;
|
|
|
|
|
|
|
|
|
|
if (!directive_tab) {
|
|
|
|
|
directive_tab = Hash_NewTable (253, rua_directive_get_key, 0, 0, 0);
|
|
|
|
|
for (size_t i = 0; i < ARRCOUNT(rua_directives); i++) {
|
|
|
|
|
Hash_Add (directive_tab, &rua_directives[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
directive_t *directive = Hash_Find (directive_tab, token);
|
|
|
|
|
return directive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These keywords are part of the Ruamoko language and require the QuakeForge
|
|
|
|
|
// Ruamoko VM.
|
|
|
|
|
static keyword_t rua_keywords[] = {
|
|
|
|
|
#define VEC_TYPE(type_name, base_type) \
|
|
|
|
|
{ #type_name, QC_TYPE_SPEC, .spec = { .type = &type_##type_name } },
|
|
|
|
|
#include "tools/qfcc/include/vec_types.h"
|
2024-09-04 00:50:00 +00:00
|
|
|
|
|
|
|
|
|
{"bvec2", QC_TYPE_SPEC, .spec = {.type = &type_bvec2}},
|
|
|
|
|
{"bvec3", QC_TYPE_SPEC, .spec = {.type = &type_bvec3}},
|
|
|
|
|
{"bvec4", QC_TYPE_SPEC, .spec = {.type = &type_bvec4}},
|
|
|
|
|
|
|
|
|
|
#define MAT_TYPE(type_name, base_type, cols, align_as) \
|
|
|
|
|
{ #type_name, QC_TYPE_SPEC, .spec = { . type = &type_##type_name } },
|
|
|
|
|
#include "tools/qfcc/include/mat_types.h"
|
|
|
|
|
{ "mat2", QC_TYPE_SPEC, .spec = { . type = &type_mat2x2 } },
|
|
|
|
|
{ "mat3", QC_TYPE_SPEC, .spec = { . type = &type_mat3x3 } },
|
|
|
|
|
{ "mat4", QC_TYPE_SPEC, .spec = { . type = &type_mat4x4 } },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// These keywords are all part of the Ruamoko (Objective-QC) language.
|
|
|
|
|
// The first time any one of them is encountered, the class system will be
|
|
|
|
|
// initialized.
|
|
|
|
|
// If not compiling for the QuakeForge VM, or if Ruamoko has been disabled,
|
|
|
|
|
// then they will be unavailable as keywords.
|
|
|
|
|
static keyword_t obj_keywords[] = {
|
|
|
|
|
{"id", QC_OBJECT_NAME, .spec = { .type = &type_id } },
|
|
|
|
|
{"Class", QC_TYPE_SPEC, .spec = { .type = &type_Class } },
|
|
|
|
|
{"Method", QC_TYPE_SPEC, .spec = { .type = &type_method } },
|
|
|
|
|
{"Super", QC_TYPE_SPEC, .spec = { .type = &type_super } },
|
|
|
|
|
{"SEL", QC_TYPE_SPEC, .spec = { .type = &type_SEL } },
|
|
|
|
|
{"IMP", QC_TYPE_SPEC, .spec = { .type = &type_IMP } },
|
|
|
|
|
|
|
|
|
|
{"@class", QC_CLASS },
|
|
|
|
|
{"@defs", QC_DEFS },
|
|
|
|
|
{"@encode", QC_ENCODE },
|
|
|
|
|
{"@end", QC_END },
|
|
|
|
|
{"@implementation", QC_IMPLEMENTATION },
|
|
|
|
|
{"@interface", QC_INTERFACE },
|
|
|
|
|
{"@private", QC_PRIVATE },
|
|
|
|
|
{"@protected", QC_PROTECTED },
|
|
|
|
|
{"@protocol", QC_PROTOCOL },
|
|
|
|
|
{"@public", QC_PUBLIC },
|
|
|
|
|
{"@reference", QC_REFERENCE },
|
|
|
|
|
{"@selector", QC_SELECTOR },
|
|
|
|
|
{"@self", QC_SELF },
|
|
|
|
|
{"@this", QC_THIS },
|
|
|
|
|
|
|
|
|
|
// This is a hack to trigger the initialization of the class
|
|
|
|
|
// sytem if it is seen before any other Objective-QC symbol. Otherwise,
|
|
|
|
|
// it is just an identifier, though it does reference a built-in type
|
|
|
|
|
// created by the class system.
|
|
|
|
|
{"obj_module", 0 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// These keywords are extensions to QC and thus available only in advanced
|
|
|
|
|
// or extended code. However, if they are preceeded by an @ (eg, @for), then
|
|
|
|
|
// they are always available. This is to prevent them from causing trouble
|
|
|
|
|
// for traditional code that might use these words as identifiers, but still
|
|
|
|
|
// make the language features available to traditional code.
|
|
|
|
|
static keyword_t at_keywords[] = {
|
|
|
|
|
{"for", QC_FOR },
|
|
|
|
|
{"goto", QC_GOTO },
|
|
|
|
|
{"break", QC_BREAK },
|
|
|
|
|
{"continue", QC_CONTINUE},
|
|
|
|
|
{"switch", QC_SWITCH },
|
|
|
|
|
{"case", QC_CASE },
|
|
|
|
|
{"default", QC_DEFAULT },
|
|
|
|
|
{"nil", QC_NIL },
|
|
|
|
|
{"struct", QC_STRUCT },
|
|
|
|
|
{"union", QC_STRUCT },
|
|
|
|
|
{"enum", QC_ENUM },
|
|
|
|
|
{"typedef", QC_TYPEDEF },
|
|
|
|
|
{"extern", QC_EXTERN },
|
|
|
|
|
{"static", QC_STATIC },
|
|
|
|
|
{"sizeof", QC_SIZEOF },
|
|
|
|
|
{"not", QC_NOT },
|
|
|
|
|
{"auto", QC_TYPE_SPEC, .spec = { .type = &type_auto } },
|
2024-09-03 08:59:56 +00:00
|
|
|
|
{"const", QC_TYPE_QUAL, .spec = { .is_const = true } },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// These keywords require the QuakeForge VM to be of any use. ie, they cannot
|
|
|
|
|
// be supported (sanely) by v6 progs.
|
|
|
|
|
static keyword_t qf_keywords[] = {
|
|
|
|
|
{"quaternion", QC_TYPE_SPEC, .spec = { .type = &type_quaternion } },
|
|
|
|
|
{"double", QC_TYPE_SPEC, .spec = { .type = &type_double } },
|
|
|
|
|
{"int", QC_TYPE_SPEC, .spec = { .type = &type_int } },
|
2024-09-04 00:50:00 +00:00
|
|
|
|
{"bool", QC_TYPE_SPEC, .spec = { .type = &type_bool } },
|
2024-11-15 03:36:08 +00:00
|
|
|
|
{"lbool", QC_TYPE_SPEC, .spec = { .type = &type_lbool } },
|
2024-05-13 03:19:16 +00:00
|
|
|
|
{"unsigned", QC_TYPE_SPEC, .spec = { .is_unsigned = true } },
|
|
|
|
|
{"signed", QC_TYPE_SPEC, .spec = { .is_signed = true } },
|
|
|
|
|
{"long", QC_TYPE_SPEC, .spec = { .is_long = true } },
|
|
|
|
|
{"short", QC_TYPE_SPEC, .spec = { .is_short = true } },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
|
2024-11-15 03:36:08 +00:00
|
|
|
|
{"true", QC_TRUE },
|
|
|
|
|
{"false", QC_FALSE},
|
|
|
|
|
|
2024-04-18 15:49:47 +00:00
|
|
|
|
{"@args", QC_ARGS, },
|
|
|
|
|
{"@va_list", QC_TYPE_SPEC, .spec = { .type = &type_va_list } },
|
|
|
|
|
{"@param", QC_TYPE_SPEC, .spec = { .type = &type_param } },
|
|
|
|
|
{"@return", QC_AT_RETURN, },
|
2024-09-03 08:59:56 +00:00
|
|
|
|
{"@in", QC_TYPE_QUAL, .spec = { .storage = sc_in } },
|
|
|
|
|
{"@out", QC_TYPE_QUAL, .spec = { .storage = sc_out } },
|
|
|
|
|
{"@inout", QC_TYPE_QUAL, .spec = { .storage = sc_inout } },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
|
|
|
|
|
{"@hadamard", QC_HADAMARD, },
|
|
|
|
|
{"@cross", QC_CROSS, },
|
2024-04-24 06:45:26 +00:00
|
|
|
|
{"@dot", QC_DOT, },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
{"@wedge", QC_WEDGE, },
|
|
|
|
|
{"@regressive", QC_REGRESSIVE, },
|
|
|
|
|
{"@geometric", QC_GEOMETRIC, },
|
2024-04-24 06:45:26 +00:00
|
|
|
|
{"@algebra", QC_ALGEBRA, },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
{"@dual", QC_DUAL, },
|
|
|
|
|
{"@undual", QC_UNDUAL, },
|
2024-04-24 06:45:26 +00:00
|
|
|
|
|
2024-04-25 07:10:43 +00:00
|
|
|
|
{"@generic", QC_GENERIC, },
|
2024-05-31 07:39:50 +00:00
|
|
|
|
{"@function", QC_AT_FUNCTION, },
|
2024-04-24 06:45:26 +00:00
|
|
|
|
{"@field", QC_AT_FIELD, },
|
|
|
|
|
{"@pointer", QC_AT_POINTER, },
|
|
|
|
|
{"@array", QC_AT_ARRAY, },
|
|
|
|
|
{"@base", QC_AT_BASE, },
|
|
|
|
|
{"@width", QC_AT_WIDTH, },
|
|
|
|
|
{"@vector", QC_AT_VECTOR, },
|
|
|
|
|
{"@rows", QC_AT_ROWS, },
|
|
|
|
|
{"@cols", QC_AT_COLS, },
|
|
|
|
|
{"@matrix", QC_AT_MATRIX, },
|
|
|
|
|
{"@int", QC_AT_INT, },
|
|
|
|
|
{"@uint", QC_AT_UINT, },
|
|
|
|
|
{"@bool", QC_AT_BOOL, },
|
|
|
|
|
{"@float", QC_AT_FLOAT, },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// These keywors are always available. Other than the @ keywords, they
|
|
|
|
|
// form traditional QuakeC.
|
|
|
|
|
static keyword_t keywords[] = {
|
|
|
|
|
{"void", QC_TYPE_SPEC, .spec = { .type = &type_void } },
|
|
|
|
|
{"float", QC_TYPE_SPEC, .spec = { .type = &type_float } },
|
|
|
|
|
{"string", QC_TYPE_SPEC, .spec = { .type = &type_string } },
|
|
|
|
|
{"vector", QC_TYPE_SPEC, .spec = { .type = &type_vector } },
|
|
|
|
|
{"entity", QC_TYPE_SPEC, .spec = { .type = &type_entity } },
|
|
|
|
|
{"local", QC_LOCAL, },
|
|
|
|
|
{"return", QC_RETURN, },
|
|
|
|
|
{"while", QC_WHILE, },
|
|
|
|
|
{"do", QC_DO, },
|
|
|
|
|
{"if", QC_IF, },
|
|
|
|
|
{"else", QC_ELSE, },
|
|
|
|
|
{"@system", QC_SYSTEM, },
|
|
|
|
|
{"@overload", QC_OVERLOAD, },
|
|
|
|
|
{"@attribute", QC_ATTRIBUTE, },
|
|
|
|
|
{"@handle", QC_HANDLE, },
|
2024-11-24 16:39:27 +00:00
|
|
|
|
{"@intrinsic", QC_INTRINSIC, },
|
2024-04-18 15:49:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
qc_process_keyword (QC_YYSTYPE *lval, keyword_t *keyword, const char *token)
|
|
|
|
|
{
|
|
|
|
|
if (keyword->value == QC_STRUCT) {
|
|
|
|
|
lval->op = token[0];
|
|
|
|
|
} else if (keyword->value == QC_OBJECT_NAME) {
|
|
|
|
|
symbol_t *sym;
|
|
|
|
|
|
|
|
|
|
sym = symtab_lookup (current_symtab, token);
|
|
|
|
|
lval->symbol = sym;
|
|
|
|
|
// the global id symbol is always just a name so attempts to redefine
|
|
|
|
|
// it globally can be caught and treated as an error, but it needs to
|
|
|
|
|
// be redefinable when in an enclosing scope.
|
|
|
|
|
if (sym->sy_type == sy_name) {
|
|
|
|
|
// this is the global id (object)
|
|
|
|
|
lval->spec = (specifier_t) {
|
|
|
|
|
.type = sym->type,
|
|
|
|
|
.sym = sym,
|
|
|
|
|
};
|
|
|
|
|
return QC_OBJECT_NAME;
|
2024-04-26 06:20:13 +00:00
|
|
|
|
} else if (sym->sy_type == sy_type_param) {
|
|
|
|
|
// id has been redeclared via a generic type param
|
|
|
|
|
lval->spec = (specifier_t) {
|
2024-07-04 14:44:07 +00:00
|
|
|
|
.type_expr = new_symbol_expr (sym),
|
2024-04-26 06:20:13 +00:00
|
|
|
|
.sym = sym,
|
|
|
|
|
};
|
|
|
|
|
return QC_TYPE_NAME;
|
2024-04-18 15:49:47 +00:00
|
|
|
|
} else if (sym->sy_type == sy_type) {
|
|
|
|
|
// id has been redeclared via a typedef
|
|
|
|
|
lval->spec = (specifier_t) {
|
|
|
|
|
.type = sym->type,
|
|
|
|
|
.sym = sym,
|
|
|
|
|
};
|
|
|
|
|
return QC_TYPE_NAME;
|
|
|
|
|
}
|
2024-08-26 01:35:33 +00:00
|
|
|
|
// id has been redeclared as a variable (hopefully)
|
2024-04-18 15:49:47 +00:00
|
|
|
|
return QC_NAME;
|
|
|
|
|
} else {
|
|
|
|
|
lval->spec = keyword->spec;
|
|
|
|
|
}
|
|
|
|
|
return keyword->value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
qc_keyword_or_id (QC_YYSTYPE *lval, const char *token)
|
|
|
|
|
{
|
|
|
|
|
static hashtab_t *keyword_tab;
|
|
|
|
|
static hashtab_t *qf_keyword_tab;
|
|
|
|
|
static hashtab_t *at_keyword_tab;
|
|
|
|
|
static hashtab_t *obj_keyword_tab;
|
|
|
|
|
static hashtab_t *rua_keyword_tab;
|
|
|
|
|
|
|
|
|
|
keyword_t *keyword = 0;
|
|
|
|
|
|
|
|
|
|
if (!keyword_tab) {
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
keyword_tab = Hash_NewTable (253, rua_keyword_get_key, 0, 0, 0);
|
|
|
|
|
qf_keyword_tab = Hash_NewTable (253, rua_keyword_get_key, 0, 0, 0);
|
|
|
|
|
at_keyword_tab = Hash_NewTable (253, rua_keyword_get_key, 0, 0, 0);
|
|
|
|
|
obj_keyword_tab = Hash_NewTable (253, rua_keyword_get_key, 0, 0, 0);
|
|
|
|
|
rua_keyword_tab = Hash_NewTable (253, rua_keyword_get_key, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRCOUNT(keywords); i++)
|
|
|
|
|
Hash_Add (keyword_tab, &keywords[i]);
|
|
|
|
|
for (i = 0; i < ARRCOUNT(qf_keywords); i++)
|
|
|
|
|
Hash_Add (qf_keyword_tab, &qf_keywords[i]);
|
|
|
|
|
for (i = 0; i < ARRCOUNT(at_keywords); i++)
|
|
|
|
|
Hash_Add (at_keyword_tab, &at_keywords[i]);
|
|
|
|
|
for (i = 0; i < ARRCOUNT(obj_keywords); i++)
|
|
|
|
|
Hash_Add (obj_keyword_tab, &obj_keywords[i]);
|
|
|
|
|
for (i = 0; i < ARRCOUNT(rua_keywords); i++)
|
|
|
|
|
Hash_Add (rua_keyword_tab, &rua_keywords[i]);
|
|
|
|
|
}
|
|
|
|
|
if (options.traditional < 1) {
|
|
|
|
|
if (options.code.progsversion == PROG_VERSION) {
|
|
|
|
|
keyword = Hash_Find (rua_keyword_tab, token);
|
|
|
|
|
}
|
|
|
|
|
if (!keyword) {
|
|
|
|
|
keyword = Hash_Find (obj_keyword_tab, token);
|
|
|
|
|
if (keyword) {
|
|
|
|
|
if (!obj_initialized)
|
|
|
|
|
class_init ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!keyword)
|
|
|
|
|
keyword = Hash_Find (qf_keyword_tab, token);
|
|
|
|
|
}
|
|
|
|
|
if (!keyword && options.traditional < 2)
|
|
|
|
|
keyword = Hash_Find (at_keyword_tab, token);
|
|
|
|
|
if (!keyword && token[0] == '@') {
|
|
|
|
|
keyword = Hash_Find (at_keyword_tab, token + 1);
|
|
|
|
|
if (keyword)
|
|
|
|
|
token += 1;
|
|
|
|
|
}
|
|
|
|
|
if (!keyword)
|
|
|
|
|
keyword = Hash_Find (keyword_tab, token);
|
|
|
|
|
if (keyword && keyword->value)
|
|
|
|
|
return qc_process_keyword (lval, keyword, token);
|
|
|
|
|
if (token[0] == '@') {
|
|
|
|
|
return '@';
|
|
|
|
|
}
|
2024-08-10 11:04:58 +00:00
|
|
|
|
|
|
|
|
|
symbol_t *sym = nullptr;
|
|
|
|
|
if (generic_symtab) {
|
|
|
|
|
sym = symtab_lookup (generic_symtab, token);
|
|
|
|
|
}
|
|
|
|
|
if (!sym) {
|
|
|
|
|
sym = symtab_lookup (current_symtab, token);
|
|
|
|
|
}
|
|
|
|
|
if (!sym) {
|
2024-04-18 15:49:47 +00:00
|
|
|
|
sym = new_symbol (token);
|
2024-08-10 11:04:58 +00:00
|
|
|
|
}
|
2024-04-18 15:49:47 +00:00
|
|
|
|
lval->symbol = sym;
|
|
|
|
|
if (sym->sy_type == sy_type) {
|
|
|
|
|
lval->spec = (specifier_t) {
|
|
|
|
|
.type = sym->type,
|
|
|
|
|
.sym = sym,
|
|
|
|
|
};
|
|
|
|
|
return QC_TYPE_NAME;
|
2024-04-26 06:20:13 +00:00
|
|
|
|
} else if (sym->sy_type == sy_type_param) {
|
|
|
|
|
lval->spec = (specifier_t) {
|
2024-07-04 14:44:07 +00:00
|
|
|
|
.type_expr = new_symbol_expr (sym),
|
2024-04-26 06:20:13 +00:00
|
|
|
|
.sym = sym,
|
|
|
|
|
};
|
|
|
|
|
return QC_TYPE_NAME;
|
2024-04-18 15:49:47 +00:00
|
|
|
|
}
|
|
|
|
|
if (sym->sy_type == sy_class)
|
|
|
|
|
return QC_CLASS_NAME;
|
|
|
|
|
return QC_NAME;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-28 01:18:21 +00:00
|
|
|
|
static int
|
2024-04-18 15:49:47 +00:00
|
|
|
|
qc_yyparse (FILE *in)
|
|
|
|
|
{
|
|
|
|
|
rua_parser_t parser = {
|
|
|
|
|
.parse = qc_yypush_parse,
|
|
|
|
|
.state = qc_yypstate_new (),
|
|
|
|
|
.directive = qc_directive,
|
|
|
|
|
.keyword_or_id = qc_keyword_or_id,
|
|
|
|
|
};
|
|
|
|
|
int ret = rua_parse (in, &parser);
|
|
|
|
|
qc_yypstate_delete (parser.state);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2024-08-28 01:18:21 +00:00
|
|
|
|
|
2024-09-04 00:35:25 +00:00
|
|
|
|
int
|
|
|
|
|
qc_parse_string (const char *str)
|
|
|
|
|
{
|
|
|
|
|
rua_parser_t parser = {
|
|
|
|
|
.parse = qc_yypush_parse,
|
|
|
|
|
.state = qc_yypstate_new (),
|
|
|
|
|
.directive = qc_directive,
|
|
|
|
|
.keyword_or_id = qc_keyword_or_id,
|
|
|
|
|
};
|
|
|
|
|
int ret = rua_parse_string (str, &parser);
|
|
|
|
|
glsl_yypstate_delete (parser.state);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-28 01:18:21 +00:00
|
|
|
|
static int qc_finish (const char *file)
|
|
|
|
|
{
|
|
|
|
|
if (options.frames_files) {
|
|
|
|
|
write_frame_macros (va (0, "%s.frame", file_basename (file, 0)));
|
|
|
|
|
}
|
|
|
|
|
class_finish_module ();
|
|
|
|
|
return pr.error_count;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-19 16:39:44 +00:00
|
|
|
|
static void
|
|
|
|
|
rua_init (void)
|
|
|
|
|
{
|
|
|
|
|
current_language.initialized = true;
|
|
|
|
|
if (options.code.spirv) {
|
|
|
|
|
static module_t module; //FIXME probably not what I want
|
|
|
|
|
pr.module = &module;
|
|
|
|
|
|
|
|
|
|
spirv_add_capability (pr.module, SpvCapabilityShader);
|
2024-09-20 05:03:03 +00:00
|
|
|
|
//FIXME unhardcode
|
|
|
|
|
spirv_add_extension (pr.module, "SPV_KHR_multiview");
|
|
|
|
|
spirv_add_extinst_import (pr.module, "GLSL.std.450");
|
2024-09-19 16:39:44 +00:00
|
|
|
|
//FIXME sufficient? phys 32/storage?
|
|
|
|
|
spirv_set_addressing_model (pr.module, SpvAddressingModelLogical);
|
|
|
|
|
//FIXME look into Vulkan, or even configurable
|
|
|
|
|
spirv_set_memory_model (pr.module, SpvMemoryModelGLSL450);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-28 01:18:21 +00:00
|
|
|
|
language_t lang_ruamoko = {
|
2024-09-19 16:39:44 +00:00
|
|
|
|
.init = rua_init,
|
2024-08-28 01:18:21 +00:00
|
|
|
|
.parse = qc_yyparse,
|
|
|
|
|
.finish = qc_finish,
|
|
|
|
|
};
|