Compare commits

..

3 Commits

Author SHA1 Message Date
Scott Richmond
83ce75c6ea Clean some things up 2024-04-06 18:15:12 -04:00
Scott Richmond
42907f19d7 start debugging current state of affairs: add comments with compile errors 2024-04-06 17:00:22 -04:00
Scott Richmond
bb42ca7ca4 Add doc command to justfile 2024-04-06 16:58:11 -04:00
2 changed files with 26 additions and 17 deletions

View File

@ -84,7 +84,7 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
nil)) nil))
(defn apply-table (defn apply-table
"Applies a struct-based rule." "Applies a table-based rule."
[rule parser] [rule parser]
(def curr (current parser)) (def curr (current parser))
(def rule-fn (get rule :rule)) (def rule-fn (get rule :rule))
@ -109,6 +109,9 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
"Renames a rule. By convention, rule names are keywords." "Renames a rule. By convention, rule names are keywords."
[rule name] (put rule :name name)) [rule name] (put rule :name name))
### As noted above: we should not use this
### Instead, combinators which might not advance should stash state
### These are: !, *, ...?
(defn test (defn test
"Tests a rule: returns whether a rule passes but does not consume any tokens." "Tests a rule: returns whether a rule passes but does not consume any tokens."
[rule parser] [rule parser]
@ -122,7 +125,9 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
[rule] [rule]
@{:name (keyword (string "!" (name rule))) @{:name (keyword (string "!" (name rule)))
:rule (fn !* [parser] :rule (fn !* [parser]
(def result (test rule parser)) (def origin (stash parser))
(def result (apply-rule rule parser))
(restore parser origin)
(if-not result (if-not result
(do (advance parser) true) (do (advance parser) true)
nil))}) nil))})
@ -164,10 +169,7 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
~(set ,name (put ,name :rule (,rule :rule))) ~(set ,name (put ,name :rule (,rule :rule)))
~(var ,name (rename ,rule ,(keyword name))))) ~(var ,name (rename ,rule ,(keyword name)))))
# If we wanted to be robust, we wouldn't hard-code this (comment (defn panic
(defp stop (+ :newline :semicolon :break))
(defn panic
[rule &opt msg] [rule &opt msg]
@{:name (keyword (string "panic-" (name rule))) @{:name (keyword (string "panic-" (name rule)))
:rule (fn panic* [parser] :rule (fn panic* [parser]
@ -184,7 +186,11 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
(array/push (parser :errors) the-error) (array/push (parser :errors) the-error)
(array/push (parser :captured) the-error) (array/push (parser :captured) the-error)
true true
)}) )}))
# If we wanted to be robust, we wouldn't hard-code this
# To consider: use a stack of "panic-until" on a parser to dynamically decide how far to panic
(defp stop (+ :newline :semicolon :break))
(defn panic (defn panic
"Panics the parser, consuming all tokens until the rule matches (including the match). It also adds an error node to both the capture and the error stacks." "Panics the parser, consuming all tokens until the rule matches (including the match). It also adds an error node to both the capture and the error stacks."
@ -196,7 +202,7 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
(while (not passing) (while (not passing)
(array/push skipped (current parser)) (array/push skipped (current parser))
(advance parser) (advance parser)
(set passing (apply-rule rule parser)) (set passing (apply-rule stop parser))
(print "phew; I'm done panicking") (print "phew; I'm done panicking")
(pprint (current parser)) (pprint (current parser))
(def the-error {:type :error :expected expected :token origin :skipped skipped}) (def the-error {:type :error :expected expected :token origin :skipped skipped})
@ -204,7 +210,7 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
(array/push (parser :captured) the-error) (array/push (parser :captured) the-error)
(error parser))) (error parser)))
(defn * (defn *
"Sequences rules: matches if all rules are matched, in sequence." "Sequences rules: matches if all rules are matched, in sequence."
[& rules] [& rules]
@{:name (keyword (string/join (map name rules) "*")) @{:name (keyword (string/join (map name rules) "*"))
@ -213,7 +219,8 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
(var passing true) (var passing true)
(def origin (stash parser)) (def origin (stash parser))
(pprint origin) (pprint origin)
(set failing nil) (def failing nil)
(def passing true)
(loop [rule :in rules :while passing] (loop [rule :in rules :while passing]
(def pass? (apply-rule rule parser)) (def pass? (apply-rule rule parser))
(when (not pass?) (when (not pass?)
@ -242,13 +249,13 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
## is this right? ## is this right?
(defn order-1 [& rules] (comment (defn order-1 [& rules]
@{:name (keyword (string/join (map name rules) "*")) @{:name (keyword (string/join (map name rules) "*"))
:rule (fn order-1 [parser] :rule (fn order-1 [parser]
(def result (test (first rules) parser)) (def result (test (first rules) parser))
(if result (if result
(apply-rule (order-0 ;rules)) (apply-rule (order-0 ;rules)) ### compile error: unknown symbol order-0
nil))}) nil))}))
(defn capture-group (defn capture-group
"Takes a parser and an origin state: takes everything captured since the origin, gathers it up in a single array, pops it all off the capture stack, and pushes the gathered captures back on the stack." "Takes a parser and an origin state: takes everything captured since the origin, gathers it up in a single array, pops it all off the capture stack, and pushes the gathered captures back on the stack."
@ -328,9 +335,9 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
(def parser (new-parser tokens)) (def parser (new-parser tokens))
(try (try
(do (apply-rule rule parser) parser) (do (apply-rule rule parser) parser)
([err] err)) ([err] err)))
(upscope (upscope #XXX for easier repl use
(defn literal->ast [token] {:type (get token :type) :data (get token :literal) :token token}) (defn literal->ast [token] {:type (get token :type) :data (get token :literal) :token token})
@ -342,7 +349,7 @@ The idea, however, is that Jesus: we must not have test-rule and apply-rule: com
(declare expression simple nonbinding) (declare expression simple nonbinding)
(defp separator (+ :newline :comma :break)) (defp separator (some (+ :newline :comma :break)))
(defp separators? (any (+ :newline :comma :break))) (defp separators? (any (+ :newline :comma :break)))
(defp terminator (some (+ :newline :semicolon :break))) (defp terminator (some (+ :newline :semicolon :break)))
(defp terminators? (any (+ :newline :semicolon :break))) (defp terminators? (any (+ :newline :semicolon :break)))

View File

@ -4,7 +4,7 @@ build:
# open a janet repl in a different os window # open a janet repl in a different os window
repl: repl:
kitten @ launch --type=os-window --allow-remote-control --cwd=current --title=hx_repl:ludus kitten @ launch --type=os-window --allow-remote-control --cwd=current --title=hx_repl:ludus --keep-focus
kitten @ send-text -m "title:hx_repl:ludus" "janet -s\n" kitten @ send-text -m "title:hx_repl:ludus" "janet -s\n"
restart: restart:
@ -20,3 +20,5 @@ buffer:
sd "$" "\n" | sd "\n\n" "\n" > .repl-buffer.janet sd "$" "\n" | sd "\n\n" "\n" > .repl-buffer.janet
kitten @ send-text -m "title:hx_repl:ludus" "(import ./.repl-buffer :prefix \"\")" kitten @ send-text -m "title:hx_repl:ludus" "(import ./.repl-buffer :prefix \"\")"
doc:
sd "$" "\n" | sd "\n\n" "\n" | xargs -I _ echo "(doc " _ ")" | kitten @ send-text -m "title:hx_repl:ludus" --stdin