Branch: Tag:

2001-03-31

2001-03-31 15:20:43 by Henrik Grubbström (Grubba) <grubba@grubba.org>

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)   {   }