|
@@ -295,6 +295,8 @@ typedef struct {
|
|
|
T_CATCH,
|
|
|
T_THROW,
|
|
|
T_GOTO,
|
|
|
+ T_IS,
|
|
|
+ T_IN,
|
|
|
|
|
|
T_LPAR,
|
|
|
T_RPAR,
|
|
@@ -304,6 +306,7 @@ typedef struct {
|
|
|
T_RCB,
|
|
|
|
|
|
T_EQUALS,
|
|
|
+ T_NOTEQUALS,
|
|
|
T_PLUSASSIGN,
|
|
|
T_BARBAR,
|
|
|
T_ANDAND,
|
|
@@ -325,8 +328,10 @@ typedef struct {
|
|
|
T_GTGT,
|
|
|
T_STAR,
|
|
|
T_SLASH,
|
|
|
+ T_PERCENT,
|
|
|
T_COMMA,
|
|
|
T_DOT,
|
|
|
+ T_BANG,
|
|
|
|
|
|
T_ASSIGN,
|
|
|
T_SEMI
|
|
@@ -553,10 +558,16 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(THROW);
|
|
|
else if (strcmp(name, "goto") == 0)
|
|
|
return TK(GOTO);
|
|
|
+ else if (strcmp(name, "is") == 0)
|
|
|
+ return TK(IS);
|
|
|
+ else if (strcmp(name, "in") == 0)
|
|
|
+ return TK(IN);
|
|
|
|
|
|
return token(T_NAME, name);
|
|
|
} else if (strncmp(&source[*pos], "==", 2) == 0 && ++(*pos) && ++(*pos))
|
|
|
return TK(EQUALS);
|
|
|
+ else if (strncmp(&source[*pos], "!=", 2) == 0 && ++(*pos) && ++(*pos))
|
|
|
+ return TK(NOTEQUALS);
|
|
|
else if (strncmp(&source[*pos], "+=", 2) == 0 && ++(*pos) && ++(*pos))
|
|
|
return TK(PLUSASSIGN);
|
|
|
else if (strncmp(&source[*pos], "||", 2) == 0 && ++(*pos) && ++(*pos))
|
|
@@ -571,6 +582,10 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(SLASHSLASH);
|
|
|
else if (strncmp(&source[*pos], "**", 2) == 0 && ++(*pos) && ++(*pos))
|
|
|
return TK(STARSTAR);
|
|
|
+ else if (strncmp(&source[*pos], "<<", 2) == 0 && ++(*pos) && ++(*pos))
|
|
|
+ return TK(LTLT);
|
|
|
+ else if (strncmp(&source[*pos], ">>", 2) == 0 && ++(*pos) && ++(*pos))
|
|
|
+ return TK(GTGT);
|
|
|
else if (source[*pos] == '(' && ++(*pos))
|
|
|
return TK(LPAR);
|
|
|
else if (source[*pos] == ')' && ++(*pos))
|
|
@@ -591,6 +606,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(STAR);
|
|
|
else if (source[*pos] == '/' && ++(*pos))
|
|
|
return TK(SLASH);
|
|
|
+ else if (source[*pos] == '%' && ++(*pos))
|
|
|
+ return TK(PERCENT);
|
|
|
else if (source[*pos] == '?' && ++(*pos))
|
|
|
return TK(QM);
|
|
|
else if (source[*pos] == ':' && ++(*pos))
|
|
@@ -607,6 +624,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(LT);
|
|
|
else if (source[*pos] == '>' && ++(*pos))
|
|
|
return TK(GT);
|
|
|
+ else if (source[*pos] == '!' && ++(*pos))
|
|
|
+ return TK(BANG);
|
|
|
|
|
|
LEX_ERROR("unexpected input")
|
|
|
}
|
|
@@ -640,6 +659,7 @@ struct _node_t {
|
|
|
|
|
|
N_BLOCK,
|
|
|
|
|
|
+ N_NOT,
|
|
|
N_NEGATE,
|
|
|
|
|
|
N_LITERAL,
|
|
@@ -657,12 +677,21 @@ struct _node_t {
|
|
|
N_MUL,
|
|
|
N_DIV,
|
|
|
N_IDIV,
|
|
|
+ N_MOD,
|
|
|
N_POW,
|
|
|
+ N_SHL,
|
|
|
+ N_SHR,
|
|
|
|
|
|
N_ASSIGN,
|
|
|
N_ASSIGN_ADD,
|
|
|
|
|
|
N_EQUALS,
|
|
|
+ N_NOTEQUALS,
|
|
|
+ N_IS,
|
|
|
+ N_IN,
|
|
|
+ N_NOTIS,
|
|
|
+ N_NOTIN,
|
|
|
+
|
|
|
N_LT,
|
|
|
N_GT,
|
|
|
|
|
@@ -1011,6 +1040,10 @@ node_t *parse_unary(list_t *tokens, size_t *pos) {
|
|
|
node_t *a = parse_unary(tokens, pos);
|
|
|
|
|
|
return NODE1(NEGATE, a);
|
|
|
+ } else if (MATCH(BANG)) {
|
|
|
+ node_t *a = parse_unary(tokens, pos);
|
|
|
+
|
|
|
+ return NODE1(NOT, a);
|
|
|
}
|
|
|
|
|
|
return parse_postfix(tokens, pos);
|
|
@@ -1055,6 +1088,12 @@ node_t *parse_mul(list_t *tokens, size_t *pos) {
|
|
|
|
|
|
a = NODE2(IDIV, a, b);
|
|
|
|
|
|
+ continue;
|
|
|
+ } else if (MATCH(PERCENT)) {
|
|
|
+ node_t *b = parse_pow(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(MOD, a, b);
|
|
|
+
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -1091,6 +1130,23 @@ node_t *parse_add(list_t *tokens, size_t *pos) {
|
|
|
node_t *parse_shift(list_t *tokens, size_t *pos) {
|
|
|
node_t *a = parse_add(tokens, pos);
|
|
|
|
|
|
+ do {
|
|
|
+ if (MATCH(LTLT)) {
|
|
|
+ node_t *b = parse_add(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(SHL, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ } else if (MATCH(GTGT)) {
|
|
|
+ node_t *b = parse_add(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(SHR, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ } while (1);
|
|
|
+
|
|
|
return a;
|
|
|
}
|
|
|
|
|
@@ -1127,6 +1183,42 @@ node_t *parse_equality(list_t *tokens, size_t *pos) {
|
|
|
|
|
|
a = NODE2(EQUALS, a, b);
|
|
|
|
|
|
+ continue;
|
|
|
+ } else if (MATCH(NOTEQUALS)) {
|
|
|
+ node_t *b = parse_relation(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(NOTEQUALS, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ } else if (MATCH(IS)) {
|
|
|
+ node_t *b = parse_relation(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(IS, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ } else if (AT(BANG) && ATP(IS, 1)) {
|
|
|
+ EXPECT(BANG, "!");
|
|
|
+ EXPECT(IS, "is");
|
|
|
+
|
|
|
+ node_t *b = parse_relation(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(NOTIS, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ } else if (MATCH(IN)) {
|
|
|
+ node_t *b = parse_relation(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(IN, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ } else if (AT(BANG) && ATP(IN, 1)) {
|
|
|
+ EXPECT(BANG, "!");
|
|
|
+ EXPECT(IN, "in");
|
|
|
+
|
|
|
+ node_t *b = parse_relation(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(NOTIN, a, b);
|
|
|
+
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -2073,6 +2165,26 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, lis
|
|
|
BINOP("equals");
|
|
|
break;
|
|
|
|
|
|
+ case N_NOTEQUALS:
|
|
|
+ BINOP("not_equals");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_IS:
|
|
|
+ BINOP("is");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_NOTIS:
|
|
|
+ BINOP("not_is");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_IN:
|
|
|
+ BINOP("in");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_NOTIN:
|
|
|
+ BINOP("not_in");
|
|
|
+ break;
|
|
|
+
|
|
|
case N_LT:
|
|
|
BINOP("lt");
|
|
|
break;
|
|
@@ -2101,14 +2213,30 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, lis
|
|
|
BINOP("idiv");
|
|
|
break;
|
|
|
|
|
|
+ case N_MOD:
|
|
|
+ BINOP("mod");
|
|
|
+ break;
|
|
|
+
|
|
|
case N_POW:
|
|
|
BINOP("pow");
|
|
|
break;
|
|
|
|
|
|
+ case N_SHL:
|
|
|
+ BINOP("shl");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_SHR:
|
|
|
+ BINOP("shr");
|
|
|
+ break;
|
|
|
+
|
|
|
case N_NEGATE:
|
|
|
UNOP("negate");
|
|
|
break;
|
|
|
|
|
|
+ case N_NOT:
|
|
|
+ UNOP("not");
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
COMPILE_ERROR("not yet implemented");
|
|
|
}
|