diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index 2f15c019e..e23fc5a87 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -747,21 +747,6 @@ static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node) { ZCC_AssignStmt *snode = (ZCC_AssignStmt *)node; out.Open("assign-stmt"); - switch (snode->AssignOp) - { - case ZCC_EQ: out.AddChar('='); break; - case ZCC_MULEQ: out.Add("*=", 2); break; - case ZCC_DIVEQ: out.Add("/=", 2); break; - case ZCC_MODEQ: out.Add("%=", 2); break; - case ZCC_ADDEQ: out.Add("+=", 2); break; - case ZCC_SUBEQ: out.Add("-=", 2); break; - case ZCC_LSHEQ: out.Add("<<=", 2); break; - case ZCC_RSHEQ: out.Add(">>=", 2); break; - case ZCC_ANDEQ: out.Add("&=", 2); break; - case ZCC_OREQ: out.Add("|=", 2); break; - case ZCC_XOREQ: out.Add("^=", 2); break; - default: BadAssignOp(out, snode->AssignOp); break; - } PrintNodes(out, snode->Dests); PrintNodes(out, snode->Sources); out.Close(); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 0c493d54a..42c3014c1 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -104,7 +104,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line) %parse_accept { DPrintf(DMSG_SPAMMY, "Input accepted\n"); } %parse_failure { /**failed = true;*/ } -%nonassoc EQ MULEQ DIVEQ MODEQ ADDEQ SUBEQ LSHEQ RSHEQ ANDEQ OREQ XOREQ. +%right EQ MULEQ DIVEQ MODEQ ADDEQ SUBEQ LSHEQ RSHEQ ANDEQ OREQ XOREQ URSHEQ. %right QUESTION COLON. %left OROR. %left ANDAND. @@ -1247,6 +1247,67 @@ expr(X) ::= expr(A) OROR expr(B). /* a || b */ BINARY_EXPR(A,B,PEX_BoolOr); X = expr2; } +expr(X) ::= expr(A) EQ expr(B). /* a = b */ +{ + BINARY_EXPR(A,B,PEX_Assign); + X = expr2; +} +expr(X) ::= expr(A) ADDEQ expr(B). /* a += b */ +{ + BINARY_EXPR(A,B,PEX_AddAssign); + X = expr2; +} +expr(X) ::= expr(A) SUBEQ expr(B). /* a -= b */ +{ + BINARY_EXPR(A,B,PEX_SubAssign); + X = expr2; +} +expr(X) ::= expr(A) MULEQ expr(B). /* a *= b */ +{ + BINARY_EXPR(A,B,PEX_MulAssign); + X = expr2; +} +expr(X) ::= expr(A) DIVEQ expr(B). /* a /= b */ +{ + BINARY_EXPR(A,B,PEX_DivAssign); + X = expr2; +} +expr(X) ::= expr(A) MODEQ expr(B). /* a %= b */ +{ + BINARY_EXPR(A,B,PEX_ModAssign); + X = expr2; +} +expr(X) ::= expr(A) LSHEQ expr(B). /* a <<= b */ +{ + BINARY_EXPR(A,B,PEX_LshAssign); + X = expr2; +} +expr(X) ::= expr(A) RSHEQ expr(B). /* a >>= b */ +{ + BINARY_EXPR(A,B,PEX_RshAssign); + X = expr2; +} +expr(X) ::= expr(A) URSHEQ expr(B). /* a >>>= b */ +{ + BINARY_EXPR(A,B,PEX_URshAssign); + X = expr2; +} +expr(X) ::= expr(A) ANDEQ expr(B). /* a &= b */ +{ + BINARY_EXPR(A,B,PEX_AndAssign); + X = expr2; +} +expr(X) ::= expr(A) OREQ expr(B). /* a |= b */ +{ + BINARY_EXPR(A,B,PEX_OrAssign); + X = expr2; +} +expr(X) ::= expr(A) XOREQ expr(B). /* a ^= b */ +{ + BINARY_EXPR(A,B,PEX_XorAssign); + X = expr2; +} + expr(X) ::= expr(A) SCOPE expr(B). { @@ -1402,7 +1463,7 @@ statement(X) ::= expression_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ statement(X) ::= selection_statement(X). statement(X) ::= iteration_statement(X). statement(X) ::= jump_statement(X). -statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } +//statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } statement(X) ::= local_var(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } statement(X) ::= error SEMICOLON. { X = NULL; } @@ -1553,7 +1614,6 @@ for_init(X) ::= for_bump(A). { X = A /*X-overwrites-A*/; } %type for_bump{ZCC_Statement *} for_bump(X) ::= . { X = NULL; } for_bump(X) ::= expression_statement(A). { X = A; /*X-overwrites-A*/ } -for_bump(X) ::= assign_statement(A). { X = A; /*X-overwrites-A*/ } /*----- If Statements -----*/ @@ -1614,28 +1674,19 @@ labeled_statement(X) ::= DEFAULT(T) COLON. /*----- Assignment Statements -----*/ +/* This is no longer being used, in favor of handling assignments as expressions, just like C and C++ do. + Keep this here in case some other parts require assignment syntax or Lua-style multi-assignments become a thing. %type assign_statement{ZCC_AssignStmt *} -assign_statement(X) ::= expr_list(A) assign_op(OP) expr_list(B). [EQ] +assign_statement(X) ::= expr_list(A) EQ expr_list(B). [EQ] { - NEW_AST_NODE(AssignStmt,stmt,OP); - stmt->AssignOp = OP.Int; + NEW_AST_NODE(AssignStmt,stmt,A); + stmt->AssignOp = ZCC_EQ; stmt->Dests = A; stmt->Sources = B; X = stmt; } - -assign_op(X) ::= EQ(T). { X.Int = ZCC_EQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= MULEQ(T). { X.Int = ZCC_MULEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= DIVEQ(T). { X.Int = ZCC_DIVEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= MODEQ(T). { X.Int = ZCC_MODEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= ADDEQ(T). { X.Int = ZCC_ADDEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= SUBEQ(T). { X.Int = ZCC_SUBEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= LSHEQ(T). { X.Int = ZCC_LSHEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= RSHEQ(T). { X.Int = ZCC_RSHEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= ANDEQ(T). { X.Int = ZCC_ANDEQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= OREQ(T). { X.Int = ZCC_OREQ; X.SourceLoc = T.SourceLoc; } -assign_op(X) ::= XOREQ(T). { X.Int = ZCC_XOREQ; X.SourceLoc = T.SourceLoc; } +*/ /*----- Local Variable Definition "Statements" -----*/ diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index eb039f996..b2c58c124 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2373,33 +2373,6 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) break; } - case AST_AssignStmt: - { - auto assign = static_cast(ast); - switch (assign->AssignOp) - { - case ZCC_EQ: - // this ignores multi-assign statements (these should probably be disabled in the grammar.) - return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources)); - - case ZCC_MULEQ: - case ZCC_DIVEQ: - case ZCC_MODEQ: - case ZCC_ADDEQ: - case ZCC_SUBEQ: - case ZCC_LSHEQ: - case ZCC_RSHEQ: - case ZCC_ANDEQ: - case ZCC_OREQ: - case ZCC_XOREQ: - //break; - default: - Error(ast, "Invalid assign statement"); - - } - break; - } - case AST_FuncParm: { auto fparm = static_cast(ast); @@ -2526,6 +2499,23 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_NEQ: return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right); + case PEX_Assign: + return new FxAssign(left, right); +/* + case ZCC_MULEQ: + case ZCC_DIVEQ: + case ZCC_MODEQ: + case ZCC_ADDEQ: + case ZCC_SUBEQ: + case ZCC_LSHEQ: + case ZCC_RSHEQ: + case ZCC_ANDEQ: + case ZCC_OREQ: + case ZCC_XOREQ: + //break; + default: + Error(ast, "Invalid assign statement"); +*/ // todo: These do not have representations in DECORATE and no implementation exists yet. case PEX_LTGTEQ: @@ -2537,6 +2527,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // vector operations will be done later. case PEX_CrossProduct: case PEX_DotProduct: + + default: I_Error("Binary operator %d not implemented yet", op); } diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index eeabb10e5..5c9936988 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -53,6 +53,19 @@ xx(BitXor, ) xx(BoolAnd, ) xx(BoolOr, ) +xx(Assign, ) +xx(AddAssign, ) +xx(SubAssign, ) +xx(MulAssign, ) +xx(DivAssign, ) +xx(ModAssign, ) +xx(LshAssign, ) +xx(RshAssign, ) +xx(URshAssign, ) +xx(AndAssign, ) +xx(OrAssign, ) +xx(XorAssign, ) + xx(Scope, ) xx(Trinary, ) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 48fd28f45..222e8e6c5 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -73,6 +73,7 @@ static void InitTokenMap() TOKENDEF (TK_SubEq, ZCC_SUBEQ); TOKENDEF (TK_LShiftEq, ZCC_LSHEQ); TOKENDEF (TK_RShiftEq, ZCC_RSHEQ); + TOKENDEF (TK_URShiftEq, ZCC_URSHEQ); TOKENDEF (TK_AndEq, ZCC_ANDEQ); TOKENDEF (TK_OrEq, ZCC_OREQ); TOKENDEF (TK_XorEq, ZCC_XOREQ);