|
@@ -304,6 +304,7 @@ typedef struct {
|
|
|
T_THROW,
|
|
|
T_GOTO,
|
|
|
T_CLASS,
|
|
|
+ T_DEL,
|
|
|
T_IS,
|
|
|
T_IN,
|
|
|
|
|
@@ -425,7 +426,7 @@ char *traverse(char *source, size_t pos, size_t *line, size_t *col) {
|
|
|
(*line)++;
|
|
|
(*col) = 1;
|
|
|
|
|
|
- p = i;
|
|
|
+ p = i+1;
|
|
|
} else (*col)++;
|
|
|
}
|
|
|
|
|
@@ -448,6 +449,15 @@ void format_error(char *filename, char *source, size_t pos, char *fmt, ...) {
|
|
|
if (!*src)
|
|
|
return;
|
|
|
|
|
|
+ int empty = 1;
|
|
|
+ for (size_t i = 0; src[i] && src[i] != '\n'; i++)
|
|
|
+ if (!isspace(src[i])) {
|
|
|
+ empty = 0; break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (empty)
|
|
|
+ return;
|
|
|
+
|
|
|
fputc('\t', stderr);
|
|
|
|
|
|
for (size_t i = 0; src[i] && src[i] != '\n' && i < 64; i++)
|
|
@@ -666,6 +676,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(GOTO);
|
|
|
else if (strcmp(name, "class") == 0)
|
|
|
return TK(CLASS);
|
|
|
+ else if (strcmp(name, "del") == 0)
|
|
|
+ return TK(DEL);
|
|
|
else if (strcmp(name, "is") == 0)
|
|
|
return TK(IS);
|
|
|
else if (strcmp(name, "in") == 0)
|
|
@@ -810,6 +822,7 @@ struct _node_t {
|
|
|
|
|
|
N_NOT,
|
|
|
N_NEGATE,
|
|
|
+ N_UNARY_PLUS,
|
|
|
N_BNOT,
|
|
|
|
|
|
N_LITERAL,
|
|
@@ -889,6 +902,7 @@ struct _node_t {
|
|
|
N_LABEL,
|
|
|
N_GOTO,
|
|
|
N_CLASS,
|
|
|
+ N_DEL,
|
|
|
|
|
|
N_INLINE,
|
|
|
N_HEADER,
|
|
@@ -1249,11 +1263,11 @@ node_t *parse_primary(list_t *tokens, size_t *pos) {
|
|
|
} else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) || MATCH(NAME))
|
|
|
return NODET(LITERAL, tokens->data[(*pos)-1]);
|
|
|
|
|
|
- if (AT(RPAR)) {
|
|
|
+ if (MATCH(RPAR)) {
|
|
|
PARSE_ERROR("extraneous )");
|
|
|
- } else if (AT(RSB)) {
|
|
|
+ } else if (MATCH(RSB)) {
|
|
|
PARSE_ERROR("extraneous ]");
|
|
|
- } else if (AT(RCB)) {
|
|
|
+ } else if (MATCH(RCB)) {
|
|
|
PARSE_ERROR("extraneous }");
|
|
|
} else {
|
|
|
PARSE_ERROR("expected expression");
|
|
@@ -1350,6 +1364,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(PLUS)) {
|
|
|
+ node_t *a = parse_unary(tokens, pos);
|
|
|
+
|
|
|
+ return NODE1(UNARY_PLUS, a);
|
|
|
} else if (MATCH(BANG)) {
|
|
|
node_t *a = parse_unary(tokens, pos);
|
|
|
|
|
@@ -2182,6 +2200,10 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
|
list_push(pair, triples);
|
|
|
|
|
|
return NODETL(CLASS, t, pair);
|
|
|
+ } else if (MATCH(DEL)) {
|
|
|
+ node_t *a = parse_expr(tokens, pos);
|
|
|
+
|
|
|
+ return NODE1(DEL, a);
|
|
|
} else if (MATCH(INLINE)) {
|
|
|
if (!AT(STRING))
|
|
|
PARSE_ERROR("expected string");
|
|
@@ -4219,6 +4241,21 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
case N_CLASS: break;
|
|
|
case N_PASS: break;
|
|
|
|
|
|
+ case N_DEL:
|
|
|
+ EMIT("qi_del(state, ");
|
|
|
+
|
|
|
+ if (node->a->tag == N_INDEX) {
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a->a);
|
|
|
+ EMIT(", ");
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a->b);
|
|
|
+ } else if (node->a->tag == N_MEMBER) {
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a->a);
|
|
|
+ EMIT(", qi_make_string(state, \"%s\")", node->a->t->text);
|
|
|
+ } else COMPILE_ERROR("not a index/member expression");
|
|
|
+
|
|
|
+ EMIT(");");
|
|
|
+ break;
|
|
|
+
|
|
|
case N_TRY:
|
|
|
EMIT("qi_try(state, {\n");
|
|
|
LBPUSH();
|
|
@@ -4405,6 +4442,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
UNOP("negate");
|
|
|
break;
|
|
|
|
|
|
+ case N_UNARY_PLUS:
|
|
|
+ UNOP("unary_plus");
|
|
|
+ break;
|
|
|
+
|
|
|
case N_NOT:
|
|
|
UNOP("not");
|
|
|
break;
|