From 6d138a1181b4a6b5d9b25eb98871e789db060f5b Mon Sep 17 00:00:00 2001 From: George Lemon Date: Wed, 6 Mar 2024 05:52:29 +0200 Subject: [PATCH] Add IndexRange `[0..^2]` Signed-off-by: George Lemon --- src/tim/engine/ast.nim | 8 +++-- src/tim/engine/compilers/html.nim | 15 ++++++++- src/tim/engine/parser.nim | 56 +++++++++++++++++++++---------- src/tim/engine/tokens.nim | 1 + 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/tim/engine/ast.nim b/src/tim/engine/ast.nim index 5129103..82b133c 100755 --- a/src/tim/engine/ast.nim +++ b/src/tim/engine/ast.nim @@ -37,8 +37,9 @@ type ntIdent = "Identifier" ntCall = "FunctionCall" ntIdentPair - ntDotExpr - ntBracketExpr + ntDotExpr = "DotExpression" + ntBracketExpr = "BracketExpression" + ntIndexRange = "IndexRange" ntConditionStmt = "ConditionStatement" ntLoopStmt = "LoopStmt" ntViewLoader = "ViewLoader" @@ -153,6 +154,9 @@ type of ntBracketExpr: bracketStorageType*: StorageType bracketLHS*, bracketIndex*: Node + of ntIndexRange: + rangeNodes*: array[2, Node] + rangeLastIndex*: bool # from end to start using ^ circumflex accent of ntLitFunction: fnIdent*: string fnParams*: OrderedTable[string, FnParam] diff --git a/src/tim/engine/compilers/html.nim b/src/tim/engine/compilers/html.nim index 435b230..62459b9 100755 --- a/src/tim/engine/compilers/html.nim +++ b/src/tim/engine/compilers/html.nim @@ -307,6 +307,19 @@ proc walkAccessorStorage(c: var HtmlCompiler, result = lhs.arrayItems[rhs.iVal] except Defect: compileErrorWithArgs(indexDefect, lhs.meta, [$(rhs.iVal), "0.." & $(lhs.arrayItems.high)]) + of ntIndexRange: + let l = rhs.rangeNodes[0].iVal + let r = rhs.rangeNodes[1].iVal + try: + result = ast.newNode(ntLitArray) + result.meta = lhs.meta + case rhs.rangeLastIndex + of false: + result.arrayItems = lhs.arrayItems[l..r] + of true: + result.arrayItems = lhs.arrayItems[l..^r] + except Defect: + compileErrorWithArgs(indexDefect, lhs.meta, ["", "0.." & $(lhs.arrayItems.high)]) else: compileErrorWithArgs(invalidAccessorStorage, rhs.meta, [rhs.toString, $lhs.nt]) else: discard @@ -544,7 +557,7 @@ proc getValue(c: var HtmlCompiler, node: Node, if likely(some.scopeTable != nil): return c.getValue(some.scopeTable[node.identName].varValue, scopetables) compileErrorWithArgs(undeclaredVariable, [node.identName]) - of ntAssignableSet: + of ntAssignableSet, ntIndexRange: # return literal nodes result = node of ntInfixExpr: diff --git a/src/tim/engine/parser.nim b/src/tim/engine/parser.nim index adc8492..4502340 100755 --- a/src/tim/engine/parser.nim +++ b/src/tim/engine/parser.nim @@ -103,6 +103,12 @@ proc `notin`(tk: TokenTuple, kind: set[TokenKind]): bool {.inline.} = proc isFnCall(p: var Parser): bool {.inline.} = p.curr is tkIdentifier and p.next is tkLP and p.next.wsno == 0 +template isRange: untyped = + ( + (p.curr is tkDot and p.next is tkDot) and + (p.curr.line == tk.line and p.next.line == tk.line) + ) + template expectWalk(kind: TokenKind) = if likely(p.curr is kind): walk p @@ -262,25 +268,39 @@ proc parseDotExpr(p: var Parser, lhs: Node): Node {.gcsafe.} = proc parseBracketExpr(p: var Parser, lhs: Node): Node {.gcsafe.} = # parse bracket expression - result = ast.newNode(ntBracketExpr, p.prev) - walk p # tkLB + let tk = p.curr; walk p # tkLB let index = p.getPrefixOrInfix() + result = ast.newNode(ntBracketExpr, p.curr) + result.bracketLHS = lhs caseNotNil index: - result.bracketIndex = index - result.bracketLHS = lhs - expectWalk tkRB - while true: - case p.curr.kind - of tkDot: - if p.curr.line == result.meta[0]: - result = p.parseDotExpr(result) - else: break - of tkLB: - if p.curr.line == result.meta[0]: - result = p.parseBracketExpr(result) - else: break - else: - break # todo handle infix expressions + if p.curr is tkRB: + result.bracketIndex = index + while true: + case p.curr.kind + of tkDot: + if p.curr.line == result.meta[0]: + result = p.parseDotExpr(result) + else: break + of tkLB: + if p.curr.line == result.meta[0]: + result = p.parseBracketExpr(result) + else: break + else: + break # todo handle infix expressions + elif isRange: + walk p, 2 + let lastIndex = + if p.curr is tkCaret: + walk p; true + else: false + expect {tkInteger, tkIdentVar}: + let rhs = p.parsePrefix() + caseNotnil rhs: + let rangeNode = ast.newNode(ntIndexRange) + rangeNode.rangeNodes = [index, rhs] + rangeNode.rangeLastIndex = lastIndex + result.bracketIndex = rangeNode + expectWalk tkRB prefixHandle pIdent: # parse an identifier @@ -592,7 +612,7 @@ prefixHandle pFor: pairNode.identPairs[1] = vNode result.loopItem = pairNode walk p - expectWalk(tkIN) + expectWalk tkIN expect {tkIdentVar, tkLB}: let items = p.parsePrefix() caseNotNil items: diff --git a/src/tim/engine/tokens.nim b/src/tim/engine/tokens.nim index 4ee9f53..e16d4ba 100755 --- a/src/tim/engine/tokens.nim +++ b/src/tim/engine/tokens.nim @@ -156,6 +156,7 @@ registerTokens toktokSettings: doc = tokenize(handleDocBlock, '*') comment = tokenize(handleInlineComment, '/') `mod` = '%' + caret = '^' lc = '{' rc = '}' lp = '('