Step 18 (part 3): Expand parser — expressions, commands, features
Tokenizer: * and % now emit as operators (were silently swallowed) Added keywords: install, measure, behavior, called 5 new arithmetic operator tests Parser — expression layer: Arithmetic (+, -, *, /, %) via parse-arith Unary not, no, unary minus the X of Y possessive (parse-the-expr) as Type conversion, X in Y membership, array literals [...] fetch URL parsing fixed — no longer consumes "as" meant for fetch Parser — 8 new commands: return, throw, append...to, tell...end, for...in...end, make a Type, install Behavior, measure Parser — 2 new features: def name(params)...end, behavior Name(params)...end Parser — enhanced: wait for event [from target], on every event modifier 33 new parser tests (16 suites), 5 tokenizer tests. 3043/3043 full build, zero regressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -375,6 +375,291 @@
|
||||
(assert= "hello" (nth ast 2)))))
|
||||
|
||||
;; ── Full expressions (matching tokenizer conformance) ─────────────
|
||||
(defsuite
|
||||
"hs-parse-arithmetic"
|
||||
(deftest
|
||||
"addition"
|
||||
(let
|
||||
((ast (hs-compile "set x to 1 + 2")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote +) (first val))
|
||||
(assert= 1 (nth val 1))
|
||||
(assert= 2 (nth val 2)))))
|
||||
(deftest
|
||||
"subtraction"
|
||||
(let
|
||||
((ast (hs-compile "set x to 10 - 3")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote -) (first val))
|
||||
(assert= 10 (nth val 1))
|
||||
(assert= 3 (nth val 2)))))
|
||||
(deftest
|
||||
"multiplication"
|
||||
(let
|
||||
((ast (hs-compile "set x to 4 * 5")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote *) (first val))
|
||||
(assert= 4 (nth val 1))
|
||||
(assert= 5 (nth val 2)))))
|
||||
(deftest
|
||||
"division"
|
||||
(let
|
||||
((ast (hs-compile "set x to 10 / 2")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote /) (first val))
|
||||
(assert= 10 (nth val 1))
|
||||
(assert= 2 (nth val 2)))))
|
||||
(deftest
|
||||
"chained arithmetic"
|
||||
(let
|
||||
((ast (hs-compile "set x to 1 + 2 + 3")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote +) (first val))
|
||||
(assert= 3 (nth val 2))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-unary"
|
||||
(deftest
|
||||
"not expr"
|
||||
(let
|
||||
((ast (hs-compile "if not x end")))
|
||||
(let ((cnd (nth ast 1))) (assert= (quote not) (first cnd)))))
|
||||
(deftest
|
||||
"no expr"
|
||||
(let
|
||||
((ast (hs-compile "if no x end")))
|
||||
(let ((cnd (nth ast 1))) (assert= (quote no) (first cnd)))))
|
||||
(deftest
|
||||
"unary minus"
|
||||
(let
|
||||
((ast (hs-compile "set x to -5")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote -) (first val))
|
||||
(assert= 0 (nth val 1))
|
||||
(assert= 5 (nth val 2))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-the-of"
|
||||
(deftest
|
||||
"the innerHTML of me"
|
||||
(let
|
||||
((ast (hs-compile "set the innerHTML of me to 'hi'")))
|
||||
(let
|
||||
((tgt (nth ast 1)))
|
||||
(assert= (make-symbol ".") (first tgt))
|
||||
(assert= "innerHTML" (nth tgt 2)))))
|
||||
(deftest
|
||||
"the as article skip"
|
||||
(let
|
||||
((ast (hs-compile "set the result to 5")))
|
||||
(let ((tgt (nth ast 1))) (assert= (quote it) (first tgt))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-as-conversion"
|
||||
(deftest
|
||||
"expr as Int"
|
||||
(let
|
||||
((ast (hs-compile "set x to y as Int")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote as) (first val))
|
||||
(assert= "Int" (nth val 2)))))
|
||||
(deftest
|
||||
"expr as String"
|
||||
(let
|
||||
((ast (hs-compile "set x to count as String")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote as) (first val))
|
||||
(assert= "String" (nth val 2))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-in-operator"
|
||||
(deftest
|
||||
"x in collection"
|
||||
(let
|
||||
((ast (hs-compile "if x in items end")))
|
||||
(let ((cnd (nth ast 1))) (assert= (quote in?) (first cnd))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-array-literals"
|
||||
(deftest
|
||||
"empty array"
|
||||
(let
|
||||
((ast (hs-compile "set x to []")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote array) (first val))
|
||||
(assert= 1 (len val)))))
|
||||
(deftest
|
||||
"array with elements"
|
||||
(let
|
||||
((ast (hs-compile "set x to [1, 2, 3]")))
|
||||
(let
|
||||
((val (nth ast 2)))
|
||||
(assert= (quote array) (first val))
|
||||
(assert= 4 (len val))
|
||||
(assert= 1 (nth val 1))
|
||||
(assert= 2 (nth val 2))
|
||||
(assert= 3 (nth val 3))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-return-throw"
|
||||
(deftest
|
||||
"return expr"
|
||||
(let
|
||||
((ast (hs-compile "return 42")))
|
||||
(assert= (quote return) (first ast))
|
||||
(assert= 42 (nth ast 1))))
|
||||
(deftest
|
||||
"return bare"
|
||||
(let
|
||||
((ast (hs-compile "return")))
|
||||
(assert= (quote return) (first ast))
|
||||
(assert= nil (nth ast 1))))
|
||||
(deftest
|
||||
"throw expr"
|
||||
(let
|
||||
((ast (hs-compile "throw 'error'")))
|
||||
(assert= (quote throw) (first ast))
|
||||
(assert= "error" (nth ast 1)))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-append"
|
||||
(deftest
|
||||
"append to target"
|
||||
(let
|
||||
((ast (hs-compile "append 'hello' to me")))
|
||||
(assert= (quote append!) (first ast))
|
||||
(assert= "hello" (nth ast 1))
|
||||
(assert= (quote me) (first (nth ast 2))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-tell"
|
||||
(deftest
|
||||
"tell target commands end"
|
||||
(let
|
||||
((ast (hs-compile "tell <div/> add .active end")))
|
||||
(assert= (quote tell) (first ast))
|
||||
(assert= (quote query) (first (nth ast 1)))
|
||||
(assert= (quote add-class) (first (nth ast 2))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-for"
|
||||
(deftest
|
||||
"for x in items end"
|
||||
(let
|
||||
((ast (hs-compile "for item in items log item end")))
|
||||
(assert= (quote for) (first ast))
|
||||
(assert= "item" (nth ast 1))
|
||||
(assert= (quote ref) (first (nth ast 2)))
|
||||
(assert= (quote log) (first (nth ast 3)))))
|
||||
(deftest
|
||||
"for with index"
|
||||
(let
|
||||
((ast (hs-compile "for item in items index i log item end")))
|
||||
(assert= (quote for) (first ast))
|
||||
(assert= "item" (nth ast 1)))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-make"
|
||||
(deftest
|
||||
"make a Object"
|
||||
(let
|
||||
((ast (hs-compile "make a Object")))
|
||||
(assert= (quote make) (first ast))
|
||||
(assert= "Object" (nth ast 1))))
|
||||
(deftest
|
||||
"make a Set called s"
|
||||
(let
|
||||
((ast (hs-compile "make a Set called s")))
|
||||
(assert= (quote make) (first ast))
|
||||
(assert= "Set" (nth ast 1))
|
||||
(assert= "s" (nth ast 2)))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-install"
|
||||
(deftest
|
||||
"install behavior"
|
||||
(let
|
||||
((ast (hs-compile "install Draggable")))
|
||||
(assert= (quote install) (first ast))
|
||||
(assert= "Draggable" (nth ast 1))))
|
||||
(deftest
|
||||
"install with args"
|
||||
(let
|
||||
((ast (hs-compile "install Sortable(true)")))
|
||||
(assert= (quote install) (first ast))
|
||||
(assert= "Sortable" (nth ast 1))
|
||||
(assert= true (nth ast 2)))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-measure"
|
||||
(deftest
|
||||
"measure target"
|
||||
(let
|
||||
((ast (hs-compile "measure me")))
|
||||
(assert= (quote measure) (first ast))
|
||||
(assert= (quote me) (first (nth ast 1))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-wait-for"
|
||||
(deftest
|
||||
"wait for transitionend"
|
||||
(let
|
||||
((ast (hs-compile "wait for transitionend")))
|
||||
(assert= (quote wait-for) (first ast))
|
||||
(assert= "transitionend" (nth ast 1))))
|
||||
(deftest
|
||||
"wait for click from target"
|
||||
(let
|
||||
((ast (hs-compile "wait for click from #btn")))
|
||||
(assert= (quote wait-for) (first ast))
|
||||
(assert= "click" (nth ast 1))
|
||||
(assert= :from (nth ast 2)))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-def-behavior"
|
||||
(deftest
|
||||
"def function"
|
||||
(let
|
||||
((ast (hs-compile "def greet(name) log name end")))
|
||||
(assert= (quote def) (first ast))
|
||||
(assert= "greet" (nth ast 1))
|
||||
(assert= 1 (len (nth ast 2)))
|
||||
(assert= (quote log) (first (nth ast 3)))))
|
||||
(deftest
|
||||
"behavior with on handler"
|
||||
(let
|
||||
((ast (hs-compile "behavior Clickable on click add .clicked end end")))
|
||||
(assert= (quote behavior) (first ast))
|
||||
(assert= "Clickable" (nth ast 1))
|
||||
(assert= 1 (len (nth ast 3)))))
|
||||
(deftest
|
||||
"def no params"
|
||||
(let
|
||||
((ast (hs-compile "def reset() set x to 0 end")))
|
||||
(assert= (quote def) (first ast))
|
||||
(assert= "reset" (nth ast 1))
|
||||
(assert= 0 (len (nth ast 2))))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-every-modifier"
|
||||
(deftest
|
||||
"on every click"
|
||||
(let
|
||||
((ast (hs-compile "on every click add .pulse end")))
|
||||
(assert= (quote on) (first ast))
|
||||
(assert= "click" (nth ast 1))
|
||||
(assert= :every (nth ast 2))
|
||||
(assert= true (nth ast 3)))))
|
||||
|
||||
(defsuite
|
||||
"hs-parse-conformance"
|
||||
(deftest
|
||||
|
||||
Reference in New Issue
Block a user