/*1* *****************************************************************************2*3* SPDX-License-Identifier: BSD-2-Clause4*5* Copyright (c) 2018-2025 Gavin D. Howard and contributors.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions are met:9*10* * Redistributions of source code must retain the above copyright notice, this11* list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright notice,14* this list of conditions and the following disclaimer in the documentation15* and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"18* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE21* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS24* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN25* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)26* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE27* POSSIBILITY OF SUCH DAMAGE.28*29* *****************************************************************************30*31* The parser for bc.32*33*/3435#if BC_ENABLED3637#include <assert.h>38#include <stdbool.h>39#include <stdlib.h>40#include <string.h>4142#include <setjmp.h>4344#include <bc.h>45#include <num.h>46#include <vm.h>4748// Before you embark on trying to understand this code, have you read the49// Development manual (manuals/development.md) and the comment in include/bc.h50// yet? No? Do that first. I'm serious.51//52// The reason is because this file holds the most sensitive and finicky code in53// the entire codebase. Even getting history to work on Windows was nothing54// compared to this. This is where dreams go to die, where dragons live, and55// from which Ken Thompson himself would flee.5657static void58bc_parse_else(BcParse* p);5960static void61bc_parse_stmt(BcParse* p);6263static BcParseStatus64bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next);6566static void67bc_parse_expr_status(BcParse* p, uint8_t flags, BcParseNext next);6869/**70* Returns true if an instruction could only have come from a "leaf" expression.71* For more on what leaf expressions are, read the comment for BC_PARSE_LEAF().72* @param t The instruction to test.73* @return True if the instruction is a from a leaf expression.74*/75static bool76bc_parse_inst_isLeaf(BcInst t)77{78return (t >= BC_INST_NUM && t <= BC_INST_LEADING_ZERO) ||79#if BC_ENABLE_EXTRA_MATH80t == BC_INST_TRUNC ||81#endif // BC_ENABLE_EXTRA_MATH82t <= BC_INST_DEC;83}8485/**86* Returns true if the *previous* token was a delimiter. A delimiter is anything87* that can legally end a statement. In bc's case, it could be a newline, a88* semicolon, and a brace in certain cases.89* @param p The parser.90* @return True if the token is a legal delimiter.91*/92static bool93bc_parse_isDelimiter(const BcParse* p)94{95BcLexType t = p->l.t;96bool good;9798// If it's an obvious delimiter, say so.99if (BC_PARSE_DELIMITER(t)) return true;100101good = false;102103// If the current token is a keyword, then...beware. That means that we need104// to check for a "dangling" else, where there was no brace-delimited block105// on the previous if.106if (t == BC_LEX_KW_ELSE)107{108size_t i;109uint16_t *fptr = NULL, flags = BC_PARSE_FLAG_ELSE;110111// As long as going up the stack is valid for a dangling else, keep on.112for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i)113{114fptr = bc_vec_item_rev(&p->flags, i);115flags = *fptr;116117// If we need a brace and don't have one, then we don't have a118// delimiter.119if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE)120{121return false;122}123}124125// Oh, and we had also better have an if statement somewhere.126good = ((flags & BC_PARSE_FLAG_IF) != 0);127}128else if (t == BC_LEX_RBRACE)129{130size_t i;131132// Since we have a brace, we need to just check if a brace was needed.133for (i = 0; !good && i < p->flags.len; ++i)134{135uint16_t* fptr = bc_vec_item_rev(&p->flags, i);136good = (((*fptr) & BC_PARSE_FLAG_BRACE) != 0);137}138}139140return good;141}142143/**144* Returns true if we are in top level of a function body. The POSIX grammar145* is defined such that anything is allowed after a function body, so we must146* use this function to detect that case when ending a function body.147* @param p The parser.148* @return True if we are in the top level of parsing a function body.149*/150static bool151bc_parse_TopFunc(const BcParse* p)152{153bool good = p->flags.len == 2;154155uint16_t val = BC_PARSE_FLAG_BRACE | BC_PARSE_FLAG_FUNC_INNER;156val |= BC_PARSE_FLAG_FUNC;157158return good && BC_PARSE_TOP_FLAG(p) == val;159}160161/**162* Sets a previously defined exit label. What are labels? See the bc Parsing163* section of the Development manual (manuals/development.md).164* @param p The parser.165*/166static void167bc_parse_setLabel(BcParse* p)168{169BcFunc* func = p->func;170BcInstPtr* ip = bc_vec_top(&p->exits);171size_t* label;172173assert(func == bc_vec_item(&p->prog->fns, p->fidx));174175// Set the preallocated label to the correct index.176label = bc_vec_item(&func->labels, ip->idx);177*label = func->code.len;178179// Now, we don't need the exit label; it is done.180bc_vec_pop(&p->exits);181}182183/**184* Creates a label and sets it to idx. If this is an exit label, then idx is185* actually invalid, but it doesn't matter because it will be fixed by186* bc_parse_setLabel() later.187* @param p The parser.188* @param idx The index of the label.189*/190static void191bc_parse_createLabel(BcParse* p, size_t idx)192{193bc_vec_push(&p->func->labels, &idx);194}195196/**197* Creates a conditional label. Unlike an exit label, this label is set at198* creation time because it comes *before* the code that will target it.199* @param p The parser.200* @param idx The index of the label.201*/202static void203bc_parse_createCondLabel(BcParse* p, size_t idx)204{205bc_parse_createLabel(p, p->func->code.len);206bc_vec_push(&p->conds, &idx);207}208209/**210* Creates an exit label to be filled in later by bc_parse_setLabel(). Also, why211* create a label to be filled in later? Because exit labels are meant to be212* targeted by code that comes *before* the label. Since we have to parse that213* code first, and don't know how long it will be, we need to just make sure to214* reserve a slot to be filled in later when we know.215*216* By the way, this uses BcInstPtr because it was convenient. The field idx217* holds the index, and the field func holds the loop boolean.218*219* @param p The parser.220* @param idx The index of the label's position.221* @param loop True if the exit label is for a loop or not.222*/223static void224bc_parse_createExitLabel(BcParse* p, size_t idx, bool loop)225{226BcInstPtr ip;227228assert(p->func == bc_vec_item(&p->prog->fns, p->fidx));229230ip.func = loop;231ip.idx = idx;232ip.len = 0;233234bc_vec_push(&p->exits, &ip);235bc_parse_createLabel(p, SIZE_MAX);236}237238/**239* Pops the correct operators off of the operator stack based on the current240* operator. This is because of the Shunting-Yard algorithm. Lower prec means241* higher precedence.242* @param p The parser.243* @param type The operator.244* @param start The previous start of the operator stack. For more245* information, see the bc Parsing section of the Development246* manual (manuals/development.md).247* @param nexprs A pointer to the current number of expressions that have not248* been consumed yet. This is an IN and OUT parameter.249*/250static void251bc_parse_operator(BcParse* p, BcLexType type, size_t start, size_t* nexprs)252{253BcLexType t;254uchar l, r = BC_PARSE_OP_PREC(type);255uchar left = BC_PARSE_OP_LEFT(type);256257// While we haven't hit the stop point yet...258while (p->ops.len > start)259{260// Get the top operator.261t = BC_PARSE_TOP_OP(p);262263// If it's a left paren, we have reached the end of whatever expression264// this is no matter what. We also don't pop the left paren because it265// will need to stay for the rest of the subexpression.266if (t == BC_LEX_LPAREN) break;267268// Break for precedence. Precedence operates differently on left and269// right associativity, by the way. A left associative operator that270// matches the current precedence should take priority, but a right271// associative operator should not.272//273// Also, a lower precedence value means a higher precedence.274l = BC_PARSE_OP_PREC(t);275if (l >= r && (l != r || !left)) break;276277// Do the housekeeping. In particular, make sure to note that one278// expression was consumed (well, two were, but another was added) if279// the operator was not a prefix operator. (Postfix operators are not280// handled by this function at all.)281bc_parse_push(p, BC_PARSE_TOKEN_INST(t));282bc_vec_pop(&p->ops);283*nexprs -= !BC_PARSE_OP_PREFIX(t);284}285286bc_vec_push(&p->ops, &type);287}288289/**290* Parses a right paren. In the Shunting-Yard algorithm, it needs to be put on291* the operator stack. But before that, it needs to consume whatever operators292* there are until it hits a left paren.293* @param p The parser.294* @param nexprs A pointer to the current number of expressions that have not295* been consumed yet. This is an IN and OUT parameter.296*/297static void298bc_parse_rightParen(BcParse* p, size_t* nexprs)299{300BcLexType top;301302// Consume operators until a left paren.303while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN)304{305bc_parse_push(p, BC_PARSE_TOKEN_INST(top));306bc_vec_pop(&p->ops);307*nexprs -= !BC_PARSE_OP_PREFIX(top);308}309310// We need to pop the left paren as well.311bc_vec_pop(&p->ops);312313// Oh, and we also want the next token.314bc_lex_next(&p->l);315}316317/**318* Parses function arguments.319* @param p The parser.320* @param flags Flags restricting what kind of expressions the arguments can321* be.322*/323static void324bc_parse_args(BcParse* p, uint8_t flags)325{326bool comma = false;327size_t nargs;328329bc_lex_next(&p->l);330331// Print and comparison operators not allowed. Well, comparison operators332// only for POSIX. But we do allow arrays, and we *must* get a value.333flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);334flags |= (BC_PARSE_ARRAY | BC_PARSE_NEEDVAL);335336// Count the arguments and parse them.337for (nargs = 0; p->l.t != BC_LEX_RPAREN; ++nargs)338{339bc_parse_expr_status(p, flags, bc_parse_next_arg);340341comma = (p->l.t == BC_LEX_COMMA);342if (comma) bc_lex_next(&p->l);343}344345// An ending comma is FAIL.346if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);347348// Now do the call with the number of arguments.349bc_parse_push(p, BC_INST_CALL);350bc_parse_pushIndex(p, nargs);351}352353/**354* Parses a function call.355* @param p The parser.356* @param flags Flags restricting what kind of expressions the arguments can357* be.358*/359static void360bc_parse_call(BcParse* p, const char* name, uint8_t flags)361{362size_t idx;363364bc_parse_args(p, flags);365366// We just assert this because bc_parse_args() should367// ensure that the next token is what it should be.368assert(p->l.t == BC_LEX_RPAREN);369370// We cannot use bc_program_insertFunc() here371// because it will overwrite an existing function.372idx = bc_map_index(&p->prog->fn_map, name);373374// The function does not exist yet. Create a space for it. If the user does375// not define it, it's a *runtime* error, not a parse error.376if (idx == BC_VEC_INVALID_IDX)377{378idx = bc_program_insertFunc(p->prog, name);379380assert(idx != BC_VEC_INVALID_IDX);381382// Make sure that this pointer was not invalidated.383p->func = bc_vec_item(&p->prog->fns, p->fidx);384}385// The function exists, so set the right function index.386else idx = ((BcId*) bc_vec_item(&p->prog->fn_map, idx))->idx;387388bc_parse_pushIndex(p, idx);389390// Make sure to get the next token.391bc_lex_next(&p->l);392}393394/**395* Parses a name/identifier-based expression. It could be a variable, an array396* element, an array itself (for function arguments), a function call, etc.397* @param p The parser.398* @param type A pointer to return the resulting instruction.399* @param can_assign A pointer to return true if the name can be assigned to,400* false otherwise.401* @param flags Flags restricting what kind of expression the name can be.402*/403static void404bc_parse_name(BcParse* p, BcInst* type, bool* can_assign, uint8_t flags)405{406char* name;407408BC_SIG_ASSERT_LOCKED;409410// We want a copy of the name since the lexer might overwrite its copy.411name = bc_vm_strdup(p->l.str.v);412413BC_SETJMP_LOCKED(vm, err);414415// We need the next token to see if it's just a variable or something more.416bc_lex_next(&p->l);417418// Array element or array.419if (p->l.t == BC_LEX_LBRACKET)420{421bc_lex_next(&p->l);422423// Array only. This has to be a function parameter.424if (p->l.t == BC_LEX_RBRACKET)425{426// Error if arrays are not allowed.427if (BC_ERR(!(flags & BC_PARSE_ARRAY)))428{429bc_parse_err(p, BC_ERR_PARSE_EXPR);430}431432*type = BC_INST_ARRAY;433*can_assign = false;434}435else436{437// If we are here, we have an array element. We need to set the438// expression parsing flags.439uint8_t flags2 = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) |440BC_PARSE_NEEDVAL;441442bc_parse_expr_status(p, flags2, bc_parse_next_elem);443444// The next token *must* be a right bracket.445if (BC_ERR(p->l.t != BC_LEX_RBRACKET))446{447bc_parse_err(p, BC_ERR_PARSE_TOKEN);448}449450*type = BC_INST_ARRAY_ELEM;451*can_assign = true;452}453454// Make sure to get the next token.455bc_lex_next(&p->l);456457// Push the instruction and the name of the identifier.458bc_parse_push(p, *type);459bc_parse_pushName(p, name, false);460}461else if (p->l.t == BC_LEX_LPAREN)462{463// We are parsing a function call; error if not allowed.464if (BC_ERR(flags & BC_PARSE_NOCALL))465{466bc_parse_err(p, BC_ERR_PARSE_TOKEN);467}468469*type = BC_INST_CALL;470*can_assign = false;471472bc_parse_call(p, name, flags);473}474else475{476// Just a variable.477*type = BC_INST_VAR;478*can_assign = true;479bc_parse_push(p, BC_INST_VAR);480bc_parse_pushName(p, name, true);481}482483err:484// Need to make sure to unallocate the name.485free(name);486BC_LONGJMP_CONT(vm);487BC_SIG_MAYLOCK;488}489490/**491* Parses a builtin function that takes no arguments. This includes read(),492* rand(), maxibase(), maxobase(), maxscale(), and maxrand().493* @param p The parser.494* @param inst The instruction corresponding to the builtin.495*/496static void497bc_parse_noArgBuiltin(BcParse* p, BcInst inst)498{499// Must have a left paren.500bc_lex_next(&p->l);501if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);502503// Must have a right paren.504bc_lex_next(&p->l);505if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);506507bc_parse_push(p, inst);508509bc_lex_next(&p->l);510}511512/**513* Parses a builtin function that takes 1 argument. This includes length(),514* sqrt(), abs(), scale(), and irand().515* @param p The parser.516* @param type The lex token.517* @param flags The expression parsing flags for parsing the argument.518* @param prev An out parameter; the previous instruction pointer.519*/520static void521bc_parse_builtin(BcParse* p, BcLexType type, uint8_t flags, BcInst* prev)522{523// Must have a left paren.524bc_lex_next(&p->l);525if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);526527bc_lex_next(&p->l);528529// Change the flags as needed for parsing the argument.530flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);531flags |= BC_PARSE_NEEDVAL;532533// Since length can take arrays, we need to specially add that flag.534if (type == BC_LEX_KW_LENGTH || type == BC_LEX_KW_ASCIIFY)535{536flags |= BC_PARSE_ARRAY;537}538539// Otherwise, we need to clear it because it could be set.540else flags &= ~(BC_PARSE_ARRAY);541542bc_parse_expr_status(p, flags, bc_parse_next_rel);543544// Must have a right paren.545if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);546547// Adjust previous based on the token and push it.548*prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH;549bc_parse_push(p, *prev);550551bc_lex_next(&p->l);552}553554/**555* Parses a builtin function that takes 3 arguments. This includes modexp() and556* divmod().557* @param p The parser.558* @param type The lex token.559* @param flags The expression parsing flags for parsing the argument.560* @param prev An out parameter; the previous instruction pointer.561*/562static void563bc_parse_builtin3(BcParse* p, BcLexType type, uint8_t flags, BcInst* prev)564{565assert(type == BC_LEX_KW_MODEXP || type == BC_LEX_KW_DIVMOD);566567// Must have a left paren.568bc_lex_next(&p->l);569if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);570571bc_lex_next(&p->l);572573// Change the flags as needed for parsing the argument.574flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);575flags |= BC_PARSE_NEEDVAL;576577bc_parse_expr_status(p, flags, bc_parse_next_builtin);578579// Must have a comma.580if (BC_ERR(p->l.t != BC_LEX_COMMA)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);581582bc_lex_next(&p->l);583584bc_parse_expr_status(p, flags, bc_parse_next_builtin);585586// Must have a comma.587if (BC_ERR(p->l.t != BC_LEX_COMMA)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);588589bc_lex_next(&p->l);590591// If it is a divmod, parse an array name. Otherwise, just parse another592// expression.593if (type == BC_LEX_KW_DIVMOD)594{595// Must have a name.596if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);597598// This is safe because the next token should not overwrite the name.599bc_lex_next(&p->l);600601// Must have a left bracket.602if (BC_ERR(p->l.t != BC_LEX_LBRACKET))603{604bc_parse_err(p, BC_ERR_PARSE_TOKEN);605}606607// This is safe because the next token should not overwrite the name.608bc_lex_next(&p->l);609610// Must have a right bracket.611if (BC_ERR(p->l.t != BC_LEX_RBRACKET))612{613bc_parse_err(p, BC_ERR_PARSE_TOKEN);614}615616// This is safe because the next token should not overwrite the name.617bc_lex_next(&p->l);618}619else bc_parse_expr_status(p, flags, bc_parse_next_rel);620621// Must have a right paren.622if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);623624// Adjust previous based on the token and push it.625*prev = type - BC_LEX_KW_MODEXP + BC_INST_MODEXP;626bc_parse_push(p, *prev);627628// If we have divmod, we need to assign the modulus to the array element, so629// we need to push the instructions for doing so.630if (type == BC_LEX_KW_DIVMOD)631{632// The zeroth element.633bc_parse_push(p, BC_INST_ZERO);634bc_parse_push(p, BC_INST_ARRAY_ELEM);635636// Push the array.637bc_parse_pushName(p, p->l.str.v, false);638639// Swap them and assign. After this, the top item on the stack should640// be the quotient.641bc_parse_push(p, BC_INST_SWAP);642bc_parse_push(p, BC_INST_ASSIGN_NO_VAL);643}644645bc_lex_next(&p->l);646}647648/**649* Parses the scale keyword. This is special because scale can be a value or a650* builtin function.651* @param p The parser.652* @param type An out parameter; the instruction for the parse.653* @param can_assign An out parameter; whether the expression can be assigned654* to.655* @param flags The expression parsing flags for parsing a scale() arg.656*/657static void658bc_parse_scale(BcParse* p, BcInst* type, bool* can_assign, uint8_t flags)659{660bc_lex_next(&p->l);661662// Without the left paren, it's just the keyword.663if (p->l.t != BC_LEX_LPAREN)664{665// Set, push, and return.666*type = BC_INST_SCALE;667*can_assign = true;668bc_parse_push(p, BC_INST_SCALE);669return;670}671672// Handle the scale function.673*type = BC_INST_SCALE_FUNC;674*can_assign = false;675676// Once again, adjust the flags.677flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);678flags |= BC_PARSE_NEEDVAL;679680bc_lex_next(&p->l);681682bc_parse_expr_status(p, flags, bc_parse_next_rel);683684// Must have a right paren.685if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);686687bc_parse_push(p, BC_INST_SCALE_FUNC);688689bc_lex_next(&p->l);690}691692/**693* Parses and increment or decrement operator. This is a bit complex.694* @param p The parser.695* @param prev An out parameter; the previous instruction pointer.696* @param can_assign An out parameter; whether the expression can be assigned697* to.698* @param nexs An in/out parameter; the number of expressions in the699* parse tree that are not used.700* @param flags The expression parsing flags for parsing a scale() arg.701*/702static void703bc_parse_incdec(BcParse* p, BcInst* prev, bool* can_assign, size_t* nexs,704uint8_t flags)705{706BcLexType type;707uchar inst;708BcInst etype = *prev;709BcLexType last = p->l.last;710711assert(prev != NULL && can_assign != NULL);712713// If we can't assign to the previous token, then we have an error.714if (BC_ERR(last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC ||715last == BC_LEX_RPAREN))716{717bc_parse_err(p, BC_ERR_PARSE_ASSIGN);718}719720// Is the previous instruction for a variable?721if (BC_PARSE_INST_VAR(etype))722{723// If so, this is a postfix operator.724if (!*can_assign) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);725726// Only postfix uses BC_INST_INC and BC_INST_DEC.727*prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC);728bc_parse_push(p, inst);729bc_lex_next(&p->l);730*can_assign = false;731}732else733{734// This is a prefix operator. In that case, we just convert it to735// an assignment instruction.736*prev = inst = BC_INST_ASSIGN_PLUS + (p->l.t != BC_LEX_OP_INC);737738bc_lex_next(&p->l);739type = p->l.t;740741// Because we parse the next part of the expression742// right here, we need to increment this.743*nexs = *nexs + 1;744745// Is the next token a normal identifier?746if (type == BC_LEX_NAME)747{748// Parse the name.749uint8_t flags2 = flags & ~(BC_PARSE_ARRAY);750bc_parse_name(p, prev, can_assign, flags2 | BC_PARSE_NOCALL);751}752// Is the next token a global?753else if (type >= BC_LEX_KW_LAST && type <= BC_LEX_KW_OBASE)754{755bc_parse_push(p, type - BC_LEX_KW_LAST + BC_INST_LAST);756bc_lex_next(&p->l);757}758// Is the next token specifically scale, which needs special treatment?759else if (BC_NO_ERR(type == BC_LEX_KW_SCALE))760{761bc_lex_next(&p->l);762763// Check that scale() was not used.764if (BC_ERR(p->l.t == BC_LEX_LPAREN))765{766bc_parse_err(p, BC_ERR_PARSE_TOKEN);767}768else bc_parse_push(p, BC_INST_SCALE);769}770// Now we know we have an error.771else bc_parse_err(p, BC_ERR_PARSE_TOKEN);772773*can_assign = false;774775bc_parse_push(p, BC_INST_ONE);776bc_parse_push(p, inst);777}778}779780/**781* Parses the minus operator. This needs special treatment because it is either782* subtract or negation.783* @param p The parser.784* @param prev An in/out parameter; the previous instruction.785* @param ops_bgn The size of the operator stack.786* @param rparen True if the last token was a right paren.787* @param binlast True if the last token was a binary operator.788* @param nexprs An in/out parameter; the number of unused expressions.789*/790static void791bc_parse_minus(BcParse* p, BcInst* prev, size_t ops_bgn, bool rparen,792bool binlast, size_t* nexprs)793{794BcLexType type;795796bc_lex_next(&p->l);797798// Figure out if it's a minus or a negation.799type = BC_PARSE_LEAF(*prev, binlast, rparen) ? BC_LEX_OP_MINUS : BC_LEX_NEG;800*prev = BC_PARSE_TOKEN_INST(type);801802// We can just push onto the op stack because this is the largest803// precedence operator that gets pushed. Inc/dec does not.804if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type);805else bc_parse_operator(p, type, ops_bgn, nexprs);806}807808/**809* Parses a string.810* @param p The parser.811* @param inst The instruction corresponding to how the string was found and812* how it should be printed.813*/814static void815bc_parse_str(BcParse* p, BcInst inst)816{817bc_parse_addString(p);818bc_parse_push(p, inst);819bc_lex_next(&p->l);820}821822/**823* Parses a print statement.824* @param p The parser.825*/826static void827bc_parse_print(BcParse* p, BcLexType type)828{829BcLexType t;830bool comma = false;831BcInst inst = type == BC_LEX_KW_STREAM ? BC_INST_PRINT_STREAM :832BC_INST_PRINT_POP;833834bc_lex_next(&p->l);835836t = p->l.t;837838// A print or stream statement has to have *something*.839if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_PRINT);840841do842{843// If the token is a string, then print it with escapes.844// BC_INST_PRINT_POP plays that role for bc.845if (t == BC_LEX_STR) bc_parse_str(p, inst);846else847{848// We have an actual number; parse and add a print instruction.849bc_parse_expr_status(p, BC_PARSE_NEEDVAL, bc_parse_next_print);850bc_parse_push(p, inst);851}852853// Is the next token a comma?854comma = (p->l.t == BC_LEX_COMMA);855856// Get the next token if we have a comma.857if (comma) bc_lex_next(&p->l);858else859{860// If we don't have a comma, the statement needs to end.861if (!bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);862else break;863}864865t = p->l.t;866}867while (true);868869// If we have a comma but no token, that's bad.870if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);871}872873/**874* Parses a return statement.875* @param p The parser.876*/877static void878bc_parse_return(BcParse* p)879{880BcLexType t;881bool paren;882uchar inst = BC_INST_RET0;883884// If we are not in a function, that's an error.885if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);886887// If we are in a void function, make sure to return void.888if (p->func->voidfn) inst = BC_INST_RET_VOID;889890bc_lex_next(&p->l);891892t = p->l.t;893paren = (t == BC_LEX_LPAREN);894895// An empty return statement just needs to push the selected instruction.896if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst);897else898{899BcParseStatus s;900901// Need to parse the expression whose value will be returned.902s = bc_parse_expr_err(p, BC_PARSE_NEEDVAL, bc_parse_next_expr);903904// If the expression was empty, just push the selected instruction.905if (s == BC_PARSE_STATUS_EMPTY_EXPR)906{907bc_parse_push(p, inst);908bc_lex_next(&p->l);909}910911// POSIX requires parentheses.912if (!paren || p->l.last != BC_LEX_RPAREN)913{914bc_parse_err(p, BC_ERR_POSIX_RET);915}916917// Void functions require an empty expression.918if (BC_ERR(p->func->voidfn))919{920if (s != BC_PARSE_STATUS_EMPTY_EXPR)921{922bc_parse_verr(p, BC_ERR_PARSE_RET_VOID, p->func->name);923}924}925// If we got here, we want to be sure to end the function with a real926// return instruction, just in case.927else bc_parse_push(p, BC_INST_RET);928}929}930931/**932* Clears flags that indicate the end of an if statement and its block and sets933* the jump location.934* @param p The parser.935*/936static void937bc_parse_noElse(BcParse* p)938{939uint16_t* flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);940*flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));941bc_parse_setLabel(p);942}943944/**945* Ends (finishes parsing) the body of a control statement or a function.946* @param p The parser.947* @param brace True if the body was ended by a brace, false otherwise.948*/949static void950bc_parse_endBody(BcParse* p, bool brace)951{952bool has_brace, new_else = false;953954// We cannot be ending a body if there are no bodies to end.955if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);956957if (brace)958{959// The brace was already gotten; make sure that the caller did not lie.960// We check for the requirement of braces later.961assert(p->l.t == BC_LEX_RBRACE);962963bc_lex_next(&p->l);964965// If the next token is not a delimiter, that is a problem.966if (BC_ERR(!bc_parse_isDelimiter(p) && !bc_parse_TopFunc(p)))967{968bc_parse_err(p, BC_ERR_PARSE_TOKEN);969}970}971972// Do we have a brace flag?973has_brace = (BC_PARSE_BRACE(p) != 0);974975do976{977size_t len = p->flags.len;978bool loop;979980// If we have a brace flag but not a brace, that's a problem.981if (has_brace && !brace) bc_parse_err(p, BC_ERR_PARSE_TOKEN);982983// Are we inside a loop?984loop = (BC_PARSE_LOOP_INNER(p) != 0);985986// If we are ending a loop or an else...987if (loop || BC_PARSE_ELSE(p))988{989// Loops have condition labels that we have to take care of as well.990if (loop)991{992size_t* label = bc_vec_top(&p->conds);993994bc_parse_push(p, BC_INST_JUMP);995bc_parse_pushIndex(p, *label);996997bc_vec_pop(&p->conds);998}9991000bc_parse_setLabel(p);1001bc_vec_pop(&p->flags);1002}1003// If we are ending a function...1004else if (BC_PARSE_FUNC_INNER(p))1005{1006BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0);1007bc_parse_push(p, inst);1008bc_parse_updateFunc(p, BC_PROG_MAIN);1009bc_vec_pop(&p->flags);1010}1011// If we have a brace flag and not an if statement, we can pop the top1012// of the flags stack because they have been taken care of above.1013else if (has_brace && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags);10141015// This needs to be last to parse nested if's properly.1016if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p)))1017{1018// Eat newlines.1019while (p->l.t == BC_LEX_NLINE)1020{1021bc_lex_next(&p->l);1022}10231024// *Now* we can pop the flags.1025bc_vec_pop(&p->flags);10261027// If we are allowed non-POSIX stuff...1028if (!BC_S)1029{1030// Have we found yet another dangling else?1031*(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END;1032new_else = (p->l.t == BC_LEX_KW_ELSE);10331034// Parse the else or end the if statement body.1035if (new_else) bc_parse_else(p);1036else if (!has_brace && (!BC_PARSE_IF_END(p) || brace))1037{1038bc_parse_noElse(p);1039}1040}1041// POSIX requires us to do the bare minimum only.1042else bc_parse_noElse(p);1043}10441045// If these are both true, we have "used" the braces that we found.1046if (brace && has_brace) brace = false;1047}1048// This condition was perhaps the hardest single part of the parser. If1049// the flags stack does not have enough, we should stop. If we have a1050// new else statement, we should stop. If we do have the end of an if1051// statement and we have eaten the brace, we should stop. If we do have1052// a brace flag, we should stop.1053while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) &&1054!(has_brace = (BC_PARSE_BRACE(p) != 0)));10551056// If we have a brace, yet no body for it, that's a problem.1057if (BC_ERR(p->flags.len == 1 && brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1058else if (brace && BC_PARSE_BRACE(p))1059{1060// If we make it here, we have a brace and a flag for it.1061uint16_t flags = BC_PARSE_TOP_FLAG(p);10621063// This condition ensure that the *last* body is correctly finished by1064// popping its flags.1065if (!(flags & (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_LOOP_INNER)) &&1066!(flags & (BC_PARSE_FLAG_IF | BC_PARSE_FLAG_ELSE)) &&1067!(flags & (BC_PARSE_FLAG_IF_END)))1068{1069bc_vec_pop(&p->flags);1070}1071}1072}10731074/**1075* Starts the body of a control statement or function.1076* @param p The parser.1077* @param flags The current flags (will be edited).1078*/1079static void1080bc_parse_startBody(BcParse* p, uint16_t flags)1081{1082assert(flags);1083flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));1084flags |= BC_PARSE_FLAG_BODY;1085bc_vec_push(&p->flags, &flags);1086}10871088void1089bc_parse_endif(BcParse* p)1090{1091size_t i;1092bool good;10931094// Not a problem if this is true.1095if (BC_NO_ERR(!BC_PARSE_NO_EXEC(p))) return;10961097good = true;10981099// Find an instance of a body that needs closing, i.e., a statement that did1100// not have a right brace when it should have.1101for (i = 0; good && i < p->flags.len; ++i)1102{1103uint16_t flag = *((uint16_t*) bc_vec_item(&p->flags, i));1104good = ((flag & BC_PARSE_FLAG_BRACE) != BC_PARSE_FLAG_BRACE);1105}11061107// If we did not find such an instance...1108if (good)1109{1110// We set this to restore it later. We don't want the parser thinking1111// that we are on stdin for this one because it will want more.1112BcMode mode = vm->mode;11131114vm->mode = BC_MODE_FILE;11151116// End all of the if statements and loops.1117while (p->flags.len > 1 || BC_PARSE_IF_END(p))1118{1119if (BC_PARSE_IF_END(p)) bc_parse_noElse(p);1120if (p->flags.len > 1) bc_parse_endBody(p, false);1121}11221123vm->mode = (uchar) mode;1124}1125// If we reach here, a block was not properly closed, and we should error.1126else bc_parse_err(&vm->prs, BC_ERR_PARSE_BLOCK);1127}11281129/**1130* Parses an if statement.1131* @param p The parser.1132*/1133static void1134bc_parse_if(BcParse* p)1135{1136// We are allowed relational operators, and we must have a value.1137size_t idx;1138uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);11391140// Get the left paren and barf if necessary.1141bc_lex_next(&p->l);1142if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);11431144// Parse the condition.1145bc_lex_next(&p->l);1146bc_parse_expr_status(p, flags, bc_parse_next_rel);11471148// Must have a right paren.1149if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);11501151bc_lex_next(&p->l);11521153// Insert the conditional jump instruction.1154bc_parse_push(p, BC_INST_JUMP_ZERO);11551156idx = p->func->labels.len;11571158// Push the index for the instruction and create an exit label for an else1159// statement.1160bc_parse_pushIndex(p, idx);1161bc_parse_createExitLabel(p, idx, false);11621163bc_parse_startBody(p, BC_PARSE_FLAG_IF);1164}11651166/**1167* Parses an else statement.1168* @param p The parser.1169*/1170static void1171bc_parse_else(BcParse* p)1172{1173size_t idx = p->func->labels.len;11741175// We must be at the end of an if statement.1176if (BC_ERR(!BC_PARSE_IF_END(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);11771178// Push an unconditional jump to make bc jump over the else statement if it1179// executed the original if statement.1180bc_parse_push(p, BC_INST_JUMP);1181bc_parse_pushIndex(p, idx);11821183// Clear the else stuff. Yes, that function is misnamed for its use here,1184// but deal with it.1185bc_parse_noElse(p);11861187// Create the exit label and parse the body.1188bc_parse_createExitLabel(p, idx, false);1189bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);11901191bc_lex_next(&p->l);1192}11931194/**1195* Parse a while loop.1196* @param p The parser.1197*/1198static void1199bc_parse_while(BcParse* p)1200{1201// We are allowed relational operators, and we must have a value.1202size_t idx;1203uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);12041205// Get the left paren and barf if necessary.1206bc_lex_next(&p->l);1207if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1208bc_lex_next(&p->l);12091210// Create the labels. Loops need both.1211bc_parse_createCondLabel(p, p->func->labels.len);1212idx = p->func->labels.len;1213bc_parse_createExitLabel(p, idx, true);12141215// Parse the actual condition and barf on non-right paren.1216bc_parse_expr_status(p, flags, bc_parse_next_rel);1217if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1218bc_lex_next(&p->l);12191220// Now we can push the conditional jump and start the body.1221bc_parse_push(p, BC_INST_JUMP_ZERO);1222bc_parse_pushIndex(p, idx);1223bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);1224}12251226/**1227* Parse a for loop.1228* @param p The parser.1229*/1230static void1231bc_parse_for(BcParse* p)1232{1233size_t cond_idx, exit_idx, body_idx, update_idx;12341235// Barf on the missing left paren.1236bc_lex_next(&p->l);1237if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1238bc_lex_next(&p->l);12391240// The first statement can be empty, but if it is, check for error in POSIX1241// mode. Otherwise, parse it.1242if (p->l.t != BC_LEX_SCOLON) bc_parse_expr_status(p, 0, bc_parse_next_for);1243else bc_parse_err(p, BC_ERR_POSIX_FOR);12441245// Must have a semicolon.1246if (BC_ERR(p->l.t != BC_LEX_SCOLON)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1247bc_lex_next(&p->l);12481249// These are indices for labels. There are so many of them because the end1250// of the loop must unconditionally jump to the update code. Then the update1251// code must unconditionally jump to the condition code. Then the condition1252// code must *conditionally* jump to the exit.1253cond_idx = p->func->labels.len;1254update_idx = cond_idx + 1;1255body_idx = update_idx + 1;1256exit_idx = body_idx + 1;12571258// This creates the condition label.1259bc_parse_createLabel(p, p->func->code.len);12601261// Parse an expression if it exists.1262if (p->l.t != BC_LEX_SCOLON)1263{1264uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);1265bc_parse_expr_status(p, flags, bc_parse_next_for);1266}1267else1268{1269// Set this for the next call to bc_parse_number because an empty1270// condition means that it is an infinite loop, so the condition must be1271// non-zero. This is safe to set because the current token is a1272// semicolon, which has no string requirement.1273bc_vec_string(&p->l.str, sizeof(bc_parse_one) - 1, bc_parse_one);1274bc_parse_number(p);12751276// An empty condition makes POSIX mad.1277bc_parse_err(p, BC_ERR_POSIX_FOR);1278}12791280// Must have a semicolon.1281if (BC_ERR(p->l.t != BC_LEX_SCOLON)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1282bc_lex_next(&p->l);12831284// Now we can set up the conditional jump to the exit and an unconditional1285// jump to the body right after. The unconditional jump to the body is1286// because there is update code coming right after the condition, so we need1287// to skip it to get to the body.1288bc_parse_push(p, BC_INST_JUMP_ZERO);1289bc_parse_pushIndex(p, exit_idx);1290bc_parse_push(p, BC_INST_JUMP);1291bc_parse_pushIndex(p, body_idx);12921293// Now create the label for the update code.1294bc_parse_createCondLabel(p, update_idx);12951296// Parse if not empty, and if it is, let POSIX yell if necessary.1297if (p->l.t != BC_LEX_RPAREN) bc_parse_expr_status(p, 0, bc_parse_next_rel);1298else bc_parse_err(p, BC_ERR_POSIX_FOR);12991300// Must have a right paren.1301if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);13021303// Set up a jump to the condition right after the update code.1304bc_parse_push(p, BC_INST_JUMP);1305bc_parse_pushIndex(p, cond_idx);1306bc_parse_createLabel(p, p->func->code.len);13071308// Create an exit label for the body and start the body.1309bc_parse_createExitLabel(p, exit_idx, true);1310bc_lex_next(&p->l);1311bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);1312}13131314/**1315* Parse a statement or token that indicates a loop exit. This includes an1316* actual loop exit, the break keyword, or the continue keyword.1317* @param p The parser.1318* @param type The type of exit.1319*/1320static void1321bc_parse_loopExit(BcParse* p, BcLexType type)1322{1323size_t i;1324BcInstPtr* ip;13251326// Must have a loop. If we don't, that's an error.1327if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);13281329// If we have a break statement...1330if (type == BC_LEX_KW_BREAK)1331{1332// If there are no exits, something went wrong somewhere.1333if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);13341335// Get the exit.1336i = p->exits.len - 1;1337ip = bc_vec_item(&p->exits, i);13381339// The condition !ip->func is true if the exit is not for a loop, so we1340// need to find the first actual loop exit.1341while (!ip->func && i < p->exits.len)1342{1343ip = bc_vec_item(&p->exits, i);1344i -= 1;1345}13461347// Make sure everything is hunky dory.1348assert(ip != NULL && (i < p->exits.len || ip->func));13491350// Set the index for the exit.1351i = ip->idx;1352}1353// If we have a continue statement or just the loop end, jump to the1354// condition (or update for a foor loop).1355else i = *((size_t*) bc_vec_top(&p->conds));13561357// Add the unconditional jump.1358bc_parse_push(p, BC_INST_JUMP);1359bc_parse_pushIndex(p, i);13601361bc_lex_next(&p->l);1362}13631364/**1365* Parse a function (header).1366* @param p The parser.1367*/1368static void1369bc_parse_func(BcParse* p)1370{1371bool comma = false, voidfn;1372uint16_t flags;1373size_t idx;13741375bc_lex_next(&p->l);13761377// Must have a name.1378if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_FUNC);13791380// If the name is "void", and POSIX is not on, mark as void.1381voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME &&1382!strcmp(p->l.str.v, "void"));13831384// We can safely do this because the expected token should not overwrite the1385// function name.1386bc_lex_next(&p->l);13871388// If we *don't* have another name, then void is the name of the function.1389voidfn = (voidfn && p->l.t == BC_LEX_NAME);13901391// With a void function, allow POSIX to complain and get a new token.1392if (voidfn)1393{1394bc_parse_err(p, BC_ERR_POSIX_VOID);13951396// We can safely do this because the expected token should not overwrite1397// the function name.1398bc_lex_next(&p->l);1399}14001401// Must have a left paren.1402if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_FUNC);14031404// Make sure the functions map and vector are synchronized.1405assert(p->prog->fns.len == p->prog->fn_map.len);14061407// Insert the function by name into the map and vector.1408idx = bc_program_insertFunc(p->prog, p->l.str.v);14091410// Make sure the insert worked.1411assert(idx);14121413// Update the function pointer and stuff in the parser and set its void.1414bc_parse_updateFunc(p, idx);1415p->func->voidfn = voidfn;14161417bc_lex_next(&p->l);14181419// While we do not have a right paren, we are still parsing arguments.1420while (p->l.t != BC_LEX_RPAREN)1421{1422BcType t = BC_TYPE_VAR;14231424// If we have an asterisk, we are parsing a reference argument.1425if (p->l.t == BC_LEX_OP_MULTIPLY)1426{1427t = BC_TYPE_REF;1428bc_lex_next(&p->l);14291430// Let POSIX complain if necessary.1431bc_parse_err(p, BC_ERR_POSIX_REF);1432}14331434// If we don't have a name, the argument will not have a name. Barf.1435if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_FUNC);14361437// Increment the number of parameters.1438p->func->nparams += 1;14391440// Copy the string in the lexer so that we can use the lexer again.1441bc_vec_string(&p->buf, p->l.str.len, p->l.str.v);14421443bc_lex_next(&p->l);14441445// We are parsing an array parameter if this is true.1446if (p->l.t == BC_LEX_LBRACKET)1447{1448// Set the array type, unless we are already parsing a reference.1449if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY;14501451bc_lex_next(&p->l);14521453// The brackets *must* be empty.1454if (BC_ERR(p->l.t != BC_LEX_RBRACKET))1455{1456bc_parse_err(p, BC_ERR_PARSE_FUNC);1457}14581459bc_lex_next(&p->l);1460}1461// If we did *not* get a bracket, but we are expecting a reference, we1462// have a problem.1463else if (BC_ERR(t == BC_TYPE_REF))1464{1465bc_parse_verr(p, BC_ERR_PARSE_REF_VAR, p->buf.v);1466}14671468// Test for comma and get the next token if it exists.1469comma = (p->l.t == BC_LEX_COMMA);1470if (comma) bc_lex_next(&p->l);14711472// Insert the parameter into the function.1473bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);1474}14751476// If we have a comma, but no parameter, barf.1477if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);14781479// Start the body.1480flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER;1481bc_parse_startBody(p, flags);14821483bc_lex_next(&p->l);14841485// POSIX requires that a brace be on the same line as the function header.1486// If we don't have a brace, let POSIX throw an error.1487if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERR_POSIX_BRACE);1488}14891490/**1491* Parse an auto list.1492* @param p The parser.1493*/1494static void1495bc_parse_auto(BcParse* p)1496{1497bool comma, one;14981499// Error if the auto keyword appeared in the wrong place.1500if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1501bc_lex_next(&p->l);15021503p->auto_part = comma = false;15041505// We need at least one variable or array.1506one = (p->l.t == BC_LEX_NAME);15071508// While we have a variable or array.1509while (p->l.t == BC_LEX_NAME)1510{1511BcType t;15121513// Copy the name from the lexer, so we can use it again.1514bc_vec_string(&p->buf, p->l.str.len - 1, p->l.str.v);15151516bc_lex_next(&p->l);15171518// If we are parsing an array...1519if (p->l.t == BC_LEX_LBRACKET)1520{1521t = BC_TYPE_ARRAY;15221523bc_lex_next(&p->l);15241525// The brackets *must* be empty.1526if (BC_ERR(p->l.t != BC_LEX_RBRACKET))1527{1528bc_parse_err(p, BC_ERR_PARSE_FUNC);1529}15301531bc_lex_next(&p->l);1532}1533else t = BC_TYPE_VAR;15341535// Test for comma and get the next token if it exists.1536comma = (p->l.t == BC_LEX_COMMA);1537if (comma) bc_lex_next(&p->l);15381539// Insert the auto into the function.1540bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);1541}15421543// If we have a comma, but no auto, barf.1544if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);15451546// If we don't have any variables or arrays, barf.1547if (BC_ERR(!one)) bc_parse_err(p, BC_ERR_PARSE_NO_AUTO);15481549// The auto statement should be all that's in the statement.1550if (BC_ERR(!bc_parse_isDelimiter(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);1551}15521553/**1554* Parses a body.1555* @param p The parser.1556* @param brace True if a brace was encountered, false otherwise.1557*/1558static void1559bc_parse_body(BcParse* p, bool brace)1560{1561uint16_t* flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);15621563assert(flag_ptr != NULL);1564assert(p->flags.len >= 2);15651566// The body flag is for when we expect a body. We got a body, so clear the1567// flag.1568*flag_ptr &= ~(BC_PARSE_FLAG_BODY);15691570// If we are inside a function, that means we just barely entered it, and1571// we can expect an auto list.1572if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER)1573{1574// We *must* have a brace in this case.1575if (BC_ERR(!brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);15761577p->auto_part = (p->l.t != BC_LEX_KW_AUTO);15781579if (!p->auto_part)1580{1581// Make sure this is true to not get a parse error.1582p->auto_part = true;15831584// Since we already have the auto keyword, parse.1585bc_parse_auto(p);1586}15871588// Eat a newline.1589if (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);1590}1591else1592{1593// This is the easy part.1594size_t len = p->flags.len;15951596assert(*flag_ptr);15971598// Parse a statement.1599bc_parse_stmt(p);16001601// This is a very important condition to get right. If there is no1602// brace, and no body flag, and the flags len hasn't shrunk, then we1603// have a body that was not delimited by braces, so we need to end it1604// now, after just one statement.1605if (!brace && !BC_PARSE_BODY(p) && len <= p->flags.len)1606{1607bc_parse_endBody(p, false);1608}1609}1610}16111612/**1613* Parses a statement. This is the entry point for just about everything, except1614* function definitions.1615* @param p The parser.1616*/1617static void1618bc_parse_stmt(BcParse* p)1619{1620size_t len;1621uint16_t flags;1622BcLexType type = p->l.t;16231624// Eat newline.1625if (type == BC_LEX_NLINE)1626{1627bc_lex_next(&p->l);1628return;1629}16301631// Eat auto list.1632if (type == BC_LEX_KW_AUTO)1633{1634bc_parse_auto(p);1635return;1636}16371638// If we reach this point, no auto list is allowed.1639p->auto_part = false;16401641// Everything but an else needs to be taken care of here, but else is1642// special.1643if (type != BC_LEX_KW_ELSE)1644{1645// After an if, no else found.1646if (BC_PARSE_IF_END(p))1647{1648// Clear the expectation for else, end body, and return. Returning1649// gives us a clean slate for parsing again.1650bc_parse_noElse(p);1651if (p->flags.len > 1 && !BC_PARSE_BRACE(p))1652{1653bc_parse_endBody(p, false);1654}16551656return;1657}1658// With a left brace, we are parsing a body.1659else if (type == BC_LEX_LBRACE)1660{1661// We need to start a body if we are not expecting one yet.1662if (!BC_PARSE_BODY(p))1663{1664bc_parse_startBody(p, BC_PARSE_FLAG_BRACE);1665bc_lex_next(&p->l);1666}1667// If we *are* expecting a body, that body should get a brace. This1668// takes care of braces being on a different line than if and loop1669// headers.1670else1671{1672*(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE;1673bc_lex_next(&p->l);1674bc_parse_body(p, true);1675}16761677// If we have reached this point, we need to return for a clean1678// slate.1679return;1680}1681// This happens when we are expecting a body and get a single statement,1682// i.e., a body with no braces surrounding it. Returns after for a clean1683// slate.1684else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p))1685{1686bc_parse_body(p, false);1687return;1688}1689}16901691len = p->flags.len;1692flags = BC_PARSE_TOP_FLAG(p);16931694switch (type)1695{1696// All of these are valid for expressions.1697case BC_LEX_OP_INC:1698case BC_LEX_OP_DEC:1699case BC_LEX_OP_MINUS:1700case BC_LEX_OP_BOOL_NOT:1701case BC_LEX_LPAREN:1702case BC_LEX_NAME:1703case BC_LEX_NUMBER:1704case BC_LEX_KW_IBASE:1705case BC_LEX_KW_LAST:1706case BC_LEX_KW_LENGTH:1707case BC_LEX_KW_OBASE:1708case BC_LEX_KW_SCALE:1709#if BC_ENABLE_EXTRA_MATH1710case BC_LEX_KW_SEED:1711#endif // BC_ENABLE_EXTRA_MATH1712case BC_LEX_KW_SQRT:1713case BC_LEX_KW_ABS:1714case BC_LEX_KW_IS_NUMBER:1715case BC_LEX_KW_IS_STRING:1716#if BC_ENABLE_EXTRA_MATH1717case BC_LEX_KW_IRAND:1718#endif // BC_ENABLE_EXTRA_MATH1719case BC_LEX_KW_ASCIIFY:1720case BC_LEX_KW_MODEXP:1721case BC_LEX_KW_DIVMOD:1722case BC_LEX_KW_READ:1723#if BC_ENABLE_EXTRA_MATH1724case BC_LEX_KW_RAND:1725#endif // BC_ENABLE_EXTRA_MATH1726case BC_LEX_KW_MAXIBASE:1727case BC_LEX_KW_MAXOBASE:1728case BC_LEX_KW_MAXSCALE:1729#if BC_ENABLE_EXTRA_MATH1730case BC_LEX_KW_MAXRAND:1731#endif // BC_ENABLE_EXTRA_MATH1732case BC_LEX_KW_LINE_LENGTH:1733case BC_LEX_KW_GLOBAL_STACKS:1734case BC_LEX_KW_LEADING_ZERO:1735{1736bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr);1737break;1738}17391740case BC_LEX_KW_ELSE:1741{1742bc_parse_else(p);1743break;1744}17451746// Just eat.1747case BC_LEX_SCOLON:1748{1749// Do nothing.1750break;1751}17521753case BC_LEX_RBRACE:1754{1755bc_parse_endBody(p, true);1756break;1757}17581759case BC_LEX_STR:1760{1761bc_parse_str(p, BC_INST_PRINT_STR);1762break;1763}17641765case BC_LEX_KW_BREAK:1766case BC_LEX_KW_CONTINUE:1767{1768bc_parse_loopExit(p, p->l.t);1769break;1770}17711772case BC_LEX_KW_FOR:1773{1774bc_parse_for(p);1775break;1776}17771778case BC_LEX_KW_HALT:1779{1780bc_parse_push(p, BC_INST_HALT);1781bc_lex_next(&p->l);1782break;1783}17841785case BC_LEX_KW_IF:1786{1787bc_parse_if(p);1788break;1789}17901791case BC_LEX_KW_LIMITS:1792{1793// `limits` is a compile-time command, so execute it right away.1794bc_vm_printf("BC_LONG_BIT = %lu\n", (ulong) BC_LONG_BIT);1795bc_vm_printf("BC_BASE_DIGS = %lu\n", (ulong) BC_BASE_DIGS);1796bc_vm_printf("BC_BASE_POW = %lu\n", (ulong) BC_BASE_POW);1797bc_vm_printf("BC_OVERFLOW_MAX = %lu\n", (ulong) BC_NUM_BIGDIG_MAX);1798bc_vm_printf("\n");1799bc_vm_printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE);1800bc_vm_printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM);1801bc_vm_printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE);1802bc_vm_printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING);1803bc_vm_printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME);1804bc_vm_printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM);1805#if BC_ENABLE_EXTRA_MATH1806bc_vm_printf("BC_RAND_MAX = %lu\n", BC_MAX_RAND);1807#endif // BC_ENABLE_EXTRA_MATH1808bc_vm_printf("MAX Exponent = %lu\n", BC_MAX_EXP);1809bc_vm_printf("Number of vars = %lu\n", BC_MAX_VARS);18101811bc_lex_next(&p->l);18121813break;1814}18151816case BC_LEX_KW_STREAM:1817case BC_LEX_KW_PRINT:1818{1819bc_parse_print(p, type);1820break;1821}18221823case BC_LEX_KW_QUIT:1824{1825// Quit is a compile-time command. We don't exit directly, so the vm1826// can clean up.1827vm->status = BC_STATUS_QUIT;1828BC_JMP;1829break;1830}18311832case BC_LEX_KW_RETURN:1833{1834bc_parse_return(p);1835break;1836}18371838case BC_LEX_KW_WHILE:1839{1840bc_parse_while(p);1841break;1842}18431844case BC_LEX_EOF:1845case BC_LEX_INVALID:1846case BC_LEX_NEG:1847#if BC_ENABLE_EXTRA_MATH1848case BC_LEX_OP_TRUNC:1849#endif // BC_ENABLE_EXTRA_MATH1850case BC_LEX_OP_POWER:1851case BC_LEX_OP_MULTIPLY:1852case BC_LEX_OP_DIVIDE:1853case BC_LEX_OP_MODULUS:1854case BC_LEX_OP_PLUS:1855#if BC_ENABLE_EXTRA_MATH1856case BC_LEX_OP_PLACES:1857case BC_LEX_OP_LSHIFT:1858case BC_LEX_OP_RSHIFT:1859#endif // BC_ENABLE_EXTRA_MATH1860case BC_LEX_OP_REL_EQ:1861case BC_LEX_OP_REL_LE:1862case BC_LEX_OP_REL_GE:1863case BC_LEX_OP_REL_NE:1864case BC_LEX_OP_REL_LT:1865case BC_LEX_OP_REL_GT:1866case BC_LEX_OP_BOOL_OR:1867case BC_LEX_OP_BOOL_AND:1868case BC_LEX_OP_ASSIGN_POWER:1869case BC_LEX_OP_ASSIGN_MULTIPLY:1870case BC_LEX_OP_ASSIGN_DIVIDE:1871case BC_LEX_OP_ASSIGN_MODULUS:1872case BC_LEX_OP_ASSIGN_PLUS:1873case BC_LEX_OP_ASSIGN_MINUS:1874#if BC_ENABLE_EXTRA_MATH1875case BC_LEX_OP_ASSIGN_PLACES:1876case BC_LEX_OP_ASSIGN_LSHIFT:1877case BC_LEX_OP_ASSIGN_RSHIFT:1878#endif // BC_ENABLE_EXTRA_MATH1879case BC_LEX_OP_ASSIGN:1880case BC_LEX_NLINE:1881case BC_LEX_WHITESPACE:1882case BC_LEX_RPAREN:1883case BC_LEX_LBRACKET:1884case BC_LEX_COMMA:1885case BC_LEX_RBRACKET:1886case BC_LEX_LBRACE:1887case BC_LEX_KW_AUTO:1888case BC_LEX_KW_DEFINE:1889#if DC_ENABLED1890case BC_LEX_EXTENDED_REGISTERS:1891case BC_LEX_EQ_NO_REG:1892case BC_LEX_COLON:1893case BC_LEX_EXECUTE:1894case BC_LEX_PRINT_STACK:1895case BC_LEX_CLEAR_STACK:1896case BC_LEX_REG_STACK_LEVEL:1897case BC_LEX_STACK_LEVEL:1898case BC_LEX_DUPLICATE:1899case BC_LEX_SWAP:1900case BC_LEX_POP:1901case BC_LEX_STORE_IBASE:1902case BC_LEX_STORE_OBASE:1903case BC_LEX_STORE_SCALE:1904#if BC_ENABLE_EXTRA_MATH1905case BC_LEX_STORE_SEED:1906#endif // BC_ENABLE_EXTRA_MATH1907case BC_LEX_LOAD:1908case BC_LEX_LOAD_POP:1909case BC_LEX_STORE_PUSH:1910case BC_LEX_PRINT_POP:1911case BC_LEX_NQUIT:1912case BC_LEX_EXEC_STACK_LENGTH:1913case BC_LEX_SCALE_FACTOR:1914case BC_LEX_ARRAY_LENGTH:1915#endif // DC_ENABLED1916{1917bc_parse_err(p, BC_ERR_PARSE_TOKEN);1918}1919}19201921// If the flags did not change, we expect a delimiter.1922if (len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p))1923{1924if (BC_ERR(!bc_parse_isDelimiter(p)))1925{1926bc_parse_err(p, BC_ERR_PARSE_TOKEN);1927}1928}19291930// Make sure semicolons are eaten.1931while (p->l.t == BC_LEX_SCOLON || p->l.t == BC_LEX_NLINE)1932{1933bc_lex_next(&p->l);1934}19351936// POSIX's grammar does not allow a function definition after a semicolon1937// without a newline, so check specifically for that case and error if1938// the POSIX standard flag is set.1939if (p->l.last == BC_LEX_SCOLON && p->l.t == BC_LEX_KW_DEFINE && BC_IS_POSIX)1940{1941bc_parse_err(p, BC_ERR_POSIX_FUNC_AFTER_SEMICOLON);1942}1943}19441945void1946bc_parse_parse(BcParse* p)1947{1948assert(p);19491950BC_SETJMP_LOCKED(vm, exit);19511952// We should not let an EOF get here unless some partial parse was not1953// completed, in which case, it's the user's fault.1954if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERR_PARSE_EOF);19551956// Functions need special parsing.1957else if (p->l.t == BC_LEX_KW_DEFINE)1958{1959if (BC_ERR(BC_PARSE_NO_EXEC(p)))1960{1961bc_parse_endif(p);1962if (BC_ERR(BC_PARSE_NO_EXEC(p)))1963{1964bc_parse_err(p, BC_ERR_PARSE_TOKEN);1965}1966}1967bc_parse_func(p);1968}19691970// Otherwise, parse a normal statement.1971else bc_parse_stmt(p);19721973exit:19741975// We need to reset on error.1976if (BC_ERR(((vm->status && vm->status != BC_STATUS_QUIT) || vm->sig != 0)))1977{1978bc_parse_reset(p);1979}19801981BC_LONGJMP_CONT(vm);1982BC_SIG_MAYLOCK;1983}19841985/**1986* Parse an expression. This is the actual implementation of the Shunting-Yard1987* Algorithm.1988* @param p The parser.1989* @param flags The flags for what is valid in the expression.1990* @param next A set of tokens for what is valid *after* the expression.1991* @return A parse status. In some places, an empty expression is an1992* error, and sometimes, it is required. This allows this function1993* to tell the caller if the expression was empty and let the1994* caller handle it.1995*/1996static BcParseStatus1997bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next)1998{1999BcInst prev = BC_INST_PRINT;2000uchar inst = BC_INST_INVALID;2001BcLexType top, t;2002size_t nexprs, ops_bgn;2003uint32_t i, nparens, nrelops;2004bool pfirst, rprn, array_last, done, get_token, assign;2005bool bin_last, incdec, can_assign;20062007// One of these *must* be true.2008assert(!(flags & BC_PARSE_PRINT) || !(flags & BC_PARSE_NEEDVAL));20092010// These are set very carefully. In fact, controlling the values of these2011// locals is the biggest part of making this work. ops_bgn especially is2012// important because it marks where the operator stack begins for *this*2013// invocation of this function. That's because bc_parse_expr_err() is2014// recursive (the Shunting-Yard Algorithm is most easily expressed2015// recursively when parsing subexpressions), and each invocation needs to2016// know where to stop.2017//2018// - nparens is the number of left parens without matches.2019// - nrelops is the number of relational operators that appear in the expr.2020// - nexprs is the number of unused expressions.2021// - rprn is a right paren encountered last.2022// - array_last is an array item encountered last.2023// - done means the expression has been fully parsed.2024// - get_token is true when a token is needed at the end of an iteration.2025// - assign is true when an assignment statement was parsed last.2026// - incdec is true when the previous operator was an inc or dec operator.2027// - can_assign is true when an assignemnt is valid.2028// - bin_last is true when the previous instruction was a binary operator.2029t = p->l.t;2030pfirst = (p->l.t == BC_LEX_LPAREN);2031nparens = nrelops = 0;2032nexprs = 0;2033ops_bgn = p->ops.len;2034rprn = array_last = done = get_token = assign = incdec = can_assign = false;2035bin_last = true;20362037// We want to eat newlines if newlines are not a valid ending token.2038// This is for spacing in things like for loop headers.2039if (!(flags & BC_PARSE_NOREAD))2040{2041while ((t = p->l.t) == BC_LEX_NLINE)2042{2043bc_lex_next(&p->l);2044}2045}20462047// This is the Shunting-Yard algorithm loop.2048for (; !done && BC_PARSE_EXPR(t); t = p->l.t)2049{2050// Make sure an array expression is not mixed with any others. However,2051// a right parenthesis may end the expression, so we will need to take2052// care of that right there.2053if (BC_ERR(array_last && t != BC_LEX_RPAREN))2054{2055bc_parse_err(p, BC_ERR_PARSE_EXPR);2056}20572058switch (t)2059{2060case BC_LEX_OP_INC:2061case BC_LEX_OP_DEC:2062{2063// These operators can only be used with items that can be2064// assigned to.2065if (BC_ERR(incdec)) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);20662067bc_parse_incdec(p, &prev, &can_assign, &nexprs, flags);20682069rprn = get_token = bin_last = false;2070incdec = true;2071flags &= ~(BC_PARSE_ARRAY);20722073break;2074}20752076#if BC_ENABLE_EXTRA_MATH2077case BC_LEX_OP_TRUNC:2078{2079// The previous token must have been a leaf expression, or the2080// operator is in the wrong place.2081if (BC_ERR(!BC_PARSE_LEAF(prev, bin_last, rprn)))2082{2083bc_parse_err(p, BC_ERR_PARSE_TOKEN);2084}20852086// I can just add the instruction because2087// negative will already be taken care of.2088bc_parse_push(p, BC_INST_TRUNC);20892090rprn = can_assign = incdec = false;2091get_token = true;2092flags &= ~(BC_PARSE_ARRAY);20932094break;2095}2096#endif // BC_ENABLE_EXTRA_MATH20972098case BC_LEX_OP_MINUS:2099{2100bc_parse_minus(p, &prev, ops_bgn, rprn, bin_last, &nexprs);21012102rprn = get_token = can_assign = false;21032104// This is true if it was a binary operator last.2105bin_last = (prev == BC_INST_MINUS);2106if (bin_last) incdec = false;21072108flags &= ~(BC_PARSE_ARRAY);21092110break;2111}21122113// All of this group, including the fallthrough, is to parse binary2114// operators.2115case BC_LEX_OP_ASSIGN_POWER:2116case BC_LEX_OP_ASSIGN_MULTIPLY:2117case BC_LEX_OP_ASSIGN_DIVIDE:2118case BC_LEX_OP_ASSIGN_MODULUS:2119case BC_LEX_OP_ASSIGN_PLUS:2120case BC_LEX_OP_ASSIGN_MINUS:2121#if BC_ENABLE_EXTRA_MATH2122case BC_LEX_OP_ASSIGN_PLACES:2123case BC_LEX_OP_ASSIGN_LSHIFT:2124case BC_LEX_OP_ASSIGN_RSHIFT:2125#endif // BC_ENABLE_EXTRA_MATH2126case BC_LEX_OP_ASSIGN:2127{2128// We need to make sure the assignment is valid.2129if (!BC_PARSE_INST_VAR(prev))2130{2131bc_parse_err(p, BC_ERR_PARSE_ASSIGN);2132}21332134// Fallthrough.2135BC_FALLTHROUGH2136}21372138case BC_LEX_OP_POWER:2139case BC_LEX_OP_MULTIPLY:2140case BC_LEX_OP_DIVIDE:2141case BC_LEX_OP_MODULUS:2142case BC_LEX_OP_PLUS:2143#if BC_ENABLE_EXTRA_MATH2144case BC_LEX_OP_PLACES:2145case BC_LEX_OP_LSHIFT:2146case BC_LEX_OP_RSHIFT:2147#endif // BC_ENABLE_EXTRA_MATH2148case BC_LEX_OP_REL_EQ:2149case BC_LEX_OP_REL_LE:2150case BC_LEX_OP_REL_GE:2151case BC_LEX_OP_REL_NE:2152case BC_LEX_OP_REL_LT:2153case BC_LEX_OP_REL_GT:2154case BC_LEX_OP_BOOL_NOT:2155case BC_LEX_OP_BOOL_OR:2156case BC_LEX_OP_BOOL_AND:2157{2158// This is true if the operator if the token is a prefix2159// operator. This is only for boolean not.2160if (BC_PARSE_OP_PREFIX(t))2161{2162// Prefix operators are only allowed after binary operators2163// or prefix operators.2164if (BC_ERR(!bin_last && !BC_PARSE_OP_PREFIX(p->l.last)))2165{2166bc_parse_err(p, BC_ERR_PARSE_EXPR);2167}2168}2169// If we execute the else, that means we have a binary operator.2170// If the previous operator was a prefix or a binary operator,2171// then a binary operator is not allowed.2172else if (BC_ERR(BC_PARSE_PREV_PREFIX(prev) || bin_last))2173{2174bc_parse_err(p, BC_ERR_PARSE_EXPR);2175}21762177nrelops += (t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT);2178prev = BC_PARSE_TOKEN_INST(t);21792180bc_parse_operator(p, t, ops_bgn, &nexprs);21812182rprn = incdec = can_assign = false;2183get_token = true;2184bin_last = !BC_PARSE_OP_PREFIX(t);2185flags &= ~(BC_PARSE_ARRAY);21862187break;2188}21892190case BC_LEX_LPAREN:2191{2192// A left paren is *not* allowed right after a leaf expr.2193if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2194{2195bc_parse_err(p, BC_ERR_PARSE_EXPR);2196}21972198nparens += 1;2199rprn = incdec = can_assign = false;2200get_token = true;22012202// Push the paren onto the operator stack.2203bc_vec_push(&p->ops, &t);22042205break;2206}22072208case BC_LEX_RPAREN:2209{2210// This needs to be a status. The error is handled in2211// bc_parse_expr_status().2212if (BC_ERR(p->l.last == BC_LEX_LPAREN))2213{2214return BC_PARSE_STATUS_EMPTY_EXPR;2215}22162217// The right paren must not come after a prefix or binary2218// operator.2219if (BC_ERR(bin_last || BC_PARSE_PREV_PREFIX(prev)))2220{2221bc_parse_err(p, BC_ERR_PARSE_EXPR);2222}22232224// If there are no parens left, we are done, but we need another2225// token.2226if (!nparens)2227{2228done = true;2229get_token = false;2230break;2231}22322233// Now that we know the right paren has not ended the2234// expression, make sure an array expression is not mixed with2235// any others.2236if (BC_ERR(array_last))2237{2238bc_parse_err(p, BC_ERR_PARSE_EXPR);2239}22402241nparens -= 1;2242rprn = true;2243get_token = bin_last = incdec = false;22442245bc_parse_rightParen(p, &nexprs);22462247break;2248}22492250case BC_LEX_STR:2251{2252// POSIX only allows strings alone.2253if (BC_IS_POSIX) bc_parse_err(p, BC_ERR_POSIX_EXPR_STRING);22542255// A string is a leaf and cannot come right after a leaf.2256if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2257{2258bc_parse_err(p, BC_ERR_PARSE_EXPR);2259}22602261bc_parse_addString(p);22622263get_token = true;2264bin_last = rprn = false;2265nexprs += 1;22662267break;2268}22692270case BC_LEX_NAME:2271{2272// A name is a leaf and cannot come right after a leaf.2273if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2274{2275bc_parse_err(p, BC_ERR_PARSE_EXPR);2276}22772278get_token = bin_last = false;22792280bc_parse_name(p, &prev, &can_assign, flags & ~BC_PARSE_NOCALL);22812282rprn = (prev == BC_INST_CALL);2283array_last = (prev == BC_INST_ARRAY);2284nexprs += 1;2285flags &= ~(BC_PARSE_ARRAY);22862287break;2288}22892290case BC_LEX_NUMBER:2291{2292// A number is a leaf and cannot come right after a leaf.2293if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2294{2295bc_parse_err(p, BC_ERR_PARSE_EXPR);2296}22972298// The number instruction is pushed in here.2299bc_parse_number(p);23002301nexprs += 1;2302prev = BC_INST_NUM;2303get_token = true;2304rprn = bin_last = can_assign = false;2305flags &= ~(BC_PARSE_ARRAY);23062307break;2308}23092310case BC_LEX_KW_IBASE:2311case BC_LEX_KW_LAST:2312case BC_LEX_KW_OBASE:2313#if BC_ENABLE_EXTRA_MATH2314case BC_LEX_KW_SEED:2315#endif // BC_ENABLE_EXTRA_MATH2316{2317// All of these are leaves and cannot come right after a leaf.2318if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2319{2320bc_parse_err(p, BC_ERR_PARSE_EXPR);2321}23222323prev = t - BC_LEX_KW_LAST + BC_INST_LAST;2324bc_parse_push(p, prev);23252326get_token = can_assign = true;2327rprn = bin_last = false;2328nexprs += 1;2329flags &= ~(BC_PARSE_ARRAY);23302331break;2332}23332334case BC_LEX_KW_LENGTH:2335case BC_LEX_KW_SQRT:2336case BC_LEX_KW_ABS:2337case BC_LEX_KW_IS_NUMBER:2338case BC_LEX_KW_IS_STRING:2339#if BC_ENABLE_EXTRA_MATH2340case BC_LEX_KW_IRAND:2341#endif // BC_ENABLE_EXTRA_MATH2342case BC_LEX_KW_ASCIIFY:2343{2344// All of these are leaves and cannot come right after a leaf.2345if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2346{2347bc_parse_err(p, BC_ERR_PARSE_EXPR);2348}23492350bc_parse_builtin(p, t, flags, &prev);23512352rprn = get_token = bin_last = incdec = can_assign = false;2353nexprs += 1;2354flags &= ~(BC_PARSE_ARRAY);23552356break;2357}23582359case BC_LEX_KW_READ:2360#if BC_ENABLE_EXTRA_MATH2361case BC_LEX_KW_RAND:2362#endif // BC_ENABLE_EXTRA_MATH2363case BC_LEX_KW_MAXIBASE:2364case BC_LEX_KW_MAXOBASE:2365case BC_LEX_KW_MAXSCALE:2366#if BC_ENABLE_EXTRA_MATH2367case BC_LEX_KW_MAXRAND:2368#endif // BC_ENABLE_EXTRA_MATH2369case BC_LEX_KW_LINE_LENGTH:2370case BC_LEX_KW_GLOBAL_STACKS:2371case BC_LEX_KW_LEADING_ZERO:2372{2373// All of these are leaves and cannot come right after a leaf.2374if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2375{2376bc_parse_err(p, BC_ERR_PARSE_EXPR);2377}23782379// Error if we have read and it's not allowed.2380else if (t == BC_LEX_KW_READ && BC_ERR(flags & BC_PARSE_NOREAD))2381{2382bc_parse_err(p, BC_ERR_EXEC_REC_READ);2383}23842385prev = t - BC_LEX_KW_READ + BC_INST_READ;2386bc_parse_noArgBuiltin(p, prev);23872388rprn = get_token = bin_last = incdec = can_assign = false;2389nexprs += 1;2390flags &= ~(BC_PARSE_ARRAY);23912392break;2393}23942395case BC_LEX_KW_SCALE:2396{2397// This is a leaf and cannot come right after a leaf.2398if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2399{2400bc_parse_err(p, BC_ERR_PARSE_EXPR);2401}24022403// Scale needs special work because it can be a variable *or* a2404// function.2405bc_parse_scale(p, &prev, &can_assign, flags);24062407rprn = get_token = bin_last = false;2408nexprs += 1;2409flags &= ~(BC_PARSE_ARRAY);24102411break;2412}24132414case BC_LEX_KW_MODEXP:2415case BC_LEX_KW_DIVMOD:2416{2417// This is a leaf and cannot come right after a leaf.2418if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))2419{2420bc_parse_err(p, BC_ERR_PARSE_EXPR);2421}24222423bc_parse_builtin3(p, t, flags, &prev);24242425rprn = get_token = bin_last = incdec = can_assign = false;2426nexprs += 1;2427flags &= ~(BC_PARSE_ARRAY);24282429break;2430}24312432case BC_LEX_EOF:2433case BC_LEX_INVALID:2434case BC_LEX_NEG:2435case BC_LEX_NLINE:2436case BC_LEX_WHITESPACE:2437case BC_LEX_LBRACKET:2438case BC_LEX_COMMA:2439case BC_LEX_RBRACKET:2440case BC_LEX_LBRACE:2441case BC_LEX_SCOLON:2442case BC_LEX_RBRACE:2443case BC_LEX_KW_AUTO:2444case BC_LEX_KW_BREAK:2445case BC_LEX_KW_CONTINUE:2446case BC_LEX_KW_DEFINE:2447case BC_LEX_KW_FOR:2448case BC_LEX_KW_IF:2449case BC_LEX_KW_LIMITS:2450case BC_LEX_KW_RETURN:2451case BC_LEX_KW_WHILE:2452case BC_LEX_KW_HALT:2453case BC_LEX_KW_PRINT:2454case BC_LEX_KW_QUIT:2455case BC_LEX_KW_STREAM:2456case BC_LEX_KW_ELSE:2457#if DC_ENABLED2458case BC_LEX_EXTENDED_REGISTERS:2459case BC_LEX_EQ_NO_REG:2460case BC_LEX_COLON:2461case BC_LEX_EXECUTE:2462case BC_LEX_PRINT_STACK:2463case BC_LEX_CLEAR_STACK:2464case BC_LEX_REG_STACK_LEVEL:2465case BC_LEX_STACK_LEVEL:2466case BC_LEX_DUPLICATE:2467case BC_LEX_SWAP:2468case BC_LEX_POP:2469case BC_LEX_STORE_IBASE:2470case BC_LEX_STORE_OBASE:2471case BC_LEX_STORE_SCALE:2472#if BC_ENABLE_EXTRA_MATH2473case BC_LEX_STORE_SEED:2474#endif // BC_ENABLE_EXTRA_MATH2475case BC_LEX_LOAD:2476case BC_LEX_LOAD_POP:2477case BC_LEX_STORE_PUSH:2478case BC_LEX_PRINT_POP:2479case BC_LEX_NQUIT:2480case BC_LEX_EXEC_STACK_LENGTH:2481case BC_LEX_SCALE_FACTOR:2482case BC_LEX_ARRAY_LENGTH:2483#endif // DC_ENABLED2484{2485#if BC_DEBUG2486// We should never get here, even in debug builds.2487bc_parse_err(p, BC_ERR_PARSE_TOKEN);2488break;2489#endif // BC_DEBUG2490}2491}24922493if (get_token) bc_lex_next(&p->l);2494}24952496// Now that we have parsed the expression, we need to empty the operator2497// stack.2498while (p->ops.len > ops_bgn)2499{2500top = BC_PARSE_TOP_OP(p);2501assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;25022503// There should not be *any* parens on the stack anymore.2504if (BC_ERR(top == BC_LEX_LPAREN || top == BC_LEX_RPAREN))2505{2506bc_parse_err(p, BC_ERR_PARSE_EXPR);2507}25082509bc_parse_push(p, BC_PARSE_TOKEN_INST(top));25102511// Adjust the number of unused expressions.2512nexprs -= !BC_PARSE_OP_PREFIX(top);2513bc_vec_pop(&p->ops);25142515incdec = false;2516}25172518// There must be only one expression at the top.2519if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERR_PARSE_EXPR);25202521// Check that the next token is correct.2522for (i = 0; i < next.len && t != next.tokens[i]; ++i)2523{2524continue;2525}2526if (BC_ERR(i == next.len && !bc_parse_isDelimiter(p)))2527{2528bc_parse_err(p, BC_ERR_PARSE_EXPR);2529}25302531// Check that POSIX would be happy with the number of relational operators.2532if (!(flags & BC_PARSE_REL) && nrelops)2533{2534bc_parse_err(p, BC_ERR_POSIX_REL_POS);2535}2536else if ((flags & BC_PARSE_REL) && nrelops > 1)2537{2538bc_parse_err(p, BC_ERR_POSIX_MULTIREL);2539}25402541// If this is true, then we might be in a situation where we don't print.2542// We would want to have the increment/decrement operator not make an extra2543// copy if it's not necessary.2544if (!(flags & BC_PARSE_NEEDVAL) && !pfirst)2545{2546// We have the easy case if the last operator was an assignment2547// operator.2548if (assign)2549{2550inst = *((uchar*) bc_vec_top(&p->func->code));2551inst += (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);2552incdec = false;2553}2554// If we have an inc/dec operator and we are *not* printing, implement2555// the optimization to get rid of the extra copy.2556else if (incdec && !(flags & BC_PARSE_PRINT))2557{2558inst = *((uchar*) bc_vec_top(&p->func->code));2559incdec = (inst <= BC_INST_DEC);2560inst = BC_INST_ASSIGN_PLUS_NO_VAL +2561(inst != BC_INST_INC && inst != BC_INST_ASSIGN_PLUS);2562}25632564// This condition allows us to change the previous assignment2565// instruction (which does a copy) for a NO_VAL version, which does not.2566// This condition is set if either of the above if statements ends up2567// being true.2568if (inst >= BC_INST_ASSIGN_POWER_NO_VAL &&2569inst <= BC_INST_ASSIGN_NO_VAL)2570{2571// Pop the previous assignment instruction and push a new one.2572// Inc/dec needs the extra instruction because it is now a binary2573// operator and needs a second operand.2574bc_vec_pop(&p->func->code);2575if (incdec) bc_parse_push(p, BC_INST_ONE);2576bc_parse_push(p, inst);2577}2578}25792580// If we might have to print...2581if ((flags & BC_PARSE_PRINT))2582{2583// With a paren first or the last operator not being an assignment, we2584// *do* want to print.2585if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT);2586}2587// We need to make sure to push a pop instruction for assignment statements2588// that will not print. The print will pop, but without it, we need to pop.2589else if (!(flags & BC_PARSE_NEEDVAL) &&2590(inst < BC_INST_ASSIGN_POWER_NO_VAL ||2591inst > BC_INST_ASSIGN_NO_VAL))2592{2593bc_parse_push(p, BC_INST_POP);2594}25952596// We want to eat newlines if newlines are not a valid ending token.2597// This is for spacing in things like for loop headers.2598//2599// Yes, this is one case where I reuse a variable for a different purpose;2600// in this case, incdec being true now means that newlines are not valid.2601for (incdec = true, i = 0; i < next.len && incdec; ++i)2602{2603incdec = (next.tokens[i] != BC_LEX_NLINE);2604}2605if (incdec)2606{2607while (p->l.t == BC_LEX_NLINE)2608{2609bc_lex_next(&p->l);2610}2611}26122613return BC_PARSE_STATUS_SUCCESS;2614}26152616/**2617* Parses an expression with bc_parse_expr_err(), but throws an error if it gets2618* an empty expression.2619* @param p The parser.2620* @param flags The flags for what is valid in the expression.2621* @param next A set of tokens for what is valid *after* the expression.2622*/2623static void2624bc_parse_expr_status(BcParse* p, uint8_t flags, BcParseNext next)2625{2626BcParseStatus s = bc_parse_expr_err(p, flags, next);26272628if (BC_ERR(s == BC_PARSE_STATUS_EMPTY_EXPR))2629{2630bc_parse_err(p, BC_ERR_PARSE_EMPTY_EXPR);2631}2632}26332634void2635bc_parse_expr(BcParse* p, uint8_t flags)2636{2637assert(p);2638bc_parse_expr_status(p, flags, bc_parse_next_read);2639}2640#endif // BC_ENABLED264126422643