ocaml: phase 1 expression parser (+37 tests, 95 total) — consumes lib/guest/pratt.sx
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 55s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 55s
Atoms (literals/var/con/unit/list), application (left-assoc), prefix - / not, 29-op precedence table via pratt-op-lookup (incl. keyword-spelled mod/land/ lor/lxor/lsl/lsr/asr), tuples, parens, if/then/else, fun, let, let rec with function shorthand. AST follows Haskell-on-SX (:int / :op / :fun / etc).
This commit is contained in:
@@ -29,7 +29,9 @@ cat > "$TMPFILE" << 'EPOCHS'
|
||||
(epoch 1)
|
||||
(load "lib/guest/lex.sx")
|
||||
(load "lib/guest/prefix.sx")
|
||||
(load "lib/guest/pratt.sx")
|
||||
(load "lib/ocaml/tokenizer.sx")
|
||||
(load "lib/ocaml/parser.sx")
|
||||
(load "lib/ocaml/tests/tokenize.sx")
|
||||
|
||||
;; ── empty / eof ────────────────────────────────────────────────
|
||||
@@ -169,6 +171,95 @@ cat > "$TMPFILE" << 'EPOCHS'
|
||||
(epoch 195)
|
||||
(eval "(ocaml-test-tok-value \"x := !y\" 1)")
|
||||
|
||||
;; ── Phase 1.parse: parser ──────────────────────────────────────
|
||||
;; Atoms
|
||||
(epoch 200)
|
||||
(eval "(ocaml-parse \"42\")")
|
||||
(epoch 201)
|
||||
(eval "(ocaml-parse \"3.14\")")
|
||||
(epoch 202)
|
||||
(eval "(ocaml-parse \"\\\"hi\\\"\")")
|
||||
(epoch 203)
|
||||
(eval "(ocaml-parse \"'a'\")")
|
||||
(epoch 204)
|
||||
(eval "(ocaml-parse \"true\")")
|
||||
(epoch 205)
|
||||
(eval "(ocaml-parse \"false\")")
|
||||
(epoch 206)
|
||||
(eval "(ocaml-parse \"x\")")
|
||||
(epoch 207)
|
||||
(eval "(ocaml-parse \"Some\")")
|
||||
(epoch 208)
|
||||
(eval "(ocaml-parse \"()\")")
|
||||
|
||||
;; Application (left-assoc)
|
||||
(epoch 210)
|
||||
(eval "(ocaml-parse \"f x\")")
|
||||
(epoch 211)
|
||||
(eval "(ocaml-parse \"f x y\")")
|
||||
(epoch 212)
|
||||
(eval "(ocaml-parse \"f (g x)\")")
|
||||
(epoch 213)
|
||||
(eval "(ocaml-parse \"Some 42\")")
|
||||
|
||||
;; Binops with precedence
|
||||
(epoch 220)
|
||||
(eval "(ocaml-parse \"1 + 2\")")
|
||||
(epoch 221)
|
||||
(eval "(ocaml-parse \"a + b * c\")")
|
||||
(epoch 222)
|
||||
(eval "(ocaml-parse \"a * b + c\")")
|
||||
(epoch 223)
|
||||
(eval "(ocaml-parse \"a && b || c\")")
|
||||
(epoch 224)
|
||||
(eval "(ocaml-parse \"a = b\")")
|
||||
(epoch 225)
|
||||
(eval "(ocaml-parse \"a ^ b ^ c\")")
|
||||
(epoch 226)
|
||||
(eval "(ocaml-parse \"a :: b :: []\")")
|
||||
(epoch 227)
|
||||
(eval "(ocaml-parse \"(a + b) * c\")")
|
||||
(epoch 228)
|
||||
(eval "(ocaml-parse \"a |> f |> g\")")
|
||||
(epoch 229)
|
||||
(eval "(ocaml-parse \"x mod 2\")")
|
||||
|
||||
;; Prefix
|
||||
(epoch 230)
|
||||
(eval "(ocaml-parse \"-x\")")
|
||||
(epoch 231)
|
||||
(eval "(ocaml-parse \"-1 + 2\")")
|
||||
|
||||
;; Tuples & lists
|
||||
(epoch 240)
|
||||
(eval "(ocaml-parse \"(1, 2, 3)\")")
|
||||
(epoch 241)
|
||||
(eval "(ocaml-parse \"[1; 2; 3]\")")
|
||||
(epoch 242)
|
||||
(eval "(ocaml-parse \"[]\")")
|
||||
|
||||
;; if / fun / let / let rec
|
||||
(epoch 250)
|
||||
(eval "(ocaml-parse \"if x then 1 else 2\")")
|
||||
(epoch 251)
|
||||
(eval "(ocaml-parse \"if c then x\")")
|
||||
(epoch 252)
|
||||
(eval "(ocaml-parse \"fun x -> x + 1\")")
|
||||
(epoch 253)
|
||||
(eval "(ocaml-parse \"fun x y -> x + y\")")
|
||||
(epoch 254)
|
||||
(eval "(ocaml-parse \"let x = 1 in x\")")
|
||||
(epoch 255)
|
||||
(eval "(ocaml-parse \"let f x = x + 1 in f 2\")")
|
||||
(epoch 256)
|
||||
(eval "(ocaml-parse \"let rec f x = f x in f 1\")")
|
||||
(epoch 257)
|
||||
(eval "(ocaml-parse \"let f x y = x + y in f 1 2\")")
|
||||
|
||||
;; begin/end
|
||||
(epoch 260)
|
||||
(eval "(ocaml-parse \"begin 1 + 2 end\")")
|
||||
|
||||
EPOCHS
|
||||
|
||||
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
||||
@@ -278,9 +369,54 @@ check 193 "Some is ctor" '"ctor"'
|
||||
check 194 "first |> value" '"|>"'
|
||||
check 195 "ref assign :=" '":="'
|
||||
|
||||
# ── Parser tests ────────────────────────────────────────────────
|
||||
check 200 "parse int" '("int" 42)'
|
||||
check 201 "parse float" '("float" 3.14)'
|
||||
check 202 "parse string" '("string" "hi")'
|
||||
check 203 "parse char" '("char" "a")'
|
||||
check 204 "parse true" '("bool" true)'
|
||||
check 205 "parse false" '("bool" false)'
|
||||
check 206 "parse var" '("var" "x")'
|
||||
check 207 "parse ctor" '("con" "Some")'
|
||||
check 208 "parse unit" '("unit")'
|
||||
|
||||
check 210 "parse f x" '("app" ("var" "f") ("var" "x"))'
|
||||
check 211 "parse f x y left-assoc" '("app" ("app" ("var" "f") ("var" "x")) ("var" "y"))'
|
||||
check 212 "parse f (g x)" '("app" ("var" "f") ("app" ("var" "g") ("var" "x")))'
|
||||
check 213 "parse Some 42" '("app" ("con" "Some") ("int" 42))'
|
||||
|
||||
check 220 "parse 1+2" '("op" "+" ("int" 1) ("int" 2))'
|
||||
check 221 "parse a + b * c prec" '("op" "+" ("var" "a") ("op" "*"'
|
||||
check 222 "parse a*b + c prec" '("op" "+" ("op" "*"'
|
||||
check 223 "parse && / || prec" '("op" "||" ("op" "&&"'
|
||||
check 224 "parse a = b" '("op" "=" ("var" "a") ("var" "b"))'
|
||||
check 225 "parse ^ right-assoc" '("op" "^" ("var" "a") ("op" "^"'
|
||||
check 226 "parse :: right-assoc" '("op" "::" ("var" "a") ("op" "::"'
|
||||
check 227 "parse parens override" '("op" "*" ("op" "+"'
|
||||
check 228 "parse |> chain" '("op" "|>" ("op" "|>"'
|
||||
check 229 "parse mod kw-binop" '("op" "mod" ("var" "x") ("int" 2))'
|
||||
|
||||
check 230 "parse -x" '("neg" ("var" "x"))'
|
||||
check 231 "parse -1+2" '("op" "+" ("neg" ("int" 1)) ("int" 2))'
|
||||
|
||||
check 240 "parse tuple" '("tuple" ("int" 1) ("int" 2) ("int" 3))'
|
||||
check 241 "parse list literal" '("list" ("int" 1) ("int" 2) ("int" 3))'
|
||||
check 242 "parse []" '("list")'
|
||||
|
||||
check 250 "parse if/then/else" '("if" ("var" "x") ("int" 1) ("int" 2))'
|
||||
check 251 "parse if w/o else" '("if" ("var" "c") ("var" "x") ("unit"))'
|
||||
check 252 "parse fun x -> ..." '("fun" ("x") ("op" "+" ("var" "x") ("int" 1)))'
|
||||
check 253 "parse fun x y ->" '("fun" ("x" "y")'
|
||||
check 254 "parse let x = 1 in x" '("let" "x" () ("int" 1) ("var" "x"))'
|
||||
check 255 "parse let f x =" '("let" "f" ("x") ("op" "+"'
|
||||
check 256 "parse let rec f x =" '("let-rec" "f" ("x")'
|
||||
check 257 "parse let f x y =" '("let" "f" ("x" "y")'
|
||||
|
||||
check 260 "parse begin/end" '("op" "+" ("int" 1) ("int" 2))'
|
||||
|
||||
TOTAL=$((PASS + FAIL))
|
||||
if [ $FAIL -eq 0 ]; then
|
||||
echo "ok $PASS/$TOTAL OCaml-on-SX tokenizer tests passed"
|
||||
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"
|
||||
else
|
||||
echo "FAIL $PASS/$TOTAL passed, $FAIL failed:"
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user