bc: upstream fixes
function old new delta bc_parse_expr_empty_ok 1764 1843 +79 bc_error_at - 62 +62 bc_parse_inst_isLeaf - 30 +30 zbc_func_insert 100 120 +20 bc_error_bad_function_definition - 10 +10 bc_error_bad_assignment - 10 +10 zxc_lex_next 1608 1614 +6 ok_in_expr 30 - -30 zxc_vm_process 874 839 -35 ------------------------------------------------------------------------------ (add/remove: 4/1 grow/shrink: 3/1 up/down: 217/-65) Total: 152 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
ff65355b8a
commit
2231468a2f
177
miscutils/bc.c
177
miscutils/bc.c
@ -971,19 +971,42 @@ static ERRORFUNC int bc_error(const char *msg)
|
|||||||
{
|
{
|
||||||
IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg);
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg);
|
||||||
}
|
}
|
||||||
|
static ERRORFUNC int bc_error_at(const char *msg)
|
||||||
|
{
|
||||||
|
const char *err_at = G.prs.lex_next_at;
|
||||||
|
if (err_at) {
|
||||||
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt(
|
||||||
|
"%s at '%.*s'",
|
||||||
|
msg,
|
||||||
|
(int)(strchrnul(err_at, '\n') - err_at),
|
||||||
|
err_at
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg);
|
||||||
|
}
|
||||||
static ERRORFUNC int bc_error_bad_character(char c)
|
static ERRORFUNC int bc_error_bad_character(char c)
|
||||||
{
|
{
|
||||||
if (!c)
|
if (!c)
|
||||||
IF_ERROR_RETURN_POSSIBLE(return) bc_error("NUL character");
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error("NUL character");
|
||||||
IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("bad character '%c'", c);
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("bad character '%c'", c);
|
||||||
}
|
}
|
||||||
|
static ERRORFUNC int bc_error_bad_function_definition(void)
|
||||||
|
{
|
||||||
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad function definition");
|
||||||
|
}
|
||||||
static ERRORFUNC int bc_error_bad_expression(void)
|
static ERRORFUNC int bc_error_bad_expression(void)
|
||||||
{
|
{
|
||||||
IF_ERROR_RETURN_POSSIBLE(return) bc_error("bad expression");
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad expression");
|
||||||
|
}
|
||||||
|
static ERRORFUNC int bc_error_bad_assignment(void)
|
||||||
|
{
|
||||||
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_at(
|
||||||
|
"bad assignment: left side must be variable or array element"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
static ERRORFUNC int bc_error_bad_token(void)
|
static ERRORFUNC int bc_error_bad_token(void)
|
||||||
{
|
{
|
||||||
IF_ERROR_RETURN_POSSIBLE(return) bc_error("bad token");
|
IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad token");
|
||||||
}
|
}
|
||||||
static ERRORFUNC int bc_error_stack_has_too_few_elements(void)
|
static ERRORFUNC int bc_error_stack_has_too_few_elements(void)
|
||||||
{
|
{
|
||||||
@ -2853,6 +2876,7 @@ static BC_STATUS zxc_lex_number(char last)
|
|||||||
if (c == '\\' && p->lex_inbuf[1] == '\n') {
|
if (c == '\\' && p->lex_inbuf[1] == '\n') {
|
||||||
p->lex_inbuf += 2;
|
p->lex_inbuf += 2;
|
||||||
p->lex_line++;
|
p->lex_line++;
|
||||||
|
dbg_lex("++p->lex_line=%zd", p->lex_line);
|
||||||
c = peek_inbuf(); // force next line to be read
|
c = peek_inbuf(); // force next line to be read
|
||||||
goto check_c;
|
goto check_c;
|
||||||
}
|
}
|
||||||
@ -2919,6 +2943,7 @@ static BC_STATUS zxc_lex_next(void)
|
|||||||
BcParse *p = &G.prs;
|
BcParse *p = &G.prs;
|
||||||
BcStatus s;
|
BcStatus s;
|
||||||
|
|
||||||
|
G.err_line = p->lex_line;
|
||||||
p->lex_last = p->lex;
|
p->lex_last = p->lex;
|
||||||
//why?
|
//why?
|
||||||
// if (p->lex_last == XC_LEX_EOF)
|
// if (p->lex_last == XC_LEX_EOF)
|
||||||
@ -3031,8 +3056,10 @@ static BC_STATUS zbc_lex_string(void)
|
|||||||
}
|
}
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
break;
|
break;
|
||||||
if (c == '\n')
|
if (c == '\n') {
|
||||||
p->lex_line++;
|
p->lex_line++;
|
||||||
|
dbg_lex("++p->lex_line=%zd", p->lex_line);
|
||||||
|
}
|
||||||
bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf);
|
bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf);
|
||||||
p->lex_inbuf++;
|
p->lex_inbuf++;
|
||||||
}
|
}
|
||||||
@ -3079,8 +3106,10 @@ static BC_STATUS zbc_lex_comment(void)
|
|||||||
if (c == '\0') {
|
if (c == '\0') {
|
||||||
RETURN_STATUS(bc_error("unterminated comment"));
|
RETURN_STATUS(bc_error("unterminated comment"));
|
||||||
}
|
}
|
||||||
if (c == '\n')
|
if (c == '\n') {
|
||||||
p->lex_line++;
|
p->lex_line++;
|
||||||
|
dbg_lex("++p->lex_line=%zd", p->lex_line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p->lex_inbuf++; // skip trailing '/'
|
p->lex_inbuf++; // skip trailing '/'
|
||||||
|
|
||||||
@ -3105,6 +3134,7 @@ static BC_STATUS zbc_lex_token(void)
|
|||||||
// break;
|
// break;
|
||||||
case '\n':
|
case '\n':
|
||||||
p->lex_line++;
|
p->lex_line++;
|
||||||
|
dbg_lex("++p->lex_line=%zd", p->lex_line);
|
||||||
p->lex = XC_LEX_NLINE;
|
p->lex = XC_LEX_NLINE;
|
||||||
break;
|
break;
|
||||||
case '\t':
|
case '\t':
|
||||||
@ -3341,8 +3371,10 @@ static BC_STATUS zdc_lex_string(void)
|
|||||||
if (c == ']')
|
if (c == ']')
|
||||||
if (--depth == 0)
|
if (--depth == 0)
|
||||||
break;
|
break;
|
||||||
if (c == '\n')
|
if (c == '\n') {
|
||||||
p->lex_line++;
|
p->lex_line++;
|
||||||
|
dbg_lex("++p->lex_line=%zd", p->lex_line);
|
||||||
|
}
|
||||||
bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf);
|
bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf);
|
||||||
p->lex_inbuf++;
|
p->lex_inbuf++;
|
||||||
}
|
}
|
||||||
@ -3399,6 +3431,7 @@ static BC_STATUS zdc_lex_token(void)
|
|||||||
// IOW: typing "1p<enter>" should print "1" _at once_,
|
// IOW: typing "1p<enter>" should print "1" _at once_,
|
||||||
// not after some more input.
|
// not after some more input.
|
||||||
p->lex_line++;
|
p->lex_line++;
|
||||||
|
dbg_lex("++p->lex_line=%zd", p->lex_line);
|
||||||
p->lex = XC_LEX_NLINE;
|
p->lex = XC_LEX_NLINE;
|
||||||
break;
|
break;
|
||||||
case '\t':
|
case '\t':
|
||||||
@ -3960,8 +3993,7 @@ static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags)
|
|||||||
}
|
}
|
||||||
#define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS)
|
#define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS)
|
||||||
|
|
||||||
static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr,
|
static BC_STATUS zbc_parse_incdec(BcInst *prev, size_t *nexs, uint8_t flags)
|
||||||
size_t *nexprs, uint8_t flags)
|
|
||||||
{
|
{
|
||||||
BcParse *p = &G.prs;
|
BcParse *p = &G.prs;
|
||||||
BcStatus s;
|
BcStatus s;
|
||||||
@ -3978,7 +4010,6 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr,
|
|||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
} else {
|
} else {
|
||||||
*prev = inst = BC_INST_INC_PRE + (p->lex != BC_LEX_OP_INC);
|
*prev = inst = BC_INST_INC_PRE + (p->lex != BC_LEX_OP_INC);
|
||||||
*paren_expr = true;
|
|
||||||
|
|
||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
if (s) RETURN_STATUS(s);
|
if (s) RETURN_STATUS(s);
|
||||||
@ -3986,7 +4017,7 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr,
|
|||||||
|
|
||||||
// Because we parse the next part of the expression
|
// Because we parse the next part of the expression
|
||||||
// right here, we need to increment this.
|
// right here, we need to increment this.
|
||||||
*nexprs = *nexprs + 1;
|
*nexs = *nexs + 1;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XC_LEX_NAME:
|
case XC_LEX_NAME:
|
||||||
@ -4018,36 +4049,27 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr,
|
|||||||
}
|
}
|
||||||
#define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__) COMMA_SUCCESS)
|
#define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__) COMMA_SUCCESS)
|
||||||
|
|
||||||
#if 0
|
static int bc_parse_inst_isLeaf(BcInst p)
|
||||||
#define BC_PARSE_LEAF(p, rparen) \
|
|
||||||
((rparen) \
|
|
||||||
|| ((p) >= XC_INST_NUM && (p) <= XC_INST_SQRT) \
|
|
||||||
|| (p) == BC_INST_INC_POST \
|
|
||||||
|| (p) == BC_INST_DEC_POST \
|
|
||||||
)
|
|
||||||
#else
|
|
||||||
static int ok_in_expr(BcInst p)
|
|
||||||
{
|
{
|
||||||
return (p >= XC_INST_NUM && p <= XC_INST_SQRT)
|
return (p >= XC_INST_NUM && p <= XC_INST_SQRT)
|
||||||
|| p == BC_INST_INC_POST
|
|| p == BC_INST_INC_POST
|
||||||
|| p == BC_INST_DEC_POST
|
|| p == BC_INST_DEC_POST
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
#define BC_PARSE_LEAF(p, rparen) ((rparen) || ok_in_expr(p))
|
#define BC_PARSE_LEAF(prev, bin_last, rparen) \
|
||||||
#endif
|
(!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
|
||||||
|
|
||||||
static BC_STATUS zbc_parse_minus(BcInst *prev, size_t ops_bgn,
|
static BC_STATUS zbc_parse_minus(BcInst *prev, size_t ops_bgn,
|
||||||
bool rparen, size_t *nexprs)
|
bool rparen, bool bin_last, size_t *nexprs)
|
||||||
{
|
{
|
||||||
BcParse *p = &G.prs;
|
BcParse *p = &G.prs;
|
||||||
BcStatus s;
|
BcStatus s;
|
||||||
BcLexType type;
|
BcLexType type;
|
||||||
BcInst etype = *prev;
|
|
||||||
|
|
||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
if (s) RETURN_STATUS(s);
|
if (s) RETURN_STATUS(s);
|
||||||
|
|
||||||
type = BC_PARSE_LEAF(etype, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG;
|
type = BC_PARSE_LEAF(*prev, bin_last, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG;
|
||||||
*prev = BC_TOKEN_2_INST(type);
|
*prev = BC_TOKEN_2_INST(type);
|
||||||
|
|
||||||
// We can just push onto the op stack because this is the largest
|
// We can just push onto the op stack because this is the largest
|
||||||
@ -4334,9 +4356,12 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var)
|
|||||||
|
|
||||||
autoid = (void*)f->autos.v;
|
autoid = (void*)f->autos.v;
|
||||||
for (i = 0; i < f->autos.len; i++, autoid++) {
|
for (i = 0; i < f->autos.len; i++, autoid++) {
|
||||||
if (strcmp(name, autoid->name) == 0)
|
if (strcmp(name, autoid->name) == 0
|
||||||
|
&& var == autoid->idx
|
||||||
|
) {
|
||||||
RETURN_STATUS(bc_error("duplicate function parameter or auto name"));
|
RETURN_STATUS(bc_error("duplicate function parameter or auto name"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
a.idx = var;
|
a.idx = var;
|
||||||
a.name = name;
|
a.name = name;
|
||||||
@ -4358,7 +4383,7 @@ static BC_STATUS zbc_parse_funcdef(void)
|
|||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
if (s) RETURN_STATUS(s);
|
if (s) RETURN_STATUS(s);
|
||||||
if (p->lex != XC_LEX_NAME)
|
if (p->lex != XC_LEX_NAME)
|
||||||
RETURN_STATUS(bc_error("bad function definition"));
|
RETURN_STATUS(bc_error_bad_function_definition());
|
||||||
|
|
||||||
name = xstrdup(p->lex_strnumbuf.v);
|
name = xstrdup(p->lex_strnumbuf.v);
|
||||||
p->fidx = bc_program_addFunc(name);
|
p->fidx = bc_program_addFunc(name);
|
||||||
@ -4367,13 +4392,13 @@ static BC_STATUS zbc_parse_funcdef(void)
|
|||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
if (s) RETURN_STATUS(s);
|
if (s) RETURN_STATUS(s);
|
||||||
if (p->lex != BC_LEX_LPAREN)
|
if (p->lex != BC_LEX_LPAREN)
|
||||||
RETURN_STATUS(bc_error("bad function definition"));
|
RETURN_STATUS(bc_error_bad_function_definition());
|
||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
if (s) RETURN_STATUS(s);
|
if (s) RETURN_STATUS(s);
|
||||||
|
|
||||||
while (p->lex != BC_LEX_RPAREN) {
|
while (p->lex != BC_LEX_RPAREN) {
|
||||||
if (p->lex != XC_LEX_NAME)
|
if (p->lex != XC_LEX_NAME)
|
||||||
RETURN_STATUS(bc_error("bad function definition"));
|
RETURN_STATUS(bc_error_bad_function_definition());
|
||||||
|
|
||||||
++p->func->nparams;
|
++p->func->nparams;
|
||||||
|
|
||||||
@ -4388,7 +4413,7 @@ static BC_STATUS zbc_parse_funcdef(void)
|
|||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
|
|
||||||
if (p->lex != BC_LEX_RBRACKET) {
|
if (p->lex != BC_LEX_RBRACKET) {
|
||||||
s = bc_error("bad function definition");
|
s = bc_error_bad_function_definition();
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4406,7 +4431,7 @@ static BC_STATUS zbc_parse_funcdef(void)
|
|||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comma) RETURN_STATUS(bc_error("bad function definition"));
|
if (comma) RETURN_STATUS(bc_error_bad_function_definition());
|
||||||
|
|
||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
if (s) RETURN_STATUS(s);
|
if (s) RETURN_STATUS(s);
|
||||||
@ -4457,7 +4482,7 @@ static BC_STATUS zbc_parse_auto(void)
|
|||||||
bool var;
|
bool var;
|
||||||
|
|
||||||
if (p->lex != XC_LEX_NAME)
|
if (p->lex != XC_LEX_NAME)
|
||||||
RETURN_STATUS(bc_error("bad 'auto' syntax"));
|
RETURN_STATUS(bc_error_at("bad 'auto' syntax"));
|
||||||
|
|
||||||
name = xstrdup(p->lex_strnumbuf.v);
|
name = xstrdup(p->lex_strnumbuf.v);
|
||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
@ -4469,7 +4494,7 @@ static BC_STATUS zbc_parse_auto(void)
|
|||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
|
|
||||||
if (p->lex != BC_LEX_RBRACKET) {
|
if (p->lex != BC_LEX_RBRACKET) {
|
||||||
s = bc_error("bad 'auto' syntax");
|
s = bc_error_at("bad 'auto' syntax");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
s = zxc_lex_next();
|
s = zxc_lex_next();
|
||||||
@ -4486,7 +4511,7 @@ static BC_STATUS zbc_parse_auto(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (p->lex != BC_LEX_COMMA)
|
if (p->lex != BC_LEX_COMMA)
|
||||||
RETURN_STATUS(bc_error("bad 'auto' syntax"));
|
RETURN_STATUS(bc_error_at("bad 'auto' syntax"));
|
||||||
s = zxc_lex_next(); // skip comma
|
s = zxc_lex_next(); // skip comma
|
||||||
if (s) RETURN_STATUS(s);
|
if (s) RETURN_STATUS(s);
|
||||||
}
|
}
|
||||||
@ -4643,12 +4668,12 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags)
|
|||||||
BcInst prev = XC_INST_PRINT;
|
BcInst prev = XC_INST_PRINT;
|
||||||
size_t nexprs = 0, ops_bgn = p->ops.len;
|
size_t nexprs = 0, ops_bgn = p->ops.len;
|
||||||
unsigned nparens, nrelops;
|
unsigned nparens, nrelops;
|
||||||
bool paren_first, paren_expr, rprn, assign, bin_last;
|
bool paren_first, rprn, assign, bin_last, incdec;
|
||||||
|
|
||||||
dbg_lex_enter("%s:%d entered", __func__, __LINE__);
|
dbg_lex_enter("%s:%d entered", __func__, __LINE__);
|
||||||
paren_first = (p->lex == BC_LEX_LPAREN);
|
paren_first = (p->lex == BC_LEX_LPAREN);
|
||||||
nparens = nrelops = 0;
|
nparens = nrelops = 0;
|
||||||
paren_expr = rprn = assign = false;
|
rprn = assign = incdec = false;
|
||||||
bin_last = true;
|
bin_last = true;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -4666,16 +4691,19 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags)
|
|||||||
case BC_LEX_OP_INC:
|
case BC_LEX_OP_INC:
|
||||||
case BC_LEX_OP_DEC:
|
case BC_LEX_OP_DEC:
|
||||||
dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__);
|
||||||
s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags);
|
if (incdec) return bc_error_bad_assignment();
|
||||||
|
s = zbc_parse_incdec(&prev, &nexprs, flags);
|
||||||
|
incdec = true;
|
||||||
rprn = bin_last = false;
|
rprn = bin_last = false;
|
||||||
//get_token = false; - already is
|
//get_token = false; - already is
|
||||||
break;
|
break;
|
||||||
case XC_LEX_OP_MINUS:
|
case XC_LEX_OP_MINUS:
|
||||||
dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__);
|
||||||
s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs);
|
s = zbc_parse_minus(&prev, ops_bgn, rprn, bin_last, &nexprs);
|
||||||
rprn = false;
|
rprn = false;
|
||||||
//get_token = false; - already is
|
//get_token = false; - already is
|
||||||
bin_last = (prev == XC_INST_MINUS);
|
bin_last = (prev == XC_INST_MINUS);
|
||||||
|
if (bin_last) incdec = false;
|
||||||
break;
|
break;
|
||||||
case BC_LEX_OP_ASSIGN_POWER:
|
case BC_LEX_OP_ASSIGN_POWER:
|
||||||
case BC_LEX_OP_ASSIGN_MULTIPLY:
|
case BC_LEX_OP_ASSIGN_MULTIPLY:
|
||||||
@ -4689,10 +4717,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags)
|
|||||||
&& prev != XC_INST_SCALE && prev != XC_INST_IBASE
|
&& prev != XC_INST_SCALE && prev != XC_INST_IBASE
|
||||||
&& prev != XC_INST_OBASE && prev != BC_INST_LAST
|
&& prev != XC_INST_OBASE && prev != BC_INST_LAST
|
||||||
) {
|
) {
|
||||||
return bc_error("bad assignment:"
|
return bc_error_bad_assignment();
|
||||||
" left side must be variable"
|
|
||||||
" or array element"
|
|
||||||
); // note: shared string
|
|
||||||
}
|
}
|
||||||
// Fallthrough.
|
// Fallthrough.
|
||||||
case XC_LEX_OP_POWER:
|
case XC_LEX_OP_POWER:
|
||||||
@ -4710,64 +4735,63 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags)
|
|||||||
case BC_LEX_OP_BOOL_OR:
|
case BC_LEX_OP_BOOL_OR:
|
||||||
case BC_LEX_OP_BOOL_AND:
|
case BC_LEX_OP_BOOL_AND:
|
||||||
dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__);
|
||||||
if (((t == BC_LEX_OP_BOOL_NOT) != bin_last)
|
if (t == BC_LEX_OP_BOOL_NOT) {
|
||||||
|| (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT)
|
if (!bin_last && p->lex_last != BC_LEX_OP_BOOL_NOT)
|
||||||
) {
|
return bc_error_bad_expression();
|
||||||
|
} else if (prev == XC_INST_BOOL_NOT) {
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
}
|
}
|
||||||
|
|
||||||
nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT);
|
nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT);
|
||||||
prev = BC_TOKEN_2_INST(t);
|
prev = BC_TOKEN_2_INST(t);
|
||||||
bc_parse_operator(t, ops_bgn, &nexprs);
|
bc_parse_operator(t, ops_bgn, &nexprs);
|
||||||
s = zxc_lex_next();
|
rprn = incdec = false;
|
||||||
rprn = false;
|
get_token = true;
|
||||||
//get_token = false; - already is
|
|
||||||
bin_last = (t != BC_LEX_OP_BOOL_NOT);
|
bin_last = (t != BC_LEX_OP_BOOL_NOT);
|
||||||
break;
|
break;
|
||||||
case BC_LEX_LPAREN:
|
case BC_LEX_LPAREN:
|
||||||
dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__);
|
||||||
if (BC_PARSE_LEAF(prev, rprn))
|
if (BC_PARSE_LEAF(prev, bin_last, rprn))
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
bc_vec_push(&p->ops, &t);
|
bc_vec_push(&p->ops, &t);
|
||||||
nparens++;
|
nparens++;
|
||||||
get_token = true;
|
get_token = true;
|
||||||
paren_expr = false;
|
rprn = incdec = false;
|
||||||
rprn = bin_last = false;
|
|
||||||
break;
|
break;
|
||||||
case BC_LEX_RPAREN:
|
case BC_LEX_RPAREN:
|
||||||
dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__);
|
||||||
|
if (p->lex_last == BC_LEX_LPAREN) {
|
||||||
|
dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__);
|
||||||
|
return BC_STATUS_PARSE_EMPTY_EXP;
|
||||||
|
}
|
||||||
if (bin_last || prev == XC_INST_BOOL_NOT)
|
if (bin_last || prev == XC_INST_BOOL_NOT)
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
if (nparens == 0) {
|
if (nparens == 0) {
|
||||||
goto exit_loop;
|
goto exit_loop;
|
||||||
}
|
}
|
||||||
if (!paren_expr) {
|
|
||||||
dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__);
|
|
||||||
return BC_STATUS_PARSE_EMPTY_EXP;
|
|
||||||
}
|
|
||||||
s = zbc_parse_rightParen(ops_bgn, &nexprs);
|
s = zbc_parse_rightParen(ops_bgn, &nexprs);
|
||||||
nparens--;
|
nparens--;
|
||||||
get_token = true;
|
get_token = true;
|
||||||
paren_expr = rprn = true;
|
rprn = true;
|
||||||
bin_last = false;
|
bin_last = incdec = false;
|
||||||
break;
|
break;
|
||||||
case XC_LEX_NAME:
|
case XC_LEX_NAME:
|
||||||
dbg_lex("%s:%d LEX_NAME", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_NAME", __func__, __LINE__);
|
||||||
if (BC_PARSE_LEAF(prev, rprn))
|
if (BC_PARSE_LEAF(prev, bin_last, rprn))
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL);
|
s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL);
|
||||||
paren_expr = true;
|
rprn = (prev == BC_INST_CALL);
|
||||||
rprn = bin_last = false;
|
bin_last = false;
|
||||||
//get_token = false; - already is
|
//get_token = false; - already is
|
||||||
nexprs++;
|
nexprs++;
|
||||||
break;
|
break;
|
||||||
case XC_LEX_NUMBER:
|
case XC_LEX_NUMBER:
|
||||||
dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
|
||||||
if (BC_PARSE_LEAF(prev, rprn))
|
if (BC_PARSE_LEAF(prev, bin_last, rprn))
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
xc_parse_pushNUM();
|
xc_parse_pushNUM();
|
||||||
prev = XC_INST_NUM;
|
prev = XC_INST_NUM;
|
||||||
get_token = true;
|
get_token = true;
|
||||||
paren_expr = true;
|
|
||||||
rprn = bin_last = false;
|
rprn = bin_last = false;
|
||||||
nexprs++;
|
nexprs++;
|
||||||
break;
|
break;
|
||||||
@ -4775,45 +4799,40 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags)
|
|||||||
case BC_LEX_KEY_LAST:
|
case BC_LEX_KEY_LAST:
|
||||||
case BC_LEX_KEY_OBASE:
|
case BC_LEX_KEY_OBASE:
|
||||||
dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__);
|
||||||
if (BC_PARSE_LEAF(prev, rprn))
|
if (BC_PARSE_LEAF(prev, bin_last, rprn))
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE);
|
prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE);
|
||||||
xc_parse_push((char) prev);
|
xc_parse_push((char) prev);
|
||||||
get_token = true;
|
get_token = true;
|
||||||
paren_expr = true;
|
|
||||||
rprn = bin_last = false;
|
rprn = bin_last = false;
|
||||||
nexprs++;
|
nexprs++;
|
||||||
break;
|
break;
|
||||||
case BC_LEX_KEY_LENGTH:
|
case BC_LEX_KEY_LENGTH:
|
||||||
case BC_LEX_KEY_SQRT:
|
case BC_LEX_KEY_SQRT:
|
||||||
dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__);
|
||||||
if (BC_PARSE_LEAF(prev, rprn))
|
if (BC_PARSE_LEAF(prev, bin_last, rprn))
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
s = zbc_parse_builtin(t, flags, &prev);
|
s = zbc_parse_builtin(t, flags, &prev);
|
||||||
get_token = true;
|
get_token = true;
|
||||||
paren_expr = true;
|
rprn = bin_last = incdec = false;
|
||||||
rprn = bin_last = false;
|
|
||||||
nexprs++;
|
nexprs++;
|
||||||
break;
|
break;
|
||||||
case BC_LEX_KEY_READ:
|
case BC_LEX_KEY_READ:
|
||||||
dbg_lex("%s:%d LEX_READ", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_READ", __func__, __LINE__);
|
||||||
if (BC_PARSE_LEAF(prev, rprn))
|
if (BC_PARSE_LEAF(prev, bin_last, rprn))
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
s = zbc_parse_read();
|
s = zbc_parse_read();
|
||||||
prev = XC_INST_READ;
|
prev = XC_INST_READ;
|
||||||
get_token = true;
|
get_token = true;
|
||||||
paren_expr = true;
|
rprn = bin_last = incdec = false;
|
||||||
rprn = bin_last = false;
|
|
||||||
nexprs++;
|
nexprs++;
|
||||||
break;
|
break;
|
||||||
case BC_LEX_KEY_SCALE:
|
case BC_LEX_KEY_SCALE:
|
||||||
dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__);
|
dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__);
|
||||||
if (BC_PARSE_LEAF(prev, rprn))
|
if (BC_PARSE_LEAF(prev, bin_last, rprn))
|
||||||
return bc_error_bad_expression();
|
return bc_error_bad_expression();
|
||||||
s = zbc_parse_scale(&prev, flags);
|
s = zbc_parse_scale(&prev, flags);
|
||||||
prev = XC_INST_SCALE;
|
|
||||||
//get_token = false; - already is
|
//get_token = false; - already is
|
||||||
paren_expr = true;
|
|
||||||
rprn = bin_last = false;
|
rprn = bin_last = false;
|
||||||
nexprs++;
|
nexprs++;
|
||||||
break;
|
break;
|
||||||
@ -5286,7 +5305,7 @@ static BC_STATUS zxc_program_read(void)
|
|||||||
}
|
}
|
||||||
if (s) goto exec_err;
|
if (s) goto exec_err;
|
||||||
if (G.prs.lex != XC_LEX_NLINE && G.prs.lex != XC_LEX_EOF) {
|
if (G.prs.lex != XC_LEX_NLINE && G.prs.lex != XC_LEX_EOF) {
|
||||||
s = bc_error("bad read() expression");
|
s = bc_error_at("bad read() expression");
|
||||||
goto exec_err;
|
goto exec_err;
|
||||||
}
|
}
|
||||||
xc_parse_push(XC_INST_RET);
|
xc_parse_push(XC_INST_RET);
|
||||||
@ -5794,10 +5813,7 @@ static BC_STATUS zxc_program_assign(char inst)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (left->t == XC_RESULT_CONSTANT || left->t == XC_RESULT_TEMP)
|
if (left->t == XC_RESULT_CONSTANT || left->t == XC_RESULT_TEMP)
|
||||||
RETURN_STATUS(bc_error("bad assignment:"
|
RETURN_STATUS(bc_error_bad_assignment());
|
||||||
" left side must be variable"
|
|
||||||
" or array element"
|
|
||||||
)); // note: shared string
|
|
||||||
|
|
||||||
#if ENABLE_BC
|
#if ENABLE_BC
|
||||||
if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero))
|
if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero))
|
||||||
@ -6771,13 +6787,7 @@ static BC_STATUS zxc_vm_process(const char *text)
|
|||||||
&& G.prs.lex != XC_LEX_NLINE
|
&& G.prs.lex != XC_LEX_NLINE
|
||||||
&& G.prs.lex != XC_LEX_EOF
|
&& G.prs.lex != XC_LEX_EOF
|
||||||
) {
|
) {
|
||||||
const char *err_at;
|
bc_error_at("bad statement terminator");
|
||||||
//TODO: commonalize for other parse errors:
|
|
||||||
err_at = G.prs.lex_next_at ? G.prs.lex_next_at : "UNKNOWN";
|
|
||||||
bc_error_fmt("bad statement terminator at '%.*s'",
|
|
||||||
(int)(strchrnul(err_at, '\n') - err_at),
|
|
||||||
err_at
|
|
||||||
);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
// The above logic is fragile. Check these examples:
|
// The above logic is fragile. Check these examples:
|
||||||
@ -6871,6 +6881,7 @@ static BC_STATUS zxc_vm_execute_FILE(FILE *fp, const char *filename)
|
|||||||
G.prs.lex_filename = filename;
|
G.prs.lex_filename = filename;
|
||||||
G.prs.lex_input_fp = fp;
|
G.prs.lex_input_fp = fp;
|
||||||
G.err_line = G.prs.lex_line = 1;
|
G.err_line = G.prs.lex_line = 1;
|
||||||
|
dbg_lex("p->lex_line reset to 1");
|
||||||
|
|
||||||
do {
|
do {
|
||||||
s = zxc_vm_process("");
|
s = zxc_vm_process("");
|
||||||
|
@ -108,6 +108,11 @@ testing "bc define auto" \
|
|||||||
"8\n9\n" \
|
"8\n9\n" \
|
||||||
"" "define w() { auto z; return 8; }; w(); 9"
|
"" "define w() { auto z; return 8; }; w(); 9"
|
||||||
|
|
||||||
|
testing "bc define auto array same name" \
|
||||||
|
"bc" \
|
||||||
|
"8\n9\n" \
|
||||||
|
"" "define w(x) { auto x[]; return x; }; w(8); 9"
|
||||||
|
|
||||||
testing "bc define with body on next line" \
|
testing "bc define with body on next line" \
|
||||||
"bc" \
|
"bc" \
|
||||||
"8\n9\n" \
|
"8\n9\n" \
|
||||||
@ -133,6 +138,17 @@ testing "bc ifz does not match if keyword" \
|
|||||||
"1\n2\n2\n3\n" \
|
"1\n2\n2\n3\n" \
|
||||||
"" "ifz=1;ifz\n++ifz;ifz++\nifz"
|
"" "ifz=1;ifz\n++ifz;ifz++\nifz"
|
||||||
|
|
||||||
|
# had parse error on "f()-N"
|
||||||
|
testing "bc -l 'e(0)-2'" \
|
||||||
|
"bc -l" \
|
||||||
|
"-1.00000000000000000000\n" \
|
||||||
|
"" "e(0)-2"
|
||||||
|
|
||||||
|
testing "bc (!a&&b)" \
|
||||||
|
"bc" \
|
||||||
|
"0\n" \
|
||||||
|
"" "(!a&&b)"
|
||||||
|
|
||||||
testing "bc print 1,2,3" \
|
testing "bc print 1,2,3" \
|
||||||
"bc" \
|
"bc" \
|
||||||
"123" \
|
"123" \
|
||||||
|
Loading…
Reference in New Issue
Block a user