added array subscript
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Nov 2022 18:55:34 +0000 (13:55 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Nov 2022 18:55:34 +0000 (13:55 -0500)
src/html-templates/src/parser.onyx
src/html-templates/src/render.onyx
src/html-templates/src/types.onyx
www/templates/index.html

index c48935fce3664b5963940c8a6e6cd2de57965174..0f5cf26a5e372e5441f83914a8867f08600b7649 100644 (file)
@@ -1,7 +1,7 @@
 package otmp
 
 
-use core {string, array, iter}
+use core {string, array, iter, conv}
 use core.alloc {as_allocator}
 
 ParseError :: enum {
@@ -49,10 +49,14 @@ TemplateToken :: struct {
         Keyword_Extends;
 
         String_Literal;
+        Int_Literal;
 
         Variable;
         Symbol;
+
         Dot;
+        Open_Bracket;
+        Close_Bracket;
     }
 
     type: Type;
@@ -170,6 +174,8 @@ TemplateToken :: struct {
             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
@@ -195,6 +201,17 @@ TemplateToken :: struct {
                 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 &&
@@ -403,6 +420,15 @@ parse_expression :: (use p: ^TemplateParser) -> (^TExpr, ParseError) {
 
             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 {
@@ -413,17 +439,13 @@ parse_expression :: (use p: ^TemplateParser) -> (^TExpr, ParseError) {
         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));
@@ -431,6 +453,26 @@ parse_expression :: (use p: ^TemplateParser) -> (^TExpr, ParseError) {
             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;
     }
 
index a24a0952c295a5167e05c49c2c64122b49ffff4c..7610f03109ebe8c6ef2a05778b13d4db60561cf8 100644 (file)
@@ -1,7 +1,12 @@
 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 {
@@ -86,7 +91,7 @@ render_instructions :: (use r: ^TemplateRenderer, instrs: [..] ^TNode) -> Error
                 }
             }
 
-            case TExprVar, TExprSelector {
+            case TExprVar, TExprSelector, TExprSubscript {
                 var := resolve_expr_to_any(r, cast(^TExpr) it);
                 if !var.data do continue;
 
@@ -119,7 +124,36 @@ resolve_expr_to_any :: (use r: ^TemplateRenderer, expr: ^TExpr) -> any {
             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;
+}
index 90286bb6ea2e2c8dec3a896fe9924635a77bff23..a97d166481f20cb43f5d4c848de524e2fec9d1ae 100644 (file)
@@ -73,6 +73,19 @@ TExprSelector :: struct {
     field: str;     // storage: template.node_storage
 }
 
+TExprSubscript :: struct {
+    use expr: TExpr;
+
+    var: ^TExpr;
+    sub: ^TExpr;
+}
+
+TExprInt :: struct {
+    use expr: TExpr;
+
+    val: i32;
+}
+
 
 Error :: enum {
     None;
index 484b9c545b59d5222ccf2fe92c670beee1d8bd01..3ed620f22c4f24f24d2309b96f68a8b97c64dc6c 100644 (file)
@@ -31,7 +31,7 @@
         </tbody>
     </table>
 
-    <p>Name: {% $test.templates %} </p>
+    <p>Name: {% $test.templates.entries[0] %} </p>
     <p>Age:  {% $test.arena %} </p>
 
 {{endblock}}