package otmp
-use core {string, array, iter}
+use core {string, array, iter, conv}
use core.alloc {as_allocator}
ParseError :: enum {
Keyword_Extends;
String_Literal;
+ Int_Literal;
Variable;
Symbol;
+
Dot;
+ Open_Bracket;
+ Close_Bracket;
}
type: Type;
token_consume("in", .Keyword_In);
token_consume("extends", .Keyword_Extends);
token_consume(".", .Dot);
+ token_consume("[", .Open_Bracket);
+ token_consume("]", .Close_Bracket);
if self.s.data[0] == #char "\"" {
// :TODO add escaped strings
yield_token(.Variable);
}
+ if self.s.data[0]->is_num() {
+ chars := 0;
+ while chars < self.s.length && self.s.data[chars]->is_num() {
+ chars += 1;
+ }
+
+ tkn.text = self->eat_characters(chars);
+
+ yield_token(.Int_Literal);
+ }
+
if self.s.data[0]->is_alphanum() {
chars := 0;
while chars < self.s.length &&
retval = var_expr;
}
+
+ case .Int_Literal {
+ value: i32 = ~~ conv.str_to_i64(tkn.text);
+
+ int_expr := make_expr(t, TExprInt);
+ int_expr.val = value;
+
+ retval = int_expr;
+ }
}
if retval == null {
case .Dot {
p.l->consume();
- sym_tkn: TemplateToken;
-
- // this is gross...
- if err := do {
- expect_token(p, .Symbol, #(sym_tkn));
- return .None;
- }; err != .None {
+ if (p.l->peek()).type != .Symbol {
err = .Unexpected_Token;
break break;
}
+ sym_tkn := p.l->consume();
+
select_expr := make_expr(t, TExprSelector);
select_expr.var = retval;
select_expr.field = sym_tkn.text |> string.alloc_copy(as_allocator(^t.node_storage));
retval = select_expr;
}
+ case .Open_Bracket {
+ p.l->consume();
+
+ expr, err' := parse_expression(p);
+ if err != .None do break break;
+
+ subscript_expr := make_expr(t, TExprSubscript);
+ subscript_expr.var = retval;
+ subscript_expr.sub = expr;
+
+ retval = subscript_expr;
+
+ if (p.l->peek()).type != .Close_Bracket {
+ err = .Unexpected_Token;
+ break break;
+ }
+
+ p.l->consume();
+ }
+
case #default do break break;
}
package otmp
use core {io, tprintf}
-use core.misc {any_iter, any_dereference, any_selector}
+use core.misc {
+ any_iter,
+ any_dereference,
+ any_selector,
+ any_subscript
+}
#package
TemplateRenderer :: struct {
}
}
- case TExprVar, TExprSelector {
+ case TExprVar, TExprSelector, TExprSubscript {
var := resolve_expr_to_any(r, cast(^TExpr) it);
if !var.data do continue;
sub_any = any_dereference(sub_any);
return any_selector(sub_any, selector.field);
}
+
+ case TExprSubscript {
+ subscript := cast(^TExprSubscript) expr;
+
+ sub_any := resolve_expr_to_any(r, subscript.var);
+ sub := any_to_int(resolve_expr_to_any(r, subscript.sub));
+
+ core.printf("{} {}\n", sub_any, sub);
+
+ return any_subscript(sub_any, ~~ sub);
+ }
}
return .{null, void};
}
+
+
+#local
+// :StandardLibrary
+any_to_int :: (v: any) -> i64 {
+ switch v.type {
+ C(u32);
+ C(i32);
+ C(u64);
+ C(i64);
+
+ C :: macro (T: type_expr) {
+ case T do return ~~ *cast(^T) v.data;
+ }
+ }
+
+ return 0;
+}