pike.git/
src/
language.yacc
Branch:
Tag:
Non-build tags
All tags
No tags
2001-03-31
2001-03-31 15:20:43 by Henrik Grubbström (Grubba) <grubba@grubba.org>
a418ce8c11f2258a1152242faa9e8bdf3e8360d4 (
128
lines) (+
127
/-
1
)
[
Show
|
Annotate
]
Branch:
7.9
Added support for enum.
Rev: src/language.yacc:1.238
111:
/* This is the grammar definition of Pike. */ #include "global.h"
-
RCSID("$Id: language.yacc,v 1.
237
2001/03/31
01
:
12
:
47
grubba Exp $");
+
RCSID("$Id: language.yacc,v 1.
238
2001/03/31
15
:
20
:
43
grubba Exp $");
#ifdef HAVE_MEMORY_H #include <memory.h> #endif
131:
#include "machine.h" #include "main.h" #include "opcodes.h"
+
#include "operators.h"
#define YYMAXDEPTH 1000
146:
int low_add_local_name(struct compiler_frame *, struct pike_string *, struct pike_type *, node *); static node *lexical_islocal(struct pike_string *);
+
static void safe_inc_enum(void);
static int inherit_depth; static struct program_state *inherit_state = NULL;
273:
%type <n> catch %type <n> catch_arg %type <n> class
+
%type <n> enum
+
%type <n> enum_identifier
%type <n> safe_comma_expr %type <n> comma_expr %type <n> comma_expr2
873:
| import {} | constant {} | class { free_node($1); }
+
| enum { free_node($1); }
| error TOK_LEX_EOF { reset_type_stack();
2369:
} ;
+
enum_identifier: TOK_IDENTIFIER
+
| bad_identifier { $$ = 0; }
+
;
+
+
enum_value: /* EMPTY */
+
{
+
safe_inc_enum();
+
}
+
| '=' safe_expr0
+
{
+
pop_stack();
+
+
/* This can be made more lenient in the future */
+
+
/* Ugly hack to make sure that $2 is optimized */
+
{
+
int tmp=Pike_compiler->compiler_pass;
+
$2=mknode(F_COMMA_EXPR,$2,0);
+
Pike_compiler->compiler_pass=tmp;
+
}
+
+
if(!is_const($2))
+
{
+
if(Pike_compiler->compiler_pass==2)
+
yyerror("Enum definition is not constant.");
+
push_int(0);
+
} else {
+
if(!Pike_compiler->num_parse_error)
+
{
+
ptrdiff_t tmp=eval_low($2);
+
if(tmp < 1)
+
{
+
yyerror("Error in enum definition.");
+
push_int(0);
+
}else{
+
pop_n_elems(DO_NOT_WARN((INT32)(tmp - 1)));
+
}
+
} else {
+
push_int(0);
+
}
+
}
+
if($2) free_node($2);
+
}
+
;
+
+
enum_def: /* EMPTY */
+
| enum_identifier enum_value
+
{
+
if ($1) {
+
add_constant($1->u.sval.u.string, Pike_sp-1,
+
Pike_compiler->current_modifiers & ~ID_EXTERN);
+
}
+
free_node($1);
+
/* Update the type. */
+
{
+
struct pike_type *current = pop_unfinished_type();
+
struct pike_type *new = get_type_of_svalue(Pike_sp-1);
+
struct pike_type *res = or_pike_types(current, new, 1);
+
free_type(current);
+
free_type(new);
+
type_stack_mark();
+
push_finished_type(res);
+
}
+
}
+
;
+
+
enum_list: enum_def
+
| enum_list ',' enum_def
+
;
+
+
enum: modifiers TOK_ENUM
+
{
+
if ((Pike_compiler->current_modifiers & ID_EXTERN) &&
+
(Pike_compiler->compiler_pass == 1)) {
+
yywarning("Extern declared enum.");
+
}
+
+
push_int(-1); /* Last enum-value. */
+
type_stack_mark();
+
push_type(T_ZERO); /* Joined type so far. */
+
}
+
optional_identifier '{' enum_list end_block
+
{
+
struct pike_type *t = pop_unfinished_type();
+
pop_stack();
+
if ($4) {
+
ref_push_type_value(t);
+
add_constant($4->u.sval.u.string, Pike_sp-1,
+
Pike_compiler->current_modifiers & ~ID_EXTERN);
+
pop_stack();
+
free_node($4);
+
}
+
$$ = mktypenode(t);
+
free_type(t);
+
}
+
;
+
cond: TOK_IF { $<number>$=Pike_compiler->compiler_frame->current_number_of_locals;
2841:
| sscanf | lambda | class
+
| enum
| idents2 | expr4 '(' expr_list ')' {
3656:
} }
+
static void safe_inc_enum(void)
+
{
+
struct svalue *save_sp = Pike_sp;
+
JMP_BUF recovery;
+
+
free_svalue(&throw_value);
+
throw_value.type = T_INT;
+
if (SETJMP(recovery)) {
+
yyerror("Bad implicit enum value (failed to add 1).");
+
while(Pike_sp > save_sp) pop_stack();
+
} else {
+
push_int(1);
+
f_add(2);
+
}
+
UNSETJMP(recovery);
+
#ifdef PIKE_DEBUG
+
if (Pike_sp != save_sp) {
+
fatal("stack thrashed in enum.\n");
+
}
+
#endif /* PIKE_DEBUG */
+
}
+
void cleanup_compiler(void) { }