Fix #125: Improve reporting of operand and expression syntax errors.

Now instead of the generic "expression syntax error", more informative
error messages such as the following are reported:
 - unexpected `:' after instruction
 - expected expression after `%'
 - expected operand, got `%'

svn path=/trunk/yasm/; revision=2020
This commit is contained in:
Peter Johnson 2007-12-04 06:55:11 +00:00
parent 02075ed7ca
commit 4606b9506a
4 changed files with 99 additions and 15 deletions

View file

@ -133,16 +133,14 @@ demand_eol_(yasm_parser_nasm *parser_nasm)
}
#define demand_eol() demand_eol_(parser_nasm)
static int
expect_(yasm_parser_nasm *parser_nasm, int token)
static const char *
describe_token(int token)
{
static char strch[] = "` '";
const char *str;
if (curtok == token)
return 1;
switch (token) {
case 0: str = "end of line"; break;
case INTNUM: str = "integer"; break;
case FLTNUM: str = "floating point value"; break;
case DIRECTIVE_NAME: str = "directive name"; break;
@ -177,7 +175,17 @@ expect_(yasm_parser_nasm *parser_nasm, int token)
str = strch;
break;
}
yasm_error_set(YASM_ERROR_PARSE, "expected %s", str);
return str;
}
static int
expect_(yasm_parser_nasm *parser_nasm, int token)
{
if (curtok == token)
return 1;
yasm_error_set(YASM_ERROR_PARSE, "expected %s", describe_token(token));
destroy_curtok();
return 0;
}
@ -622,8 +630,14 @@ parse_instr(yasm_parser_nasm *parser_nasm)
for (;;) {
yasm_insn_operand *op = parse_operand(parser_nasm);
if (!op) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expression syntax error"));
if (insn->num_operands == 0)
yasm_error_set(YASM_ERROR_SYNTAX,
N_("unexpected %s after instruction"),
describe_token(curtok));
else
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected operand, got %s"),
describe_token(curtok));
yasm_bc_destroy(bc);
return NULL;
}
@ -838,6 +852,9 @@ parse_memaddr(yasm_parser_nasm *parser_nasm)
get_next_token(); \
f = rightfunc(parser_nasm, type); \
if (!f) { \
yasm_error_set(YASM_ERROR_SYNTAX, \
N_("expected expression after %s"), \
describe_token(op)); \
yasm_expr_destroy(e); \
return NULL; \
} \
@ -900,6 +917,9 @@ parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type)
get_next_token();
f = parse_expr4(parser_nasm, type);
if (!f) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"),
describe_token(op));
yasm_expr_destroy(e);
return NULL;
}
@ -925,6 +945,9 @@ parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type)
get_next_token();
f = parse_expr5(parser_nasm, type);
if (!f) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"),
describe_token(op));
yasm_expr_destroy(e);
return NULL;
}
@ -951,6 +974,9 @@ parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type)
get_next_token();
f = parse_expr6(parser_nasm, type);
if (!f) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"),
describe_token(op));
yasm_expr_destroy(e);
return NULL;
}
@ -978,14 +1004,20 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
case '~':
get_next_token();
e = parse_expr6(parser_nasm, type);
if (!e)
if (!e) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"), "`~'");
return NULL;
}
return p_expr_new_branch(YASM_EXPR_NOT, e);
case '(':
get_next_token();
e = parse_expr(parser_nasm, type);
if (!e)
if (!e) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"), "`('");
return NULL;
}
if (!expect(')')) {
yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
return NULL;
@ -1009,30 +1041,47 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
} else switch (curtok) {
case '+':
get_next_token();
return parse_expr6(parser_nasm, type);
e = parse_expr6(parser_nasm, type);
if (!e) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"), "`+'");
}
return e;
case '-':
get_next_token();
e = parse_expr6(parser_nasm, type);
if (!e)
if (!e) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"), "`-'");
return NULL;
}
return p_expr_new_branch(YASM_EXPR_NEG, e);
case '~':
get_next_token();
e = parse_expr6(parser_nasm, type);
if (!e)
if (!e) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"), "`~'");
return NULL;
}
return p_expr_new_branch(YASM_EXPR_NOT, e);
case SEG:
get_next_token();
e = parse_expr6(parser_nasm, type);
if (!e)
if (!e) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"), "SEG");
return NULL;
}
return p_expr_new_branch(YASM_EXPR_SEG, e);
case '(':
get_next_token();
e = parse_expr(parser_nasm, type);
if (!e)
if (!e) {
yasm_error_set(YASM_ERROR_SYNTAX,
N_("expected expression after %s"), "`('");
return NULL;
}
if (!expect(')')) {
yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
return NULL;

View file

@ -30,6 +30,8 @@ EXTRA_DIST += modules/parsers/nasm/tests/strucalign.asm
EXTRA_DIST += modules/parsers/nasm/tests/strucalign.hex
EXTRA_DIST += modules/parsers/nasm/tests/struczero.asm
EXTRA_DIST += modules/parsers/nasm/tests/struczero.hex
EXTRA_DIST += modules/parsers/nasm/tests/syntax-err.asm
EXTRA_DIST += modules/parsers/nasm/tests/syntax-err.errwarn
EXTRA_DIST += modules/parsers/nasm/tests/worphan/Makefile.inc

View file

@ -0,0 +1,17 @@
global crc32
crc32: resd 1
cli:
mov ax, 5%
mov ax, %
mov ax, ~
mov ax, +
mov ax, -
mov ax, (
mov ax, )
ret 5%
ret %
ret ~
ret +
ret -
ret (
ret )

View file

@ -0,0 +1,16 @@
-:2: error: unexpected `:' after instruction
-:3: error: unexpected `:' after instruction
-:4: error: expected expression after `%'
-:5: error: expected operand, got `%'
-:6: error: expected expression after `~'
-:7: error: expected expression after `+'
-:8: error: expected expression after `-'
-:9: error: expected expression after `('
-:10: error: expected operand, got `)'
-:11: error: expected expression after `%'
-:12: error: unexpected `%' after instruction
-:13: error: expected expression after `~'
-:14: error: expected expression after `+'
-:15: error: expected expression after `-'
-:16: error: expected expression after `('
-:17: error: unexpected `)' after instruction