diff --git a/src/bean/functions.cljs b/src/bean/functions.cljs index a4d5f7d..3105a9e 100644 --- a/src/bean/functions.cljs +++ b/src/bean/functions.cljs @@ -11,6 +11,10 @@ (let [[expression-type] ast] (= expression-type :CellRef))) +(defn quoted-string? [[_ ast]] + (let [[expression-type] ast] + (= expression-type :QuotedString))) + ;; Functions don't work for matrices, ;; they need the thing as apply-op does (defn bean-concat [_sheet args] @@ -111,23 +115,35 @@ (defn bean-hget [sheet args asts] (bean-get* sheet args asts :left)) +(defn bean-frame* [sheet frame frame-name] + {:matrix (interpreter/eval-matrix (:start frame) + (:end frame) + (:grid sheet)) + :frame {:name frame-name + :selection (area/area->addresses + (select-keys frame [:start :end])) + :selection-dirn nil}}) + (defn bean-frame [sheet args asts] - (if (cell-ref? (first asts)) + (cond + (cell-ref? (first asts)) (let [[_ [_ a n]] (first asts) address (util/a1->rc a (js/parseInt n)) frame-name (frames/cell-frame address sheet) frame (frames/get-frame sheet frame-name)] (if frame-name - {:matrix (interpreter/eval-matrix (:start frame) - (:end frame) - (:grid sheet)) - :frame {:name frame-name - :selection (area/area->addresses - (select-keys frame [:start :end])) - :selection-dirn nil}} + (bean-frame* sheet frame frame-name) (errors/undefined-frame-at (str a n)))) - (errors/invalid-frame-args - (str (:scalar (first args)))))) + + (quoted-string? (first asts)) + (let [[_ [_ frame-name]] (first asts) + frame (frames/get-frame sheet frame-name)] + (if frame + (bean-frame* sheet frame frame-name) + (errors/undefined-frame-at frame-name))) + + :else (errors/invalid-frame-args + (str (:scalar (first args)))))) (defn bean-error [_sheet args] (let [str-err (str (:error (first args)))] diff --git a/src/bean/interpreter.cljs b/src/bean/interpreter.cljs index 02044b6..8b18008 100644 --- a/src/bean/interpreter.cljs +++ b/src/bean/interpreter.cljs @@ -95,9 +95,22 @@ :FunctionInvocation (apply-f sheet (eval-sub-ast arg) (rest args)) - :FunctionChain (let [[expr [_ fn-name & fn-args]] args] + :FrameLookup (let [[_ frame-name] arg] + (eval-sub-ast + [:FunctionInvocation + [:Name "frame"] + [:Expression [:QuotedString frame-name]]])) + :FunctionChain (let [[expr [node-type* + [_ name* :as name-node] + & fn-args]] args] (eval-sub-ast - (concat [:FunctionInvocation fn-name expr] fn-args))) + (case node-type* + :LabelLookup + [:FunctionInvocation + [:Name "get"] expr + [:Expression [:Value [:QuotedString name*]]]] + :FunctionInvocation + (concat [:FunctionInvocation name-node expr] fn-args)))) :Expression (if (util/is-expression? arg) (let [[left op right] args] (apply-op (eval-sub-ast op) diff --git a/src/bean/parser/parser.cljs b/src/bean/parser/parser.cljs index 147cf1f..828ae97 100644 --- a/src/bean/parser/parser.cljs +++ b/src/bean/parser/parser.cljs @@ -20,12 +20,17 @@ MatrixRef = CellRef <':'> CellRef Operation = '+' | '*' | '=' | '<' | '>' - Expression = Value | CellRef | MatrixRef | FunctionChain | Expression Operation Expression | FunctionInvocation | FunctionDefinition | Name + Expression = (Value | CellRef | MatrixRef | FunctionChain | + Expression Operation Expression | FunctionInvocation | + FunctionDefinition | FrameLookup) / Name + FunctionInvocation = (FunctionDefinition | Name) <'('> [Expression {<' '> Expression}] <')'> FunctionDefinition = <'{'> Expression <'}'> - FunctionChain = Expression <'.'> FunctionInvocation + FunctionChain = Expression [<'.'> (FunctionInvocation | LabelLookup)] - Name = #'[a-z]+' + Name = #'[a-zA-Z0-9 ]+(? Name + LabelLookup = Name Value = Integer / <'\"'> QuotedString <'\"'> QuotedString = #'[^\"]+'