diff --git a/CHANGES.txt b/CHANGES.txt index dac55446..9d06e6bd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -13,6 +13,9 @@ Bug fixes: Scripting: * Added type_name function + * nil != "", so missing values are no longer equal to the empty string + * The `=` operator is now deprecated, use `==` for comparisons, `:=` for assignment. + * if statements without an else will now produce a warning if their result is used. Internal: * Switch build system to to CMake diff --git a/src/script/parser.cpp b/src/script/parser.cpp index 56c07720..044a7dea 100644 --- a/src/script/parser.cpp +++ b/src/script/parser.cpp @@ -381,13 +381,24 @@ enum Precedence , PREC_NONE }; +/// Type of expressions. Broadly: LHS/exprssion/statement +enum ExprType +{ EXPR_VAR // A single variable, which could be converted to the left hand side of an assignment +, EXPR_STATEMENT // A 'statement', i.e. an expression that doesn't produce a result, and shouldn't be the last one in a block +, EXPR_OTHER +, EXPR_FAILED +}; + /// Parse an expression /** @param input Read tokens from the input * @param scrip Add resulting instructions to the script * @param min_prec Minimum precedence level for operators + * + * @returns the type of expression + * * NOTE: The net stack effect of an expression should be +1 */ -void parseExpr(TokenIterator& input, Script& script, Precedence min_prec); +ExprType parseExpr(TokenIterator& input, Script& script, Precedence min_prec); /// Parse an expression, possibly with operators applied. Optionally adds an instruction at the end. /** @param input Read tokens from the input @@ -397,7 +408,7 @@ void parseExpr(TokenIterator& input, Script& script, Precedence min_prec); * @param close_with_data Data for the instruction at the end * NOTE: The net stack effect of an expression should be +1 */ -void parseOper(TokenIterator& input, Script& script, Precedence min_prec, InstructionType close_with = I_NOP, int close_with_data = 0); +ExprType parseOper(TokenIterator& input, Script& script, Precedence min_prec, InstructionType close_with = I_NOP, int close_with_data = 0); /// Parse call arguments, "(...)" void parseCallArguments(TokenIterator& input, Script& script, vector& arguments); @@ -408,16 +419,16 @@ ScriptP parse(const String& s, Packaged* package, bool string_mode, vector subScript(new Script); - parseOper(input, *subScript, PREC_ALL); - expectToken(input, _("}"), &token); - script.addInstruction(I_PUSH_CONST, subScript); - } else if (token == _("[")) { - // [] = list or map literal - unsigned int count = 0; - Token t = input.peek(); - while (t != _("]") && t != TOK_EOF) { - if (input.peek(2) == _(":") && (t.type == TOK_NAME || t.type == TOK_INT || t.type == TOK_STRING)) { - // name: ... - script.addInstruction(I_PUSH_CONST, to_script(t.value)); - input.read(); // skip the name - input.read(); // and the : - } else { - // implicit numbered element - script.addInstruction(I_PUSH_CONST, script_nil); - } - parseOper(input, script, PREC_AND); - ++count; - t = input.peek(); - if (t == _(",")) { - // Comma separating the elements - input.read(); - t = input.peek(); - } +ExprType parseExpr(TokenIterator& input, Script& script, Precedence minPrec) { + Token token = input.read(); + if (token == _("(")) { + // Parentheses = grouping for precedence of expressions + ExprType type = parseOper(input, script, PREC_ALL); + expectToken(input, _(")"), &token); + return type; + } else if (token == _("{")) { + // {} = function block. Parse a new Script + intrusive_ptr