// These are more sensical predicate names in most contexts in this file
#define LEFT(tok) ((tok)->children)
#define RIGHT(tok) ((tok)->lastChild)
+#define UNARY(tok) (LEFT(tok) && LEFT(tok) == RIGHT(tok))
#define BINARY(tok) (LEFT(tok) && RIGHT(tok) && LEFT(tok)->next == RIGHT(tok))
// Forward references for recursion
static int defArg(struct Parser* p, struct Token* t)
{
- if(t->type == TOK_LPAR) return defArg(p, RIGHT(t));
+ if(t->type == TOK_LPAR) {
+ // http://code.google.com/p/flightgear-bugs/issues/detail?id=737
+ // TOK_LPAR can mean multi-value assignment or function call,
+ // disambigaute by checking the rule of the token
+ if (t->rule == PREC_SUFFIX)
+ naParseError(p, "default arguments cannot be function calls", t->line);
+ return defArg(p, RIGHT(t));
+ }
+
if(t->type == TOK_MINUS && RIGHT(t) &&
RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str)
{
RIGHT(t)->num *= -1;
return defArg(p, RIGHT(t));
}
+ if(t->type == TOK_CAT && RIGHT(t) &&
+ RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str)
+ {
+ /* default arguments are constants, but "~1" parses as two
+ * tokens, so we have to subset the expression generator for that
+ * case */
+ RIGHT(t)->num = ~(int)RIGHT(t)->num;
+ return defArg(p, RIGHT(t));
+ }
return findConstantIndex(p, t);
}
static void genBreakContinue(struct Parser* p, struct Token* t)
{
int levels = 1, loop = -1, bp, cp, i;
+ // http://code.google.com/p/flightgear-bugs/issues/detail?id=587
+ // Make sure we are inside of a loop
+ if(p->cg->loopTop <= 0)
+ naParseError(p, "break/continue outside of a valid loop", t->line);
+
if(RIGHT(t)) {
if(RIGHT(t)->type != TOK_SYMBOL)
naParseError(p, "bad break/continue label", t->line);
{
struct Token *lv = LEFT(t), *rv = RIGHT(t);
int len, dummy, var=0;
+ if (!lv)
+ naParseError(p, "bad assignment, missing variable", t->line);
+ else
if(parListLen(lv) || (lv->type == TOK_VAR && parListLen(RIGHT(lv)))) {
if(lv->type == TOK_VAR) { lv = RIGHT(lv); var = 1; }
len = parListLen(lv);
- if(rv->type == TOK_LPAR) {
+ // http://code.google.com/p/flightgear-bugs/issues/detail?id=585
+ // TOK_LPAR can mean multi-value assignment or function call,
+ // disambigaute by checking the rule of the token
+ if(rv->type == TOK_LPAR && rv->rule != PREC_SUFFIX) {
if(len != parListLen(rv))
naParseError(p, "bad assignment count", rv->line);
genCommaList(p, LEFT(rv));
else genExpr(p, LEFT(t));
break;
case TOK_LBRA:
- if(BINARY(t)) {
- genExtract(p, t);
- } else {
+ if(UNARY(t)) {
emit(p, OP_NEWVEC);
genList(p, LEFT(t), 1);
}
+ else if(BINARY(t)) {
+ genExtract(p, t);
+ } else {
+ // forbid usage as 'vec[]'
+ naParseError(p, "missing index or slice expression(s)", t->line);
+ }
break;
case TOK_LCURL:
emit(p, OP_NEWHASH);
genExpr(p, RIGHT(t)); // unary negation (see also TOK_MINUS!)
emit(p, OP_NEG);
break;
+ case TOK_CAT:
+ if(BINARY(t)) {
+ genBinOp(OP_CAT, p, t); // string concatenation
+ } else if(RIGHT(t) && RIGHT(t)->type == TOK_LITERAL && !RIGHT(t)->str) {
+ RIGHT(t)->num = ~(int)RIGHT(t)->num; // Pre-negate constants
+ genScalarConstant(p, RIGHT(t));
+ } else {
+ genExpr(p, RIGHT(t)); // unary, bitwise negation
+ emit(p, OP_BIT_NEG);
+ }
+ break;
+ case TOK_BIT_NEG:
+ genExpr(p, RIGHT(t)); // unary, bitwise negation (see also TOK_CAT!)
+ emit(p, OP_BIT_NEG);
+ break;
case TOK_DOT:
genExpr(p, LEFT(t));
if(!RIGHT(t) || RIGHT(t)->type != TOK_SYMBOL)
case TOK_AND: case TOK_OR:
genShortCircuit(p, t);
break;
+ case TOK_BIT_AND:genBinOp(OP_BIT_AND, p, t); break;
+ case TOK_BIT_OR: genBinOp(OP_BIT_OR, p, t); break;
+ case TOK_BIT_XOR:genBinOp(OP_BIT_XOR, p, t); break;
case TOK_MUL: genBinOp(OP_MUL, p, t); break;
case TOK_PLUS: genBinOp(OP_PLUS, p, t); break;
case TOK_DIV: genBinOp(OP_DIV, p, t); break;
- case TOK_CAT: genBinOp(OP_CAT, p, t); break;
case TOK_LT: genBinOp(OP_LT, p, t); break;
case TOK_LTE: genBinOp(OP_LTE, p, t); break;
case TOK_EQ: genBinOp(OP_EQ, p, t); break;
case TOK_MULEQ: genEqOp(OP_MUL, p, t); break;
case TOK_DIVEQ: genEqOp(OP_DIV, p, t); break;
case TOK_CATEQ: genEqOp(OP_CAT, p, t); break;
+ case TOK_BIT_ANDEQ: genEqOp(OP_BIT_AND, p, t); break;
+ case TOK_BIT_OREQ: genEqOp(OP_BIT_OR, p, t); break;
+ case TOK_BIT_XOREQ: genEqOp(OP_BIT_XOR, p, t); break;
default:
naParseError(p, "parse error", t->line);
};