aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-01-03 18:02:13 +0000
committerGinger Bill <bill@gingerbill.org>2017-01-03 18:02:13 +0000
commita86896e4d30b118287cf2111cd2fbec00ed2be70 (patch)
tree15198095de38744739e239bfac3c160dfa936d58 /src
parenta3883a178c1e4e10058089a2832004a6ce1521e2 (diff)
Interval expressions in `range`
Diffstat (limited to 'src')
-rw-r--r--src/checker/expr.c5
-rw-r--r--src/checker/stmt.c132
-rw-r--r--src/parser.c52
-rw-r--r--src/ssa.c177
-rw-r--r--src/tokenizer.c53
5 files changed, 306 insertions, 113 deletions
diff --git a/src/checker/expr.c b/src/checker/expr.c
index 3c7403143..bf1303e4c 100644
--- a/src/checker/expr.c
+++ b/src/checker/expr.c
@@ -3790,6 +3790,11 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
goto error;
case_end;
+ case_ast_node(i, IntervalExpr, node);
+ error_node(node, "Invalid use of an interval expression");
+ goto error;
+ case_end;
+
case_ast_node(i, Ident, node);
check_identifier(c, o, node, type_hint);
case_end;
diff --git a/src/checker/stmt.c b/src/checker/stmt.c
index 60154855f..6113c519a 100644
--- a/src/checker/stmt.c
+++ b/src/checker/stmt.c
@@ -594,42 +594,116 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
check_open_scope(c, node);
+ Type *val = NULL;
+ Type *idx = NULL;
+ Entity *entities[2] = {0};
+ isize entity_count = 0;
- Operand operand = {Addressing_Invalid};
- check_expr(c, &operand, rs->expr);
- Type *key = NULL;
- Type *val = NULL;
- if (operand.mode != Addressing_Invalid) {
- Type *t = base_type(type_deref(operand.type));
- switch (t->kind) {
- case Type_Basic:
- if (is_type_string(t)) {
- key = t_int;
- val = t_rune;
+ if (rs->expr != NULL && rs->expr->kind == AstNode_IntervalExpr) {
+ ast_node(ie, IntervalExpr, rs->expr);
+ Operand x = {Addressing_Invalid};
+ Operand y = {Addressing_Invalid};
+
+ check_expr(c, &x, ie->left);
+ if (x.mode == Addressing_Invalid) {
+ goto skip_expr;
+ }
+ check_expr(c, &y, ie->right);
+ if (y.mode == Addressing_Invalid) {
+ goto skip_expr;
+ }
+
+ convert_to_typed(c, &x, y.type, 0);
+ if (x.mode == Addressing_Invalid) {
+ goto skip_expr;
+ }
+ convert_to_typed(c, &y, x.type, 0);
+ if (y.mode == Addressing_Invalid) {
+ goto skip_expr;
+ }
+
+ convert_to_typed(c, &x, default_type(y.type), 0);
+ if (x.mode == Addressing_Invalid) {
+ goto skip_expr;
+ }
+ convert_to_typed(c, &y, default_type(x.type), 0);
+ if (y.mode == Addressing_Invalid) {
+ goto skip_expr;
+ }
+
+ if (!are_types_identical(x.type, y.type)) {
+ if (x.type != t_invalid &&
+ y.type != t_invalid) {
+ gbString xt = type_to_string(x.type);
+ gbString yt = type_to_string(y.type);
+ gbString expr_str = expr_to_string(x.expr);
+ error(ie->op, "Mismatched types in interval expression `%s` : `%s` vs `%s`", expr_str, xt, yt);
+ gb_string_free(expr_str);
+ gb_string_free(yt);
+ gb_string_free(xt);
}
- break;
- case Type_Array:
- key = t_int;
- val = t->Array.elem;
- break;
- case Type_Slice:
- key = t_int;
- val = t->Array.elem;
- break;
+ goto skip_expr;
}
- }
- if (key == NULL) {
- gbString s = expr_to_string(operand.expr);
- error_node(operand.expr, "Cannot iterate over %s", s);
- gb_string_free(s);
+ if (!is_type_integer(x.type) && !is_type_float(x.type)) {
+ error(ie->op, "Only numerical types are allowed within interval expressions");
+ goto skip_expr;
+ }
+
+ if (x.mode == Addressing_Constant &&
+ y.mode == Addressing_Constant) {
+ ExactValue a = x.value;
+ ExactValue b = y.value;
+
+ GB_ASSERT(are_types_identical(x.type, y.type));
+
+ bool ok = compare_exact_values(Token_Lt, a, b);
+ if (!ok) {
+ // TODO(bill): Better error message
+ error(ie->op, "Invalid interval expression");
+ goto skip_expr;
+ }
+ }
+
+ add_type_and_value(&c->info, ie->left, x.mode, x.type, x.value);
+ add_type_and_value(&c->info, ie->right, y.mode, y.type, y.value);
+ val = x.type;
+ idx = t_int;
+ } else {
+ Operand operand = {Addressing_Invalid};
+ check_expr(c, &operand, rs->expr);
+
+ if (operand.mode != Addressing_Invalid) {
+ Type *t = base_type(type_deref(operand.type));
+ switch (t->kind) {
+ case Type_Basic:
+ if (is_type_string(t)) {
+ val = t_rune;
+ idx = t_int;
+ }
+ break;
+ case Type_Array:
+ val = t->Array.elem;
+ idx = t_int;
+ break;
+ case Type_Slice:
+ val = t->Array.elem;
+ idx = t_int;
+ break;
+ }
+ }
+
+ if (val == NULL) {
+ gbString s = expr_to_string(operand.expr);
+ error_node(node, "Cannot iterate over %s", s);
+ gb_string_free(s);
+ }
}
- Entity *entities[2] = {0};
- isize entity_count = 0;
- AstNode *lhs[2] = {rs->key, rs->value};
- Type * rhs[2] = {key, val};
+ skip_expr:
+ AstNode *lhs[2] = {rs->value, rs->index};
+ Type * rhs[2] = {val, idx};
for (isize i = 0; i < 2; i++) {
if (lhs[i] == NULL) {
diff --git a/src/parser.c b/src/parser.c
index da87a6c7c..1332fd929 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -160,6 +160,7 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
AstNode *body; \
AstNode *else_expr; \
}) \
+ AST_NODE_KIND(IntervalExpr, "interval expression", struct { Token op; AstNode *left, *right; }) \
AST_NODE_KIND(_ExprEnd, "", i32) \
AST_NODE_KIND(_StmtBegin, "", i32) \
AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
@@ -205,11 +206,11 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
AstNode *body; \
}) \
AST_NODE_KIND(RangeStmt, "range statement", struct { \
- Token token; \
- AstNode * key; \
- AstNode * value; \
- AstNode * expr; \
- AstNode * body; \
+ Token token; \
+ AstNode *value; \
+ AstNode *index; \
+ AstNode *expr; \
+ AstNode *body; \
}) \
AST_NODE_KIND(CaseClause, "case clause", struct { \
Token token; \
@@ -451,6 +452,8 @@ Token ast_node_token(AstNode *node) {
return node->GiveExpr.token;
case AstNode_IfExpr:
return node->IfExpr.token;
+ case AstNode_IntervalExpr:
+ return ast_node_token(node->IntervalExpr.left);
case AstNode_BadStmt:
return node->BadStmt.begin;
@@ -700,6 +703,18 @@ AstNode *make_demaybe_expr(AstFile *f, AstNode *expr, Token op) {
return result;
}
+AstNode *make_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
+ AstNode *result = make_node(f, AstNode_IntervalExpr);
+
+ result->IntervalExpr.op = op;
+ result->IntervalExpr.left = left;
+ result->IntervalExpr.right = right;
+
+ return result;
+}
+
+
+
AstNode *make_basic_lit(AstFile *f, Token basic_lit) {
AstNode *result = make_node(f, AstNode_BasicLit);
@@ -854,12 +869,12 @@ AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, As
result->ForStmt.body = body;
return result;
}
-AstNode *make_range_stmt(AstFile *f, Token token, AstNode *key, AstNode *value, AstNode *expr, AstNode *body) {
+AstNode *make_range_stmt(AstFile *f, Token token, AstNode *value, AstNode *index, AstNode *expr, AstNode *body) {
AstNode *result = make_node(f, AstNode_RangeStmt);
result->RangeStmt.token = token;
- result->RangeStmt.key = key;
result->RangeStmt.value = value;
- result->RangeStmt.expr = expr;
+ result->RangeStmt.index = index;
+ result->RangeStmt.expr = expr;
result->RangeStmt.body = body;
return result;
}
@@ -2791,28 +2806,31 @@ AstNode *parse_range_stmt(AstFile *f) {
isize prev_level = f->expr_level;
f->expr_level = -1;
AstNode *expr = parse_expr(f, false);
+ if (f->curr_token.kind == Token_Interval) {
+ Token op = expect_token(f, Token_Interval);
+ AstNode *right = parse_expr(f, false);
+ expr = make_interval_expr(f, op, expr, right);
+ }
f->expr_level = prev_level;
- AstNode *key = NULL;
AstNode *value = NULL;
- AstNode *body = parse_block_stmt(f, false);
+ AstNode *index = NULL;
+ AstNode *body = parse_block_stmt(f, false);
switch (names.count) {
- case 0:
- break;
case 1:
- key = names.e[0];
+ value = names.e[0];
break;
case 2:
- key = names.e[0];
- value = names.e[1];
+ value = names.e[0];
+ index = names.e[1];
break;
default:
- error_node(names.e[names.count-1], "Expected at most 2 expressions");
+ error(token, "Expected at 1 or 2 identifiers");
return make_bad_stmt(f, token, f->curr_token);
}
- return make_range_stmt(f, token, key, value, expr, body);
+ return make_range_stmt(f, token, value, index, expr, body);
}
AstNode *parse_case_clause(AstFile *f) {
diff --git a/src/ssa.c b/src/ssa.c
index b5a441df6..a31f3e281 100644
--- a/src/ssa.c
+++ b/src/ssa.c
@@ -3908,8 +3908,15 @@ void ssa_build_when_stmt(ssaProcedure *proc, AstNodeWhenStmt *ws) {
}
}
+void ssa_emit_increment(ssaProcedure *proc, ssaValue *addr) {
+ GB_ASSERT(is_type_pointer(ssa_type(addr)));
+ Type *type = type_deref(ssa_type(addr));
+ ssa_emit_store(proc, addr, ssa_emit_arith(proc, Token_Add, ssa_emit_load(proc, addr), v_one, type));
+
+}
+
void ssa_build_range_indexed(ssaProcedure *proc, ssaValue *expr, Type *val_type,
- ssaValue **key_, ssaValue **val_, ssaBlock **loop_, ssaBlock **done_) {
+ ssaValue **val_, ssaValue **idx_, ssaBlock **loop_, ssaBlock **done_) {
ssaValue *count = NULL;
Type *expr_type = base_type(ssa_type(expr));
switch (expr_type->kind) {
@@ -3924,8 +3931,8 @@ void ssa_build_range_indexed(ssaProcedure *proc, ssaValue *expr, Type *val_type,
break;
}
- ssaValue *idx = NULL;
ssaValue *val = NULL;
+ ssaValue *idx = NULL;
ssaBlock *loop = NULL;
ssaBlock *done = NULL;
ssaBlock *body = NULL;
@@ -3933,15 +3940,15 @@ void ssa_build_range_indexed(ssaProcedure *proc, ssaValue *expr, Type *val_type,
ssaValue *index = ssa_add_local_generated(proc, t_int);
ssa_emit_store(proc, index, ssa_make_const_int(proc->module->allocator, -1));
- loop = ssa_add_block(proc, NULL, "rangeindex.loop");
+ loop = ssa_add_block(proc, NULL, "range.index.loop");
ssa_emit_jump(proc, loop);
proc->curr_block = loop;
ssaValue *incr = ssa_emit_arith(proc, Token_Add, ssa_emit_load(proc, index), v_one, t_int);
ssa_emit_store(proc, index, incr);
- body = ssa_add_block(proc, NULL, "rangeindex.body");
- done = ssa_add_block(proc, NULL, "rangeindex.done");
+ body = ssa_add_block(proc, NULL, "range.index.body");
+ done = ssa_add_block(proc, NULL, "range.index.done");
ssaValue *cond = ssa_emit_comp(proc, Token_Lt, incr, count);
ssa_emit_if(proc, cond, body, done);
proc->curr_block = body;
@@ -3962,15 +3969,15 @@ void ssa_build_range_indexed(ssaProcedure *proc, ssaValue *expr, Type *val_type,
}
}
- if (key_) *key_ = idx;
if (val_) *val_ = val;
+ if (idx_) *idx_ = idx;
if (loop_) *loop_ = loop;
if (done_) *done_ = done;
}
void ssa_build_range_string(ssaProcedure *proc, ssaValue *expr, Type *val_type,
- ssaValue **key_, ssaValue **val_, ssaBlock **loop_, ssaBlock **done_) {
+ ssaValue **val_, ssaValue **idx_, ssaBlock **loop_, ssaBlock **done_) {
ssaValue *count = v_zero;
Type *expr_type = base_type(ssa_type(expr));
switch (expr_type->kind) {
@@ -3982,8 +3989,8 @@ void ssa_build_range_string(ssaProcedure *proc, ssaValue *expr, Type *val_type,
break;
}
- ssaValue *idx = NULL;
ssaValue *val = NULL;
+ ssaValue *idx = NULL;
ssaBlock *loop = NULL;
ssaBlock *done = NULL;
ssaBlock *body = NULL;
@@ -3994,14 +4001,14 @@ void ssa_build_range_string(ssaProcedure *proc, ssaValue *expr, Type *val_type,
ssaValue *offset_ = ssa_add_local_generated(proc, t_int);
ssa_emit_store(proc, index, v_zero);
- loop = ssa_add_block(proc, NULL, "rangestring.loop");
+ loop = ssa_add_block(proc, NULL, "range.string.loop");
ssa_emit_jump(proc, loop);
proc->curr_block = loop;
- body = ssa_add_block(proc, NULL, "rangestring.body");
- done = ssa_add_block(proc, NULL, "rangestring.done");
+ body = ssa_add_block(proc, NULL, "range.string.body");
+ done = ssa_add_block(proc, NULL, "range.string.done");
ssaValue *offset = ssa_emit_load(proc, offset_);
@@ -4023,14 +4030,61 @@ void ssa_build_range_string(ssaProcedure *proc, ssaValue *expr, Type *val_type,
if (val_type != NULL) {
val = ssa_emit_struct_ev(proc, rune_and_len, 0);
}
- ssa_emit_store(proc, index, ssa_emit_arith(proc, Token_Add, ssa_emit_load(proc, index), v_one, t_int));
+ ssa_emit_increment(proc, index);
+
+ if (val_) *val_ = val;
+ if (idx_) *idx_ = idx;
+ if (loop_) *loop_ = loop;
+ if (done_) *done_ = done;
+}
+
+void ssa_build_range_interval(ssaProcedure *proc, AstNodeIntervalExpr *node, Type *val_type,
+ ssaValue **val_, ssaValue **idx_, ssaBlock **loop_, ssaBlock **done_) {
+
+ ssaValue *lower = ssa_build_expr(proc, node->left);
+ ssaValue *upper = ssa_build_expr(proc, node->right);
+
+ ssaValue *val = NULL;
+ ssaValue *idx = NULL;
+ ssaBlock *loop = NULL;
+ ssaBlock *done = NULL;
+ ssaBlock *body = NULL;
+
+ if (val_type == NULL) {
+ val_type = ssa_type(lower);
+ }
+ ssaValue *value = ssa_add_local_generated(proc, val_type);
+ ssa_emit_store(proc, value, lower);
+
+ ssaValue *index = ssa_add_local_generated(proc, t_int);
+ ssa_emit_store(proc, index, ssa_make_const_int(proc->module->allocator, 0));
+
+ loop = ssa_add_block(proc, NULL, "range.interval.loop");
+ ssa_emit_jump(proc, loop);
+ proc->curr_block = loop;
+
+ body = ssa_add_block(proc, NULL, "range.interval.body");
+ done = ssa_add_block(proc, NULL, "range.interval.done");
+
+ ssaValue *cond = ssa_emit_comp(proc, Token_Lt, ssa_emit_load(proc, value), upper);
+ ssa_emit_if(proc, cond, body, done);
+ proc->curr_block = body;
+
+ if (value != NULL) {
+ val = ssa_emit_load(proc, value);
+ }
+ idx = ssa_emit_load(proc, index);
+
+ ssa_emit_increment(proc, value);
+ ssa_emit_increment(proc, index);
- if (key_) *key_ = idx;
if (val_) *val_ = val;
+ if (idx_) *idx_ = idx;
if (loop_) *loop_ = loop;
if (done_) *done_ = done;
}
+
void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
switch (node->kind) {
case_ast_node(bs, EmptyStmt, node);
@@ -4441,77 +4495,80 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
case_ast_node(rs, RangeStmt, node);
ssa_emit_comment(proc, str_lit("RangeStmt"));
- Type *key_type = NULL;
Type *val_type = NULL;
- if (rs->key != NULL && !ssa_is_blank_ident(rs->key)) {
- key_type = type_of_expr(proc->module->info, rs->key);
- }
+ Type *idx_type = NULL;
if (rs->value != NULL && !ssa_is_blank_ident(rs->value)) {
val_type = type_of_expr(proc->module->info, rs->value);
}
-
- if (key_type != NULL) {
- ssa_add_local_for_identifier(proc, rs->key, true);
+ if (rs->index != NULL && !ssa_is_blank_ident(rs->index)) {
+ idx_type = type_of_expr(proc->module->info, rs->index);
}
+
if (val_type != NULL) {
ssa_add_local_for_identifier(proc, rs->value, true);
}
+ if (idx_type != NULL) {
+ ssa_add_local_for_identifier(proc, rs->index, true);
+ }
- ssaValue *key = NULL;
ssaValue *val = NULL;
+ ssaValue *index = NULL;
ssaBlock *loop = NULL;
ssaBlock *done = NULL;
- Type *expr_type = type_of_expr(proc->module->info, rs->expr);
- Type *et = base_type(type_deref(expr_type));
- bool deref = is_type_pointer(expr_type);
- switch (et->kind) {
- case Type_Array: {
- ssaValue *array = ssa_build_addr(proc, rs->expr).addr;
- if (deref) {
- array = ssa_emit_load(proc, array);
- }
- ssa_build_range_indexed(proc, array, val_type, &key, &val, &loop, &done);
- } break;
- case Type_Slice: {
- ssaValue *slice = ssa_build_expr(proc, rs->expr);
- if (deref) {
- slice = ssa_emit_load(proc, slice);
- }
- ssa_build_range_indexed(proc, slice, val_type, &key, &val, &loop, &done);
- } break;
- case Type_Basic: {
- ssaValue *string = ssa_build_expr(proc, rs->expr);
- if (deref) {
- string = ssa_emit_load(proc, string);
- }
- if (is_type_untyped(expr_type)) {
- ssaValue *s = ssa_add_local_generated(proc, t_string);
- ssa_emit_store(proc, s, string);
- string = ssa_emit_load(proc, s);
+ if (rs->expr->kind == AstNode_IntervalExpr) {
+ ssa_build_range_interval(proc, &rs->expr->IntervalExpr, val_type, &val, &index, &loop, &done);
+ } else {
+ Type *expr_type = type_of_expr(proc->module->info, rs->expr);
+ Type *et = base_type(type_deref(expr_type));
+ bool deref = is_type_pointer(expr_type);
+ switch (et->kind) {
+ case Type_Array: {
+ ssaValue *array = ssa_build_addr(proc, rs->expr).addr;
+ if (deref) {
+ array = ssa_emit_load(proc, array);
+ }
+ ssa_build_range_indexed(proc, array, val_type, &val, &index, &loop, &done);
+ } break;
+ case Type_Slice: {
+ ssaValue *slice = ssa_build_expr(proc, rs->expr);
+ if (deref) {
+ slice = ssa_emit_load(proc, slice);
+ }
+ ssa_build_range_indexed(proc, slice, val_type, &val, &index, &loop, &done);
+ } break;
+ case Type_Basic: {
+ ssaValue *string = ssa_build_expr(proc, rs->expr);
+ if (deref) {
+ string = ssa_emit_load(proc, string);
+ }
+ if (is_type_untyped(expr_type)) {
+ ssaValue *s = ssa_add_local_generated(proc, t_string);
+ ssa_emit_store(proc, s, string);
+ string = ssa_emit_load(proc, s);
+ }
+ ssa_build_range_string(proc, string, val_type, &val, &index, &loop, &done);
+ } break;
+ default:
+ GB_PANIC("Cannot range over %s", type_to_string(expr_type));
+ break;
}
- ssa_build_range_string(proc, string, val_type, &key, &val, &loop, &done);
- } break;
- default:
- GB_PANIC("Cannot range over %s", type_to_string(expr_type));
- break;
}
-
- ssaAddr key_addr = {0};
ssaAddr val_addr = {0};
- if (key_type != NULL) {
- key_addr = ssa_build_addr(proc, rs->key);
- }
+ ssaAddr idx_addr = {0};
if (val_type != NULL) {
val_addr = ssa_build_addr(proc, rs->value);
}
- if (key_type != NULL) {
- ssa_addr_store(proc, key_addr, key);
+ if (idx_type != NULL) {
+ idx_addr = ssa_build_addr(proc, rs->index);
}
if (val_type != NULL) {
ssa_addr_store(proc, val_addr, val);
}
+ if (idx_type != NULL) {
+ ssa_addr_store(proc, idx_addr, index);
+ }
ssa_push_target_list(proc, done, loop, NULL);
diff --git a/src/tokenizer.c b/src/tokenizer.c
index 5e0f31279..b5f46bcd7 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -78,7 +78,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
TOKEN_KIND(Token_Period, "."), \
TOKEN_KIND(Token_Comma, ","), \
TOKEN_KIND(Token_Ellipsis, ".."), \
- TOKEN_KIND(Token_RangeExclusive, "..<"), \
+ TOKEN_KIND(Token_Interval, "..<"), \
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
\
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
@@ -286,6 +286,14 @@ typedef enum TokenizerInitError {
} TokenizerInitError;
+typedef struct TokenizerState {
+ Rune curr_rune; // current character
+ u8 * curr; // character pos
+ u8 * read_curr; // pos from start
+ u8 * line; // current line pos
+ isize line_count;
+} TokenizerState;
+
typedef struct Tokenizer {
String fullpath;
u8 *start;
@@ -302,6 +310,25 @@ typedef struct Tokenizer {
} Tokenizer;
+TokenizerState save_tokenizer_state(Tokenizer *t) {
+ TokenizerState state = {0};
+ state.curr_rune = t->curr_rune;
+ state.curr = t->curr;
+ state.read_curr = t->read_curr;
+ state.line = t->line;
+ state.line_count = t->line_count;
+ return state;
+}
+
+void restore_tokenizer_state(Tokenizer *t, TokenizerState *state) {
+ t->curr_rune = state->curr_rune;
+ t->curr = state->curr;
+ t->read_curr = state->read_curr;
+ t->line = state->line;
+ t->line_count = state->line_count;
+}
+
+
void tokenizer_err(Tokenizer *t, char *msg, ...) {
va_list va;
isize column = t->read_curr - t->line+1;
@@ -456,23 +483,27 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
if (t->curr_rune == 'b') { // Binary
advance_to_next_rune(t);
scan_mantissa(t, 2);
- if (t->curr - prev <= 2)
+ if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
+ }
} else if (t->curr_rune == 'o') { // Octal
advance_to_next_rune(t);
scan_mantissa(t, 8);
- if (t->curr - prev <= 2)
+ if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
+ }
} else if (t->curr_rune == 'd') { // Decimal
advance_to_next_rune(t);
scan_mantissa(t, 10);
- if (t->curr - prev <= 2)
+ if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
+ }
} else if (t->curr_rune == 'x') { // Hexadecimal
advance_to_next_rune(t);
scan_mantissa(t, 16);
- if (t->curr - prev <= 2)
+ if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
+ }
} else {
seen_decimal_point = false;
scan_mantissa(t, 10);
@@ -491,8 +522,15 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
fraction:
if (t->curr_rune == '.') {
- token.kind = Token_Float;
+ // HACK(bill): This may be inefficient
+ TokenizerState state = save_tokenizer_state(t);
advance_to_next_rune(t);
+ if (t->curr_rune == '.') {
+ // TODO(bill): Clean up this shit
+ restore_tokenizer_state(t, &state);
+ goto end;
+ }
+ token.kind = Token_Float;
scan_mantissa(t, 10);
}
@@ -506,6 +544,7 @@ exponent:
scan_mantissa(t, 10);
}
+end:
token.string.len = t->curr - token.string.text;
return token;
}
@@ -801,7 +840,7 @@ Token tokenizer_get_token(Tokenizer *t) {
token.kind = Token_Ellipsis;
if (t->curr_rune == '<') {
advance_to_next_rune(t);
- token.kind = Token_RangeExclusive;
+ token.kind = Token_Interval;
}
}
break;