NASM parser: change from Bison parser to hand-written recursive descent

parser with one token of lookahead.  This allows for better error handling
and proper handling of things like "xxxx"/5.  There may be a minor speedup
but it's probably a wash.

Still TODO:
 - Unify the expression parser with the NASM preproc one.
 - Change the GAS parser to recursive descent.

Only had to change one test result; this is due to re-ordering of symrec
creation versus symrec use in data expressions such as x db y.  With the
Bison parser, the symrec use (y) would come first, now the symrec creation
(x) comes first.

svn path=/trunk/yasm/; revision=1716
0.6.0
Peter Johnson 18 years ago
parent 9593bcf56b
commit d52034249a
  1. 20
      modules/objfmts/win64/tests/win64-dataref.hex
  2. 8
      modules/parsers/nasm/Makefile.inc
  3. 694
      modules/parsers/nasm/nasm-bison.y
  4. 85
      modules/parsers/nasm/nasm-defs.h
  5. 1197
      modules/parsers/nasm/nasm-parse.c
  6. 2
      modules/parsers/nasm/nasm-parser.c
  7. 77
      modules/parsers/nasm/nasm-parser.h
  8. 17
      modules/parsers/nasm/nasm-token.re

@ -1364,7 +1364,7 @@ f8
00
00
00
16
17
00
00
00
@ -1374,7 +1374,7 @@ f8
00
00
00
16
17
00
00
00
@ -1999,36 +1999,36 @@ a0
03
00
78
70
74
72
00
00
00
00
40
00
00
00
00
02
00
00
00
03
00
78
00
00
00
03
00
78
70
74
72
00
00
00
00
40
00
00
00
02
03
00
00
00

@ -2,9 +2,7 @@
libyasm_a_SOURCES += modules/parsers/nasm/nasm-parser.c
libyasm_a_SOURCES += modules/parsers/nasm/nasm-parser.h
libyasm_a_SOURCES += modules/parsers/nasm/nasm-defs.h
libyasm_a_SOURCES += modules/parsers/nasm/nasm-bison.y
libyasm_a_SOURCES += nasm-bison.h
libyasm_a_SOURCES += modules/parsers/nasm/nasm-parse.c
libyasm_a_SOURCES += nasm-token.c
YASM_MODULES += parser_nasm
@ -12,12 +10,8 @@ YASM_MODULES += parser_nasm
nasm-token.c: $(srcdir)/modules/parsers/nasm/nasm-token.re re2c$(EXEEXT)
$(top_builddir)/re2c$(EXEEXT) -b -o $@ $(srcdir)/modules/parsers/nasm/nasm-token.re
BUILT_SOURCES += nasm-bison.c
BUILT_SOURCES += nasm-bison.h
BUILT_SOURCES += nasm-token.c
CLEANFILES += nasm-bison.c
CLEANFILES += nasm-bison.h
CLEANFILES += nasm-token.c
EXTRA_DIST += modules/parsers/nasm/tests/Makefile.inc

@ -1,694 +0,0 @@
/*
* NASM-compatible bison parser
*
* Copyright (C) 2001 Peter Johnson, Michael Urman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
%{
#include <util.h>
RCSID("$Id$");
#define YASM_LIB_INTERNAL
#define YASM_EXPR_INTERNAL
#include <libyasm.h>
#ifdef STDC_HEADERS
# include <math.h>
#endif
#include "modules/parsers/nasm/nasm-parser.h"
#include "modules/parsers/nasm/nasm-defs.h"
static void nasm_parser_directive
(yasm_parser_nasm *parser_nasm, const char *name,
yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams);
static int fix_directive_symrec(/*@null@*/ yasm_expr__item *ei,
/*@null@*/ void *d);
static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
int local);
#define nasm_parser_error(s) yasm_error_set(YASM_ERROR_PARSE, "%s", s)
#define YYPARSE_PARAM parser_nasm_arg
#define YYLEX_PARAM parser_nasm_arg
#define parser_nasm ((yasm_parser_nasm *)parser_nasm_arg)
#define nasm_parser_debug (parser_nasm->debug)
/*@-usedef -nullassign -memtrans -usereleased -compdef -mustfree@*/
%}
%pure_parser
%union {
unsigned int int_info;
char *str_val;
yasm_intnum *intn;
yasm_floatnum *flt;
yasm_symrec *sym;
unsigned long arch_data[4];
yasm_effaddr *ea;
yasm_expr *exp;
yasm_datavalhead datahead;
yasm_dataval *data;
yasm_bytecode *bc;
yasm_valparamhead dir_valparams;
yasm_valparam *dir_valparam;
struct {
yasm_insn_operands operands;
int num_operands;
} insn_operands;
yasm_insn_operand *insn_operand;
struct {
char *name;
int local;
} label;
struct {
char *contents;
size_t len;
} str;
}
%token <intn> INTNUM
%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME FILENAME
%token <str> STRING ONECHARSTR
%token <int_info> SIZE_OVERRIDE
%token <int_info> DECLARE_DATA
%token <int_info> RESERVE_SPACE
%token INCBIN EQU TIMES
%token SEG WRT NOSPLIT STRICT
%token <arch_data> INSN PREFIX REG SEGREG TARGETMOD
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID
%token <str_val> ID LOCAL_ID SPECIAL_ID
%token LINE
%type <bc> line lineexp exp instr
%type <ea> memaddr
%type <exp> dvexpr expr direxpr
%type <sym> explabel
%type <label> label_id label
%type <data> dataval
%type <datahead> datavals
%type <dir_valparams> directive_valparams
%type <dir_valparam> directive_valparam
%type <insn_operands> operands
%type <insn_operand> operand
%type <str> string
%left ':'
%left WRT
%left '|'
%left '^'
%left '&'
%left LEFT_OP RIGHT_OP
%left '-' '+'
%left '*' '/' SIGNDIV '%' SIGNMOD
%nonassoc UNARYOP
%nonassoc SEG
%%
input: /* empty */
| input line {
yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
parser_nasm->temp_bc =
yasm_section_bcs_append(parser_nasm->cur_section, $2);
if (parser_nasm->temp_bc)
parser_nasm->prev_bc = parser_nasm->temp_bc;
if (parser_nasm->save_input)
yasm_linemap_add_source(parser_nasm->linemap,
parser_nasm->temp_bc,
(char *)parser_nasm->save_line[parser_nasm->save_last ^ 1]);
yasm_linemap_goto_next(parser_nasm->linemap);
}
;
line: '\n' { $$ = (yasm_bytecode *)NULL; }
| lineexp '\n'
| LINE INTNUM '+' INTNUM FILENAME '\n' {
/* %line indicates the line number of the *next* line, so subtract out
* the increment when setting the line number.
*/
yasm_linemap_set(parser_nasm->linemap, $5,
yasm_intnum_get_uint($2) - yasm_intnum_get_uint($4),
yasm_intnum_get_uint($4));
yasm_intnum_destroy($2);
yasm_intnum_destroy($4);
yasm_xfree($5);
$$ = (yasm_bytecode *)NULL;
}
| '[' { parser_nasm->state = DIRECTIVE; } directive ']' '\n' {
$$ = (yasm_bytecode *)NULL;
}
| error '\n' {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("label or instruction expected at start of line"));
$$ = (yasm_bytecode *)NULL;
yyerrok;
}
;
lineexp: exp
| TIMES expr exp { $$ = $3; yasm_bc_set_multiple($$, $2); }
| label_id {
yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
N_("label alone on a line without a colon might be in error"));
$$ = (yasm_bytecode *)NULL;
define_label(parser_nasm, $1.name, $1.local);
}
| label_id ':' {
$$ = (yasm_bytecode *)NULL;
define_label(parser_nasm, $1.name, $1.local);
}
| label exp {
$$ = $2;
define_label(parser_nasm, $1.name, $1.local);
}
| label TIMES expr exp {
$$ = $4;
yasm_bc_set_multiple($$, $3);
define_label(parser_nasm, $1.name, $1.local);
}
| label EQU expr {
$$ = (yasm_bytecode *)NULL;
yasm_symtab_define_equ(p_symtab, $1.name, $3, cur_line);
yasm_xfree($1.name);
}
;
exp: instr
| DECLARE_DATA datavals {
$$ = yasm_bc_create_data(&$2, $1/8, 0, parser_nasm->arch, cur_line);
}
| RESERVE_SPACE expr {
$$ = yasm_bc_create_reserve($2, $1/8, cur_line);
}
| INCBIN string {
$$ = yasm_bc_create_incbin($2.contents, NULL, NULL,
parser_nasm->linemap, cur_line);
}
| INCBIN string ',' {
$$ = yasm_bc_create_incbin($2.contents, NULL, NULL,
parser_nasm->linemap, cur_line);
}
| INCBIN string ',' expr {
$$ = yasm_bc_create_incbin($2.contents, $4, NULL,
parser_nasm->linemap, cur_line);
}
| INCBIN string ',' expr ',' {
$$ = yasm_bc_create_incbin($2.contents, $4, NULL,
parser_nasm->linemap, cur_line);
}
| INCBIN string ',' expr ',' expr {
$$ = yasm_bc_create_incbin($2.contents, $4, $6, parser_nasm->linemap,
cur_line);
}
;
instr: INSN {
$$ = yasm_bc_create_insn(parser_nasm->arch, $1, 0, NULL, cur_line);
}
| INSN operands {
$$ = yasm_bc_create_insn(parser_nasm->arch, $1, $2.num_operands,
&$2.operands, cur_line);
}
| INSN error {
yasm_error_set(YASM_ERROR_SYNTAX, N_("expression syntax error"));
$$ = NULL;
}
| PREFIX instr {
$$ = $2;
yasm_bc_insn_add_prefix($$, $1);
}
| SEGREG instr {
$$ = $2;
yasm_bc_insn_add_seg_prefix($$, $1[0]);
}
;
datavals: dataval {
yasm_dvs_initialize(&$$);
yasm_dvs_append(&$$, $1);
}
| datavals ',' dataval { yasm_dvs_append(&$1, $3); $$ = $1; }
| datavals ',' { $$ = $1; }
;
dataval: dvexpr { $$ = yasm_dv_create_expr($1); }
| STRING {
$$ = yasm_dv_create_string($1.contents, $1.len);
}
| error {
yasm_error_set(YASM_ERROR_SYNTAX, N_("expression syntax error"));
$$ = (yasm_dataval *)NULL;
}
;
label: label_id
| label_id ':' { $$ = $1; }
;
label_id: ID { $$.name = $1; $$.local = 0; }
| SPECIAL_ID { $$.name = $1; $$.local = 1; }
| LOCAL_ID { $$.name = $1; $$.local = 1; }
;
/* directives */
directive: DIRECTIVE_NAME directive_val {
yasm_xfree($1);
}
| DIRECTIVE_NAME error {
yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid arguments to [%s]"), $1);
yasm_xfree($1);
}
;
/* $<str_val>0 is the DIRECTIVE_NAME */
/* After : is (optional) object-format specific extension */
directive_val: directive_valparams {
nasm_parser_directive(parser_nasm, $<str_val>0, &$1, NULL);
}
| directive_valparams ':' directive_valparams {
nasm_parser_directive(parser_nasm, $<str_val>0, &$1, &$3);
}
;
directive_valparams: directive_valparam {
yasm_vps_initialize(&$$);
yasm_vps_append(&$$, $1);
}
| directive_valparams directive_valparam {
yasm_vps_append(&$1, $2);
$$ = $1;
}
| directive_valparams ',' directive_valparam {
yasm_vps_append(&$1, $3);
$$ = $1;
}
;
directive_valparam: direxpr {
/* If direxpr is just an ID, put it in val and delete the expr.
* Otherwise, we need to go through the expr and replace the current
* (local) symrecs with the use of global ones.
*/
const /*@null@*/ yasm_symrec *vp_symrec;
if ((vp_symrec = yasm_expr_get_symrec(&$1, 0))) {
$$ = yasm_vp_create(yasm__xstrdup(yasm_symrec_get_name(vp_symrec)),
NULL);
yasm_expr_destroy($1);
} else {
yasm_expr__traverse_leaves_in($1, parser_nasm,
fix_directive_symrec);
$$ = yasm_vp_create(NULL, $1);
}
}
| string { $$ = yasm_vp_create($1.contents, NULL); }
| ID '=' direxpr {
yasm_expr__traverse_leaves_in($3, parser_nasm, fix_directive_symrec);
$$ = yasm_vp_create($1, $3);
}
;
/* memory addresses */
memaddr: expr {
$$ = yasm_arch_ea_create(parser_nasm->arch, $1);
}
| SEGREG ':' memaddr {
$$ = $3;
yasm_ea_set_segreg($$, $1[0]);
}
| SIZE_OVERRIDE memaddr { $$ = $2; yasm_ea_set_len($$, $1); }
| NOSPLIT memaddr { $$ = $2; yasm_ea_set_nosplit($$, 1); }
;
/* instruction operands */
operands: operand {
yasm_ops_initialize(&$$.operands);
yasm_ops_append(&$$.operands, $1);
$$.num_operands = 1;
}
| operands ',' operand {
yasm_ops_append(&$1.operands, $3);
$$.operands = $1.operands;
$$.num_operands = $1.num_operands+1;
}
;
operand: '[' memaddr ']' { $$ = yasm_operand_create_mem($2); }
| expr { $$ = yasm_operand_create_imm($1); }
| SEGREG { $$ = yasm_operand_create_segreg($1[0]); }
| STRICT operand { $$ = $2; $$->strict = 1; }
| SIZE_OVERRIDE operand {
$$ = $2;
if ($$->type == YASM_INSN__OPERAND_REG &&
yasm_arch_get_reg_size(parser_nasm->arch, $$->data.reg) != $1)
yasm_error_set(YASM_ERROR_TYPE,
N_("cannot override register size"));
else
$$->size = $1;
}
| TARGETMOD operand { $$ = $2; $$->targetmod = $1[0]; }
;
/* expression trees */
/* expr w/o FLTNUM and unary + and -, for use in directives */
direxpr: INTNUM { $$ = p_expr_new_ident(yasm_expr_int($1)); }
| ID {
$$ = p_expr_new_ident(yasm_expr_sym(
yasm_symtab_define_label(p_symtab, $1,
yasm_section_bcs_first(parser_nasm->cur_section), 0,
cur_line)));
yasm_xfree($1);
}
| direxpr '|' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_OR, $3); }
| direxpr '^' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_XOR, $3); }
| direxpr '&' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_AND, $3); }
| direxpr LEFT_OP direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHL, $3); }
| direxpr RIGHT_OP direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHR, $3); }
| direxpr '+' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_ADD, $3); }
| direxpr '-' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SUB, $3); }
| direxpr '*' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_MUL, $3); }
| direxpr '/' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_DIV, $3); }
| direxpr SIGNDIV direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNDIV, $3); }
| direxpr '%' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_MOD, $3); }
| direxpr SIGNMOD direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNMOD, $3); }
/*| '!' expr { $$ = p_expr_new_branch(YASM_EXPR_LNOT, $2); }*/
| '~' direxpr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NOT, $2); }
| '(' direxpr ')' { $$ = $2; }
;
dvexpr: INTNUM { $$ = p_expr_new_ident(yasm_expr_int($1)); }
| FLTNUM { $$ = p_expr_new_ident(yasm_expr_float($1)); }
| ONECHARSTR {
$$ = p_expr_new_ident(yasm_expr_int(
yasm_intnum_create_charconst_nasm($1.contents)));
yasm_xfree($1.contents);
}
| explabel { $$ = p_expr_new_ident(yasm_expr_sym($1)); }
/*| dvexpr '||' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_LOR, $3); }*/
| dvexpr '|' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_OR, $3); }
| dvexpr '^' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_XOR, $3); }
/*| dvexpr '&&' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_LAND, $3); }*/
| dvexpr '&' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_AND, $3); }
/*| dvexpr '==' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_EQUALS, $3); }*/
/*| dvexpr '>' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
/*| dvexpr '<' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
/*| dvexpr '>=' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
/*| dvexpr '<=' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
/*| dvexpr '!=' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_NE, $3); }*/
| dvexpr LEFT_OP dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHL, $3); }
| dvexpr RIGHT_OP dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHR, $3); }
| dvexpr '+' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_ADD, $3); }
| dvexpr '-' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SUB, $3); }
| dvexpr '*' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_MUL, $3); }
| dvexpr '/' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_DIV, $3); }
| dvexpr SIGNDIV dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNDIV, $3); }
| dvexpr '%' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_MOD, $3); }
| dvexpr SIGNMOD dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNMOD, $3); }
| '+' dvexpr %prec UNARYOP { $$ = $2; }
| '-' dvexpr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NEG, $2); }
/*| '!' dvexpr { $$ = p_expr_new_branch(YASM_EXPR_LNOT, $2); }*/
| '~' dvexpr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NOT, $2); }
| SEG dvexpr { $$ = p_expr_new_branch(YASM_EXPR_SEG, $2); }
| dvexpr WRT dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_WRT, $3); }
| '(' dvexpr ')' { $$ = $2; }
;
/* Expressions for operands and memory expressions.
* We don't attempt to check memory expressions for validity here.
* Essentially the same as dvexpr above but adds REG and string.
*/
expr: INTNUM { $$ = p_expr_new_ident(yasm_expr_int($1)); }
| FLTNUM { $$ = p_expr_new_ident(yasm_expr_float($1)); }
| REG { $$ = p_expr_new_ident(yasm_expr_reg($1[0])); }
| string {
$$ = p_expr_new_ident(yasm_expr_int(
yasm_intnum_create_charconst_nasm($1.contents)));
yasm_xfree($1.contents);
}
| explabel { $$ = p_expr_new_ident(yasm_expr_sym($1)); }
/*| expr '||' expr { $$ = p_expr_new_tree($1, YASM_EXPR_LOR, $3); }*/
| expr '|' expr { $$ = p_expr_new_tree($1, YASM_EXPR_OR, $3); }
| expr '^' expr { $$ = p_expr_new_tree($1, YASM_EXPR_XOR, $3); }
/*| expr '&&' expr { $$ = p_expr_new_tree($1, YASM_EXPR_LAND, $3); }*/
| expr '&' expr { $$ = p_expr_new_tree($1, YASM_EXPR_AND, $3); }
/*| expr '==' expr { $$ = p_expr_new_tree($1, YASM_EXPR_EQUALS, $3); }*/
/*| expr '>' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
/*| expr '<' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
/*| expr '>=' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
/*| expr '<=' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
/*| expr '!=' expr { $$ = p_expr_new_tree($1, YASM_EXPR_NE, $3); }*/
| expr LEFT_OP expr { $$ = p_expr_new_tree($1, YASM_EXPR_SHL, $3); }
| expr RIGHT_OP expr { $$ = p_expr_new_tree($1, YASM_EXPR_SHR, $3); }
| expr '+' expr { $$ = p_expr_new_tree($1, YASM_EXPR_ADD, $3); }
| expr '-' expr { $$ = p_expr_new_tree($1, YASM_EXPR_SUB, $3); }
| expr '*' expr { $$ = p_expr_new_tree($1, YASM_EXPR_MUL, $3); }
| expr '/' expr { $$ = p_expr_new_tree($1, YASM_EXPR_DIV, $3); }
| expr SIGNDIV expr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNDIV, $3); }
| expr '%' expr { $$ = p_expr_new_tree($1, YASM_EXPR_MOD, $3); }
| expr SIGNMOD expr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNMOD, $3); }
| '+' expr %prec UNARYOP { $$ = $2; }
| '-' expr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NEG, $2); }
/*| '!' expr { $$ = p_expr_new_branch(YASM_EXPR_LNOT, $2); }*/
| '~' expr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NOT, $2); }
| SEG expr { $$ = p_expr_new_branch(YASM_EXPR_SEG, $2); }
| expr WRT expr { $$ = p_expr_new_tree($1, YASM_EXPR_WRT, $3); }
| expr ':' expr { $$ = p_expr_new_tree($1, YASM_EXPR_SEGOFF, $3); }
| '(' expr ')' { $$ = $2; }
;
explabel: ID {
$$ = yasm_symtab_use(p_symtab, $1, cur_line);
yasm_xfree($1);
}
| SPECIAL_ID {
$$ = yasm_symtab_use(p_symtab, $1, cur_line);
yasm_xfree($1);
}
| LOCAL_ID {
$$ = yasm_symtab_use(p_symtab, $1, cur_line);
yasm_xfree($1);
}
| '$' {
/* "$" references the current assembly position */
$$ = yasm_symtab_define_curpos(p_symtab, "$", parser_nasm->prev_bc,
cur_line);
}
| START_SECTION_ID {
/* "$$" references the start of the current section */
$$ = yasm_symtab_define_label(p_symtab, "$$",
yasm_section_bcs_first(parser_nasm->cur_section), 0, cur_line);
}
;
string: STRING | ONECHARSTR;
%%
/*@=usedef =nullassign =memtrans =usereleased =compdef =mustfree@*/
#undef parser_nasm
static void
define_label(yasm_parser_nasm *parser_nasm, char *name, int local)
{
if (!local) {
if (parser_nasm->locallabel_base)
yasm_xfree(parser_nasm->locallabel_base);
parser_nasm->locallabel_base_len = strlen(name);
parser_nasm->locallabel_base =
yasm_xmalloc(parser_nasm->locallabel_base_len+1);
strcpy(parser_nasm->locallabel_base, name);
}
yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc, 1,
cur_line);
yasm_xfree(name);
}
static int
fix_directive_symrec(yasm_expr__item *ei, void *d)
{
yasm_parser_nasm *parser_nasm = (yasm_parser_nasm *)d;
if (!ei || ei->type != YASM_EXPR_SYM)
return 0;
/* FIXME: Delete current symrec */
ei->data.sym =
yasm_symtab_use(p_symtab, yasm_symrec_get_name(ei->data.sym),
cur_line);
return 0;
}
static void
nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
yasm_valparamhead *valparams,
yasm_valparamhead *objext_valparams)
{
yasm_valparam *vp, *vp2;
unsigned long line = cur_line;
/* Handle (mostly) output-format independent directives here */
if (yasm__strcasecmp(name, "extern") == 0) {
vp = yasm_vps_first(valparams);
if (vp->val) {
yasm_objfmt_extern_declare(parser_nasm->objfmt, vp->val,
objext_valparams, line);
} else
yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
"EXTERN");
} else if (yasm__strcasecmp(name, "global") == 0) {
vp = yasm_vps_first(valparams);
if (vp->val) {
yasm_objfmt_global_declare(parser_nasm->objfmt, vp->val,
objext_valparams, line);
} else
yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
"GLOBAL");
} else if (yasm__strcasecmp(name, "common") == 0) {
vp = yasm_vps_first(valparams);
if (vp->val) {
vp2 = yasm_vps_next(vp);
if (!vp2 || (!vp2->val && !vp2->param))
yasm_error_set(YASM_ERROR_SYNTAX,
N_("no size specified in %s declaration"),
"COMMON");
else {
if (vp2->val) {
yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
p_expr_new_ident(yasm_expr_sym(
yasm_symtab_use(p_symtab, vp2->val, line))),
objext_valparams, line);
} else if (vp2->param) {
yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
vp2->param, objext_valparams,
line);
vp2->param = NULL;
}
}
} else
yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
"COMMON");
} else if (yasm__strcasecmp(name, "section") == 0 ||
yasm__strcasecmp(name, "segment") == 0) {
yasm_section *new_section =
yasm_objfmt_section_switch(parser_nasm->objfmt, valparams,
objext_valparams, line);
if (new_section) {
parser_nasm->cur_section = new_section;
parser_nasm->prev_bc = yasm_section_bcs_last(new_section);
} else
yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
"SECTION");
} else if (yasm__strcasecmp(name, "absolute") == 0) {
/* it can be just an ID or a complete expression, so handle both. */
vp = yasm_vps_first(valparams);
if (vp->val)
parser_nasm->cur_section =
yasm_object_create_absolute(parser_nasm->object,
p_expr_new_ident(yasm_expr_sym(
yasm_symtab_use(p_symtab, vp->val, line))), line);
else if (vp->param) {
parser_nasm->cur_section =
yasm_object_create_absolute(parser_nasm->object, vp->param,
line);
vp->param = NULL;
}
parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
} else if (yasm__strcasecmp(name, "align") == 0) {
/*@only@*/ yasm_expr *boundval;
/*@depedent@*/ yasm_intnum *boundintn;
/* it can be just an ID or a complete expression, so handle both. */
vp = yasm_vps_first(valparams);
if (vp->val)
boundval = p_expr_new_ident(yasm_expr_sym(
yasm_symtab_use(p_symtab, vp->val, line)));
else if (vp->param) {
boundval = vp->param;
vp->param = NULL;
}
/* Largest .align in the section specifies section alignment.
* Note: this doesn't match NASM behavior, but is a lot more
* intelligent!
*/
boundintn = yasm_expr_get_intnum(&boundval, 0);
if (boundintn) {
unsigned long boundint = yasm_intnum_get_uint(boundintn);
/* Alignments must be a power of two. */
if (is_exp2(boundint)) {
if (boundint > yasm_section_get_align(parser_nasm->cur_section))
yasm_section_set_align(parser_nasm->cur_section, boundint,
cur_line);
}
}
/* As this directive is called only when nop is used as fill, always
* use arch (nop) fill.
*/
parser_nasm->prev_bc =
yasm_section_bcs_append(parser_nasm->cur_section,
yasm_bc_create_align(boundval, NULL, NULL,
/*yasm_section_is_code(parser_nasm->cur_section) ?*/
yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
cur_line));
} else if (yasm__strcasecmp(name, "cpu") == 0) {
yasm_vps_foreach(vp, valparams) {
if (vp->val)
yasm_arch_parse_cpu(parser_nasm->arch, vp->val,
strlen(vp->val));
else if (vp->param) {
const yasm_intnum *intcpu;
intcpu = yasm_expr_get_intnum(&vp->param, 0);
if (!intcpu)
yasm_error_set(YASM_ERROR_SYNTAX,
N_("invalid argument to [%s]"), "CPU");
else {
char strcpu[16];
sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
yasm_arch_parse_cpu(parser_nasm->arch, strcpu,
strlen(strcpu));
}
}
}
} else if (!yasm_arch_parse_directive(parser_nasm->arch, name, valparams,
objext_valparams, parser_nasm->object, line)) {
;
} else if (!yasm_dbgfmt_directive(parser_nasm->dbgfmt, name,
parser_nasm->cur_section, valparams,
line)) {
;
} else if (yasm_objfmt_directive(parser_nasm->objfmt, name, valparams,
objext_valparams, line)) {
yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive [%s]"),
name);
}
yasm_vps_delete(valparams);
if (objext_valparams)
yasm_vps_delete(objext_valparams);
}

@ -1,85 +0,0 @@
/* $Id$
* Variable name redefinitions for NASM-compatible parser
*
* Copyright (C) 2001 Peter Johnson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define yy_create_buffer nasm_parser__create_buffer
#define yy_delete_buffer nasm_parser__delete_buffer
#define yy_init_buffer nasm_parser__init_buffer
#define yy_load_buffer_state nasm_parser__load_buffer_state
#define yy_switch_to_buffer nasm_parser__switch_to_buffer
#define yyact nasm_parser_act
#define yyback nasm_parser_back
#define yybgin nasm_parser_bgin
#define yychar nasm_parser_char
#define yychk nasm_parser_chk
#define yycrank nasm_parser_crank
#define yydebug nasm_parser_debug
#define yydef nasm_parser_def
#define yyerrflag nasm_parser_errflag
#define yyerror nasm_parser_error
#define yyestate nasm_parser_estate
#define yyexca nasm_parser_exca
#define yyextra nasm_parser_extra
#define yyfnd nasm_parser_fnd
#define yyin nasm_parser_in
#define yyinput nasm_parser_input
#define yyleng nasm_parser_leng
#define yylex nasm_parser_lex
#define yylineno nasm_parser_lineno
#define yylook nasm_parser_look
#define yylsp nasm_parser_lsp
#define yylstate nasm_parser_lstate
#define yylval nasm_parser_lval
#define yymatch nasm_parser_match
#define yymorfg nasm_parser_morfg
#define yynerrs nasm_parser_nerrs
#define yyolsp nasm_parser_olsp
#define yyout nasm_parser_out
#define yyoutput nasm_parser_output
#define yypact nasm_parser_pact
#define yyparse nasm_parser_parse
#define yypgo nasm_parser_pgo
#define yyprevious nasm_parser_previous
#define yyps nasm_parser_ps
#define yypv nasm_parser_pv
#define yyr1 nasm_parser_r1
#define yyr2 nasm_parser_r2
#define yyreds nasm_parser_reds
#define yyrestart nasm_parser_restart
#define yys nasm_parser_s
#define yysbuf nasm_parser_sbuf
#define yysptr nasm_parser_sptr
#define yystate nasm_parser_state
#define yysvec nasm_parser_svec
#define yytchar nasm_parser_tchar
#define yytext nasm_parser_text
#define yytmp nasm_parser_tmp
#define yytoks nasm_parser_toks
#define yytop nasm_parser_top
#define yyunput nasm_parser_unput
#define yyv nasm_parser_v
#define yyval nasm_parser_val
#define yyvstop nasm_parser_vstop
/*#define yywrap nasm_parser_wrap*/

File diff suppressed because it is too large Load Diff

@ -62,6 +62,8 @@ nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp, yasm_arch *a,
parser_nasm.save_input = save_input;
parser_nasm.save_last = 0;
parser_nasm.peek_token = NONE;
/* initialize scanner structure */
yasm_scanner_initialize(&parser_nasm.s);

@ -27,12 +27,56 @@
#ifndef YASM_NASM_PARSER_H
#define YASM_NASM_PARSER_H
#include "nasm-bison.h"
#define YYCTYPE unsigned char
#define MAX_SAVED_LINE_LEN 80
enum tokentype {
INTNUM = 258,
FLTNUM,
DIRECTIVE_NAME,
FILENAME,
STRING,
SIZE_OVERRIDE,
DECLARE_DATA,
RESERVE_SPACE,
INCBIN,
EQU,
TIMES,
SEG,
WRT,
NOSPLIT,
STRICT,
INSN,
PREFIX,
REG,
SEGREG,
TARGETMOD,
LEFT_OP,
RIGHT_OP,
SIGNDIV,
SIGNMOD,
START_SECTION_ID,
ID,
LOCAL_ID,
SPECIAL_ID,
LINE,
NONE /* special token for lookahead */
};
typedef union {
unsigned int int_info;
char *str_val;
yasm_intnum *intn;
yasm_floatnum *flt;
unsigned long arch_data[4];
struct {
char *contents;
size_t len;
} str;
} yystype;
#define YYSTYPE yystype
typedef struct yasm_parser_nasm {
FILE *in;
int debug;
@ -54,7 +98,6 @@ typedef struct yasm_parser_nasm {
/*@dependent@*/ yasm_symtab *symtab;
/*@null@*/ yasm_bytecode *prev_bc;
yasm_bytecode *temp_bc;
int save_input;
YYCTYPE save_line[2][MAX_SAVED_LINE_LEN];
@ -69,10 +112,36 @@ typedef struct yasm_parser_nasm {
LINECHG2,
INSTRUCTION
} state;
int token; /* enum tokentype or any character */
yystype tokval;
char tokch; /* first character of token */
/* one token of lookahead; used sparingly */
int peek_token; /* NONE if none */
yystype peek_tokval;
char peek_tokch;
} yasm_parser_nasm;
/* shorter access names to commonly used parser_nasm fields */
#define p_symtab (parser_nasm->symtab)
#define curtok (parser_nasm->token)
#define curval (parser_nasm->tokval)
#define INTNUM_val (curval.intn)
#define FLTNUM_val (curval.flt)
#define DIRECTIVE_NAME_val (curval.str_val)
#define FILENAME_val (curval.str_val)
#define STRING_val (curval.str)
#define SIZE_OVERRIDE_val (curval.int_info)
#define DECLARE_DATA_val (curval.int_info)
#define RESERVE_SPACE_val (curval.int_info)
#define INSN_val (curval.arch_data)
#define PREFIX_val (curval.arch_data)
#define REG_val (curval.arch_data)
#define SEGREG_val (curval.arch_data)
#define TARGETMOD_val (curval.arch_data)
#define ID_val (curval.str_val)
#define cur_line (yasm_linemap_get_current(parser_nasm->linemap))
@ -80,7 +149,7 @@ typedef struct yasm_parser_nasm {
#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
int nasm_parser_parse(void *parser_nasm_arg);
void nasm_parser_parse(yasm_parser_nasm *parser_nasm);
void nasm_parser_cleanup(yasm_parser_nasm *parser_nasm);
int nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm);

@ -33,7 +33,6 @@ RCSID("$Id$");
#include <libyasm.h>
#include "modules/parsers/nasm/nasm-parser.h"
#include "modules/parsers/nasm/nasm-defs.h"
#define BSIZE 8192
@ -43,7 +42,8 @@ RCSID("$Id$");
#define YYMARKER (s->ptr)
#define YYFILL(n) {fill(parser_nasm, &cursor);}
#define RETURN(i) {s->cur = cursor; return i;}
#define RETURN(i) {s->cur = cursor; parser_nasm->tokch = s->tok[0]; \
return i;}
#define SCANINIT() {s->tok = cursor;}
@ -125,6 +125,15 @@ nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm)
size_t count, len;
YYCTYPE savech;
/* Handle one token of lookahead */
if (parser_nasm->peek_token != NONE) {
int tok = parser_nasm->peek_token;
*lvalp = parser_nasm->peek_tokval; /* structure copy */
parser_nasm->tokch = parser_nasm->peek_tokch;
parser_nasm->peek_token = NONE;
return tok;
}
/* Catch EOF */
if (s->eof && cursor == s->eof)
return 0;
@ -593,8 +602,6 @@ stringconst_scan:
lvalp->str.len = count;
if (parser_nasm->save_input)
cursor = save_line(parser_nasm, cursor);
if (count == 1)
RETURN(ONECHARSTR);
RETURN(STRING);
}
@ -603,8 +610,6 @@ stringconst_scan:
strbuf[count] = '\0';
lvalp->str.contents = (char *)strbuf;
lvalp->str.len = count;
if (count == 1)
RETURN(ONECHARSTR);
RETURN(STRING);
}

Loading…
Cancel
Save