diff options
Diffstat (limited to 'src/dc_parse.c')
-rw-r--r-- | src/dc_parse.c | 185 |
1 files changed, 154 insertions, 31 deletions
diff --git a/src/dc_parse.c b/src/dc_parse.c index b9b5afb6..2a6f387a 100644 --- a/src/dc_parse.c +++ b/src/dc_parse.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2018-2021 Gavin D. Howard and contributors. + * Copyright (c) 2018-2023 Gavin D. Howard and contributors. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -50,8 +50,9 @@ * @param p The parser. * @param var True if the parser is for a variable, false otherwise. */ -static void dc_parse_register(BcParse *p, bool var) { - +static void +dc_parse_register(BcParse* p, bool var) +{ bc_lex_next(&p->l); if (p->l.t != BC_LEX_NAME) bc_parse_err(p, BC_ERR_PARSE_TOKEN); @@ -62,7 +63,9 @@ static void dc_parse_register(BcParse *p, bool var) { * Parses a dc string. * @param p The parser. */ -static inline void dc_parse_string(BcParse *p) { +static inline void +dc_parse_string(BcParse* p) +{ bc_parse_addString(p); bc_lex_next(&p->l); } @@ -75,8 +78,9 @@ static inline void dc_parse_string(BcParse *p) { * a global. * @param store True if the operation is a store, false otherwise. */ -static void dc_parse_mem(BcParse *p, uchar inst, bool name, bool store) { - +static void +dc_parse_mem(BcParse* p, uchar inst, bool name, bool store) +{ // Push the instruction. bc_parse_push(p, inst); @@ -85,7 +89,8 @@ static void dc_parse_mem(BcParse *p, uchar inst, bool name, bool store) { // Stores use the bc assign infrastructure, but they need to do a swap // first. - if (store) { + if (store) + { bc_parse_push(p, BC_INST_SWAP); bc_parse_push(p, BC_INST_ASSIGN_NO_VAL); } @@ -98,8 +103,9 @@ static void dc_parse_mem(BcParse *p, uchar inst, bool name, bool store) { * @param p The parser. * @param inst The instruction for the condition. */ -static void dc_parse_cond(BcParse *p, uchar inst) { - +static void +dc_parse_cond(BcParse* p, uchar inst) +{ // Push the instruction for the condition and the conditional execution. bc_parse_push(p, inst); bc_parse_push(p, BC_INST_EXEC_COND); @@ -110,7 +116,8 @@ static void dc_parse_cond(BcParse *p, uchar inst) { bc_lex_next(&p->l); // If the next token is an else, parse the else. - if (p->l.t == BC_LEX_KW_ELSE) { + if (p->l.t == BC_LEX_KW_ELSE) + { dc_parse_register(p, true); bc_lex_next(&p->l); } @@ -124,13 +131,14 @@ static void dc_parse_cond(BcParse *p, uchar inst) { * @param t The token to parse. * @param flags The flags that say what is allowed or not. */ -static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { - +static void +dc_parse_token(BcParse* p, BcLexType t, uint8_t flags) +{ uchar inst; bool assign, get_token = false; - switch (t) { - + switch (t) + { case BC_LEX_OP_REL_EQ: case BC_LEX_OP_REL_LE: case BC_LEX_OP_REL_GE: @@ -161,16 +169,18 @@ static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { // This tells us whether or not the neg is for a command or at the // beginning of a number. If it's a command, push it. Otherwise, // fallthrough and parse the number. - if (dc_lex_negCommand(&p->l)) { + if (dc_lex_negCommand(&p->l)) + { bc_parse_push(p, BC_INST_NEG); get_token = true; break; } bc_lex_next(&p->l); + + // Fallthrough. + BC_FALLTHROUGH } - // Fallthrough. - BC_FALLTHROUGH case BC_LEX_NUMBER: { @@ -187,7 +197,9 @@ static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { { // Make sure the read is not recursive. if (BC_ERR(flags & BC_PARSE_NOREAD)) + { bc_parse_err(p, BC_ERR_EXEC_REC_READ); + } else bc_parse_push(p, BC_INST_READ); get_token = true; @@ -243,7 +255,113 @@ static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { break; } - default: + case BC_LEX_EOF: + case BC_LEX_INVALID: +#if BC_ENABLED + case BC_LEX_OP_INC: + case BC_LEX_OP_DEC: +#endif // BC_ENABLED + case BC_LEX_OP_BOOL_NOT: +#if BC_ENABLE_EXTRA_MATH + case BC_LEX_OP_TRUNC: +#endif // BC_ENABLE_EXTRA_MATH + case BC_LEX_OP_POWER: + case BC_LEX_OP_MULTIPLY: + case BC_LEX_OP_DIVIDE: + case BC_LEX_OP_MODULUS: + case BC_LEX_OP_PLUS: + case BC_LEX_OP_MINUS: +#if BC_ENABLE_EXTRA_MATH + case BC_LEX_OP_PLACES: + case BC_LEX_OP_LSHIFT: + case BC_LEX_OP_RSHIFT: +#endif // BC_ENABLE_EXTRA_MATH + case BC_LEX_OP_BOOL_OR: + case BC_LEX_OP_BOOL_AND: +#if BC_ENABLED + case BC_LEX_OP_ASSIGN_POWER: + case BC_LEX_OP_ASSIGN_MULTIPLY: + case BC_LEX_OP_ASSIGN_DIVIDE: + case BC_LEX_OP_ASSIGN_MODULUS: + case BC_LEX_OP_ASSIGN_PLUS: + case BC_LEX_OP_ASSIGN_MINUS: +#if BC_ENABLE_EXTRA_MATH + case BC_LEX_OP_ASSIGN_PLACES: + case BC_LEX_OP_ASSIGN_LSHIFT: + case BC_LEX_OP_ASSIGN_RSHIFT: +#endif // BC_ENABLE_EXTRA_MATH +#endif // BC_ENABLED + case BC_LEX_NLINE: + case BC_LEX_WHITESPACE: + case BC_LEX_LPAREN: + case BC_LEX_RPAREN: + case BC_LEX_LBRACKET: + case BC_LEX_COMMA: + case BC_LEX_RBRACKET: + case BC_LEX_LBRACE: + case BC_LEX_NAME: + case BC_LEX_RBRACE: +#if BC_ENABLED + case BC_LEX_KW_AUTO: + case BC_LEX_KW_BREAK: + case BC_LEX_KW_CONTINUE: + case BC_LEX_KW_DEFINE: + case BC_LEX_KW_FOR: + case BC_LEX_KW_IF: + case BC_LEX_KW_LIMITS: + case BC_LEX_KW_RETURN: + case BC_LEX_KW_WHILE: + case BC_LEX_KW_HALT: + case BC_LEX_KW_LAST: +#endif // BC_ENABLED + case BC_LEX_KW_IBASE: + case BC_LEX_KW_OBASE: + case BC_LEX_KW_SCALE: +#if BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_SEED: +#endif // BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_LENGTH: + case BC_LEX_KW_PRINT: + case BC_LEX_KW_SQRT: + case BC_LEX_KW_ABS: + case BC_LEX_KW_IS_NUMBER: + case BC_LEX_KW_IS_STRING: +#if BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_IRAND: +#endif // BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_ASCIIFY: + case BC_LEX_KW_MODEXP: + case BC_LEX_KW_DIVMOD: + case BC_LEX_KW_QUIT: +#if BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_RAND: +#endif // BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_MAXIBASE: + case BC_LEX_KW_MAXOBASE: + case BC_LEX_KW_MAXSCALE: +#if BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_MAXRAND: +#endif // BC_ENABLE_EXTRA_MATH + case BC_LEX_KW_LINE_LENGTH: +#if BC_ENABLED + case BC_LEX_KW_GLOBAL_STACKS: +#endif // BC_ENABLED + case BC_LEX_KW_LEADING_ZERO: + case BC_LEX_KW_STREAM: + case BC_LEX_KW_ELSE: + case BC_LEX_EXTENDED_REGISTERS: + case BC_LEX_EQ_NO_REG: + case BC_LEX_EXECUTE: + case BC_LEX_PRINT_STACK: + case BC_LEX_CLEAR_STACK: + case BC_LEX_STACK_LEVEL: + case BC_LEX_DUPLICATE: + case BC_LEX_SWAP: + case BC_LEX_POP: + case BC_LEX_PRINT_POP: + case BC_LEX_NQUIT: + case BC_LEX_EXEC_STACK_LENGTH: + case BC_LEX_SCALE_FACTOR: { // All other tokens should be taken care of by the caller, or they // actually *are* invalid. @@ -254,8 +372,9 @@ static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { if (get_token) bc_lex_next(&p->l); } -void dc_parse_expr(BcParse *p, uint8_t flags) { - +void +dc_parse_expr(BcParse* p, uint8_t flags) +{ BcInst inst; BcLexType t; bool need_expr, have_expr = false; @@ -267,10 +386,11 @@ void dc_parse_expr(BcParse *p, uint8_t flags) { // designed. // While we don't have EOF... - while ((t = p->l.t) != BC_LEX_EOF) { - + while ((t = p->l.t) != BC_LEX_EOF) + { // Eat newline. - if (t == BC_LEX_NLINE) { + if (t == BC_LEX_NLINE) + { bc_lex_next(&p->l); continue; } @@ -281,7 +401,8 @@ void dc_parse_expr(BcParse *p, uint8_t flags) { // If the instruction is invalid, that means we have to do some harder // parsing. So if not invalid, just push the instruction; otherwise, // parse the token. - if (inst != BC_INST_INVALID) { + if (inst != BC_INST_INVALID) + { bc_parse_push(p, inst); bc_lex_next(&p->l); } @@ -295,14 +416,17 @@ void dc_parse_expr(BcParse *p, uint8_t flags) { // indicate that it is executing a string. if (BC_ERR(need_expr && !have_expr)) bc_err(BC_ERR_EXEC_READ_EXPR); else if (p->l.t == BC_LEX_EOF && (flags & BC_PARSE_NOCALL)) + { bc_parse_push(p, BC_INST_POP_EXEC); + } } -void dc_parse_parse(BcParse *p) { - +void +dc_parse_parse(BcParse* p) +{ assert(p != NULL); - BC_SETJMP(exit); + BC_SETJMP_LOCKED(vm, exit); // If we have EOF, someone called this function one too many times. // Otherwise, parse. @@ -311,11 +435,10 @@ void dc_parse_parse(BcParse *p) { exit: - BC_SIG_MAYLOCK; - // Need to reset if there was an error. - if (BC_SIG_EXC) bc_parse_reset(p); + if (BC_SIG_EXC(vm)) bc_parse_reset(p); - BC_LONGJMP_CONT; + BC_LONGJMP_CONT(vm); + BC_SIG_MAYLOCK; } #endif // DC_ENABLED |