/* ParseExpr3 - handle the BXOR operator */ static ParseTreeNode *ParseExpr3(ParseContext *c) { ParseTreeNode *expr, *expr2; int tkn; expr = ParseExpr4(c); while ((tkn = GetToken(c)) == '^') { expr2 = ParseExpr4(c); if (IsIntegerLit(expr) && IsIntegerLit(expr2)) expr->u.integerLit.value = expr->u.integerLit.value ^ expr2->u.integerLit.value; else expr = MakeBinaryOpNode(c, OP_BXOR, expr, expr2); } SaveToken(c,tkn); return expr; }
/* ParseArrayInitializers - parse array initializers */ static void ParseArrayInitializers(ParseContext *c, VMVALUE size) { VMVALUE *dataPtr = (VMVALUE *)c->codeBuf; VMVALUE *dataTop = (VMVALUE *)c->ctop; int done = VMFALSE; Token tkn; FRequire(c, '{'); /* handle each line of initializers */ while (!done) { int lineDone = VMFALSE; /* look for the first non-blank line */ while ((tkn = GetToken(c)) == T_EOL) { if (!GetLine(c)) ParseError(c, "unexpected end of file in initializers"); } /* check for the end of the initializers */ if (tkn == '}') break; SaveToken(c, tkn); /* handle each initializer in the current line */ while (!lineDone) { ParseTreeNode *expr; /* get a constant expression */ expr = ParseExpr(c); if (!IsIntegerLit(expr)) ParseError(c, "expecting a constant expression"); /* check for too many initializers */ if (--size < 0) ParseError(c, "too many initializers"); /* store the initial value */ if (dataPtr >= dataTop) ParseError(c, "insufficient object data space"); *dataPtr++ = expr->u.integerLit.value; switch (tkn = GetToken(c)) { case T_EOL: lineDone = VMTRUE; break; case '}': lineDone = VMTRUE; done = VMTRUE; break; case ',': break; default: ParseError(c, "expecting a comma, right brace or end of line"); break; } } } }
/* ParseScalarInitializer - parse a scalar initializer */ static VMVALUE ParseScalarInitializer(ParseContext *c) { ParseTreeNode *expr = ParseExpr(c); if (!IsIntegerLit(expr)) ParseError(c, "expecting a constant expression"); return expr->u.integerLit.value; }
/* ParseExpr8 - handle the '<<' and '>>' operators */ static ParseTreeNode *ParseExpr8(ParseContext *c) { ParseTreeNode *expr, *expr2; int tkn; expr = ParseExpr9(c); while ((tkn = GetToken(c)) == T_SHL || tkn == T_SHR) { expr2 = ParseExpr9(c); if (IsIntegerLit(expr) && IsIntegerLit(expr2)) { switch (tkn) { case T_SHL: expr->u.integerLit.value = expr->u.integerLit.value << expr2->u.integerLit.value; break; case T_SHR: expr->u.integerLit.value = expr->u.integerLit.value >> expr2->u.integerLit.value; break; default: /* not reached */ break; } } else { int op; switch (tkn) { case T_SHL: op = OP_SHL; break; case T_SHR: op = OP_SHR; break; default: /* not reached */ op = 0; break; } expr = MakeBinaryOpNode(c, op, expr, expr2); } }
/* ParseVariableDecl - parse a variable declaration */ static int ParseVariableDecl(ParseContext *c, char *name, VMVALUE *pSize) { Token tkn; /* parse the variable name */ FRequire(c, T_IDENTIFIER); strcpy(name, c->token); /* handle arrays */ if ((tkn = GetToken(c)) == '[') { int size; /* check for an array with unspecified size */ if ((tkn = GetToken(c)) == ']') size = 0; /* otherwise, parse the array size */ else { ParseTreeNode *expr; /* put back the token */ SaveToken(c, tkn); /* get the array size */ expr = ParseExpr(c); /* make sure it's a constant */ if (!IsIntegerLit(expr) || expr->u.integerLit.value <= 0) ParseError(c, "expecting a positive constant expression"); size = expr->u.integerLit.value; /* only one dimension allowed for now */ FRequire(c, ']'); } /* return an array and its size */ *pSize = size; return VMTRUE; } /* not an array */ else SaveToken(c, tkn); /* return a scalar */ return VMFALSE; }
/* ParseConstantDef - parse a 'DEF <name> =' statement */ static void ParseConstantDef(ParseContext *c, char *name) { ParseTreeNode *expr; Symbol *sym; /* get the constant value */ expr = ParseExpr(c); /* make sure it's a constant */ if (!IsIntegerLit(expr)) ParseError(c, "expecting a constant expression"); /* add the symbol as a global */ sym = AddGlobal(c, name, SC_CONSTANT, expr->u.integerLit.value, 0); FRequire(c, T_EOL); }