Compare commits
No commits in common. "2cfe9fdffc3fb779f4716ca84d2b3b7527353c8d" and "b5def30348850526591fd884aaec2c5f2f09f88e" have entirely different histories.
2cfe9fdffc
...
b5def30348
|
@ -259,18 +259,13 @@
|
|||
|
||||
(def sequels [:lparen :keyword])
|
||||
|
||||
(defn- word-expr [parser]
|
||||
(defn- word [parser]
|
||||
(expect parser :word)
|
||||
(if (has-value? sequels (-> parser peek type)) (break (synthetic parser)))
|
||||
(def curr (-> parser current))
|
||||
(advance parser)
|
||||
{:type :word :data (curr :lexeme) :token curr})
|
||||
|
||||
(defn- word-only [parser]
|
||||
(expect parser :word)
|
||||
(def curr (current parser))
|
||||
(advance parser)
|
||||
{:type :word :data (curr :lexeme) :token curr})
|
||||
{:type :word :data (curr :lexeme) :token curr}
|
||||
)
|
||||
|
||||
(defn- args [parser]
|
||||
(def origin (current parser))
|
||||
|
@ -294,7 +289,7 @@
|
|||
(set (ast :partial) true)
|
||||
(advance parser)
|
||||
{:type :placeholder :token origin}))
|
||||
(capture nonbinding parser)))
|
||||
(try (nonbinding parser) ([e] e))))
|
||||
(array/push (ast :data) term)
|
||||
(try (separators parser)
|
||||
([e] (pp e) (array/push (ast :data) e))))
|
||||
|
@ -302,21 +297,20 @@
|
|||
ast)
|
||||
|
||||
(defn- synth-root [parser]
|
||||
(print "parsing synth root")
|
||||
(def origin (current parser))
|
||||
(advance parser)
|
||||
(case (type origin)
|
||||
:word {:type :word :data (origin :lexeme) :token origin}
|
||||
:keyword {:type :keyword :data (origin :literal) :token origin}
|
||||
:pkg-name {:type :pkg-name :data (origin :lexeme) :token origin}
|
||||
:pkg-name {:type :pkg-name :data (origin :lexem) :token origin}
|
||||
(panic parser "expected word, keyword, or package")
|
||||
)
|
||||
)
|
||||
|
||||
(defrec synthetic [parser]
|
||||
(print "parsing synthetic")
|
||||
(def origin (current parser))
|
||||
(def ast {:type :synthetic :data @[(synth-root parser)] :token origin})
|
||||
(def ast {:type :synthetic :data @[(synth-root origin)] :token origin})
|
||||
(advance parser)
|
||||
(while (has-value? sequels (-> parser current type))
|
||||
(def term
|
||||
(case (-> parser current type)
|
||||
|
@ -339,7 +333,7 @@
|
|||
(def err {:type :error :token origin :msg "unclosed paren"})
|
||||
(array/push (parser :errors) err)
|
||||
(error err))
|
||||
(def term (capture nonbinding parser))
|
||||
(def term (try (nonbinding parser) ([e] e)))
|
||||
(array/push (ast :data) term)
|
||||
(try (separators parser)
|
||||
([e] (pp e) (array/push (ast :data) e))))
|
||||
|
@ -360,10 +354,10 @@
|
|||
(def term (if (check parser :splat)
|
||||
(do
|
||||
(advance parser)
|
||||
(def splatted (try (word-only parser) ([e] e)))
|
||||
(def splatted (try (word parser) ([e] e)))
|
||||
{:type :splat :data splatted :token origin}
|
||||
)
|
||||
(capture nonbinding parser)))
|
||||
(try (nonbinding parser) ([e] e))))
|
||||
(array/push (ast :data) term)
|
||||
(try (separators parser)
|
||||
([e] (array/push (ast :data) e))))
|
||||
|
@ -384,10 +378,10 @@
|
|||
(def term (if (check parser :splat)
|
||||
(do
|
||||
(advance parser)
|
||||
(def splatted (capture word-only parser))
|
||||
(def splatted (capture word parser))
|
||||
{:type :splat :data splatted :token origin}
|
||||
)
|
||||
(capture nonbinding parser)))
|
||||
(try (nonbinding parser) ([e] e))))
|
||||
(array/push (ast :data) term)
|
||||
(try (separators parser)
|
||||
([e] (array/push (ast :data) e))))
|
||||
|
@ -406,11 +400,11 @@
|
|||
(error err))
|
||||
(def origin (current parser))
|
||||
(def term (case (type origin)
|
||||
:splat {:type :splat :data (capture word-only (advance parser)) :token origin}
|
||||
:word (try (word-only parser) ([e] e))
|
||||
:splat {:type :splat :data (try (word (advance parser)) ([e] e)) :token origin}
|
||||
:word (try (word parser) ([e] e))
|
||||
:keyword (do
|
||||
(def key (try (kw parser) ([e] e)))
|
||||
(def value (capture nonbinding parser))
|
||||
(def value (try (nonbinding parser) ([e] e)))
|
||||
{:type :pair :data [key value] :token origin})
|
||||
(try (panic parser (string expect "expected dict term, got " (type origin))) ([e] e))
|
||||
))
|
||||
|
@ -454,9 +448,9 @@
|
|||
(def term (if (check parser :splat)
|
||||
(do
|
||||
(advance parser)
|
||||
(def splatted (when (check parser :word) (word-only parser)))
|
||||
(def splatted (if (check parser :word) (word parser) nil))
|
||||
{:type :splat :data splatted :token origin})
|
||||
(capture pattern parser)))
|
||||
(try (pattern parser) ([e] e))))
|
||||
(array/push (ast :data) term)
|
||||
(try (separators parser)
|
||||
([e] (pp e) (array/push (ast :data) e))))
|
||||
|
@ -477,9 +471,9 @@
|
|||
(def term (if (check parser :splat)
|
||||
(do
|
||||
(advance parser)
|
||||
(def splatted (when (check parser :word) (word-only parser)))
|
||||
(def splatted (if (check parser :word) (word parser) nil))
|
||||
{:type :splat :data splatted :token origin})
|
||||
(capture pattern parser)))
|
||||
(try (pattern parser) ([e] e))))
|
||||
(array/push (ast :data) term)
|
||||
(try (separators parser)
|
||||
([e] (array/push (ast :data) e))))
|
||||
|
@ -498,8 +492,8 @@
|
|||
(error err))
|
||||
(def origin (current parser))
|
||||
(def term (case (type origin)
|
||||
:splat {:type :splat :data (when (check (advance parser) :word) (word-only parser)) :token origin}
|
||||
:word (capture word-pattern parser)
|
||||
:splat {:type :splat :data (try (word (advance parser)) ([_] nil)) :token origin}
|
||||
:word (try (word parser) ([e] e))
|
||||
:keyword (do
|
||||
(def key (capture kw parser))
|
||||
(def value (capture pattern parser))
|
||||
|
@ -664,49 +658,39 @@
|
|||
(expect parser :with) (advance parser)
|
||||
(try
|
||||
(do
|
||||
(expect parser :lbrace) (var lbrace (current parser)) (advance parser)
|
||||
(expect parser :lbrace) (advance parser)
|
||||
(accept-many parser ;terminators)
|
||||
(def data @[])
|
||||
(def clauses @[])
|
||||
(array/push clauses (with-clause parser))
|
||||
(accept-many parser ;terminators)
|
||||
(while (not (check parser :rbrace))
|
||||
(if (check parser :eof)
|
||||
(error {:type :error :data [clauses] :token lbrace :msg "unclosed brace"}))
|
||||
(error {:type :error :data data :token origin :msg "unclosed brace"}))
|
||||
(array/push clauses (with-clause parser))
|
||||
(accept-many parser ;terminators))
|
||||
(advance parser) # consume closing brace
|
||||
(array/push data clauses)
|
||||
(accept-many parser :newline)
|
||||
(expect parser :then) (advance parser)
|
||||
(def then (nonbinding parser))
|
||||
(array/push data (nonbinding parser))
|
||||
(accept-many parser :newline)
|
||||
(expect parser :else) (advance parser)
|
||||
(expect parser :lbrace) (set lbrace (current parser)) (advance parser)
|
||||
(accept-many parser ;terminators)
|
||||
(def else @[])
|
||||
(while (not (check parser :rbrace))
|
||||
(when (check parser :eof) (error {:type :error :token lbrace :data [else] :msg "unclosed brace"}))
|
||||
(array/push else (match-clause parser)))
|
||||
(advance parser)
|
||||
{:type :with :data [clauses then else] :token origin})
|
||||
(array/push data (nonbinding parser))
|
||||
{:type :with :data data :token origin})
|
||||
([err] err)
|
||||
)
|
||||
)
|
||||
|
||||
### function forms
|
||||
(defn- fn-simple [parser]
|
||||
(print "parsing simple function body")
|
||||
(try
|
||||
(do
|
||||
(def lhs (tup-pattern parser))
|
||||
(print "parsed lhs")
|
||||
(def guard (when (check parser :if)
|
||||
(advance parser)
|
||||
(simple parser)))
|
||||
(print "parsed guard")
|
||||
(expect parser :arrow) (advance parser)
|
||||
(print "parsed arrow")
|
||||
(def rhs (nonbinding parser))
|
||||
(print "parsed rhs")
|
||||
[[lhs guard rhs]]
|
||||
)
|
||||
([err] err)
|
||||
|
@ -734,7 +718,6 @@
|
|||
)
|
||||
|
||||
(defn- fn-clauses [parser]
|
||||
(print "parsing fn clauses")
|
||||
(def origin (current parser))
|
||||
(expect parser :lbrace) (advance parser)
|
||||
(accept-many parser ;terminators)
|
||||
|
@ -745,31 +728,25 @@
|
|||
(array/push data (capture fn-clause parser)))
|
||||
data)
|
||||
|
||||
(defn- lambda [parser]
|
||||
(def origin (current parser))
|
||||
(expect parser :fn) (advance parser)
|
||||
{:type :fn :data (fn-simple parser) :token origin})
|
||||
|
||||
(defn- fnn [parser]
|
||||
(if (= :lparen (-> parser peek type)) (break (lambda parser)))
|
||||
(try
|
||||
(do
|
||||
(print "parsing named function")
|
||||
(def origin (current parser))
|
||||
(expect parser :fn) (advance parser)
|
||||
(print "consumed `fn`")
|
||||
(print "next token: ")
|
||||
(pp (current parser))
|
||||
(def name (-> parser word-only (get :data)))
|
||||
(print "function name: ")
|
||||
(pp name)
|
||||
(def name (word parser))
|
||||
(def data (case (-> parser current type)
|
||||
:lbrace (fn-clauses parser)
|
||||
:lparen (fn-simple parser)
|
||||
(panic parser (string "expected clause or clauses, got " (-> current parser type)))))
|
||||
{:type :fn :name name :data data :token origin})
|
||||
{:type :fn :name name :data data :token origin}
|
||||
)
|
||||
([err] err)))
|
||||
|
||||
(defn- lambda [parser]
|
||||
(def origin (current parser))
|
||||
(expect parser :fn) (advance parser)
|
||||
{:type :fn :data (fn-simple parser) :token origin})
|
||||
|
||||
### compoound forms
|
||||
(defn- block [parser]
|
||||
(def origin (current parser))
|
||||
|
@ -793,10 +770,7 @@
|
|||
(expect parser :do) (advance parser)
|
||||
(def data @[])
|
||||
(array/push data (capture simple parser))
|
||||
(print "added first expression. current token:")
|
||||
(pp (current parser))
|
||||
(while (check parser :pipeline)
|
||||
(advance parser)
|
||||
(accept-many parser :newline)
|
||||
(array/push data (capture simple parser)))
|
||||
{:type :do :data data :token origin})
|
||||
|
@ -807,7 +781,7 @@
|
|||
(expect parser :ref) (advance parser)
|
||||
(try
|
||||
(do
|
||||
(def name (-> parser word-only (get :data)))
|
||||
(def name (word parser))
|
||||
(expect parser :equals) (advance parser)
|
||||
(def value (nonbinding parser))
|
||||
{:type :ref :data value :name name :token origin})
|
||||
|
@ -833,7 +807,7 @@
|
|||
(do
|
||||
(def origin (current parser))
|
||||
(expect parser :pkg) (advance parser)
|
||||
(def name (-> parser pkg-name (get :data)))
|
||||
(def name (pkg-name parser))
|
||||
(expect parser :lbrace) (advance parser)
|
||||
(accept-many parser ;terminators)
|
||||
(def data @[])
|
||||
|
@ -848,7 +822,7 @@
|
|||
(def key (capture kw parser))
|
||||
(def value (capture simple parser))
|
||||
(array/push data {:type :pair :data [key value] :token origin}))
|
||||
:word (array/push (capture word-only parser))
|
||||
:word (array/push (capture word parser))
|
||||
(panic parser "expected dict term"))
|
||||
(terminator parser))
|
||||
{:type :pkg :data data :token origin :name name})
|
||||
|
@ -859,7 +833,7 @@
|
|||
(do
|
||||
(def origin (current parser))
|
||||
(expect parser :ns) (advance parser)
|
||||
(def name (-> parser pkg-name (get :data)))
|
||||
(def name (pkg-name parser))
|
||||
(def body (block parser))
|
||||
{:type :ns :data body :name name :token origin})
|
||||
([err] err)))
|
||||
|
@ -869,9 +843,7 @@
|
|||
(expect parser :import) (advance parser)
|
||||
(def path (str parser))
|
||||
(expect parser :as) (advance parser)
|
||||
(def name-parser (if (check parser :pkg-name) pkg-name word-only))
|
||||
(def name
|
||||
(-> parser name-parser (get :data)))
|
||||
(def name (pkg-name parser))
|
||||
{:type :import :data path :name name :token origin})
|
||||
|
||||
### tests
|
||||
|
@ -902,21 +874,14 @@
|
|||
|
||||
(defn- repeatt [parser]
|
||||
(def origin (current parser))
|
||||
(advance parser)
|
||||
(def times (case (-> parser current type)
|
||||
:number (num parser)
|
||||
:word (word-only parser)
|
||||
:word (word parser)
|
||||
(panic parser "expected number or word")
|
||||
))
|
||||
(def body (block parser))
|
||||
{:type :repeat :data [times body] :token origin})
|
||||
|
||||
### panics
|
||||
(defn- panicc [parser]
|
||||
(def origin (current parser))
|
||||
(expect parser :panic) (advance parser)
|
||||
{:type :panic :data (nonbinding parser) :token origin})
|
||||
|
||||
### expressions
|
||||
# four levels of expression complexity:
|
||||
# simple (atoms, collections, synthetic expressions; no conditionals or binding or blocks)
|
||||
|
@ -939,10 +904,9 @@
|
|||
:lbracket (list parser)
|
||||
:startdict (dict parser)
|
||||
:startset (sett parser)
|
||||
:word (word-expr parser)
|
||||
:word (word parser)
|
||||
:pkg-name (pkg-name parser)
|
||||
:recur (recur parser)
|
||||
:panic (panicc parser)
|
||||
(panic parser (string expect "expected simple expression, got " (type curr)))
|
||||
)
|
||||
)
|
||||
|
@ -972,7 +936,7 @@
|
|||
:startset (sett parser)
|
||||
|
||||
# synthetic
|
||||
:word (word-expr parser)
|
||||
:word (word parser)
|
||||
:pkg-name (pkg-name parser)
|
||||
:recur (recur parser)
|
||||
|
||||
|
@ -991,13 +955,6 @@
|
|||
# blocks
|
||||
:lbrace (block parser)
|
||||
|
||||
# looping forms
|
||||
:loop (loopp parser)
|
||||
:repeat (repeatt parser)
|
||||
|
||||
# panic!
|
||||
:panic (panicc parser)
|
||||
|
||||
(panic parser (string "expected nonbinding expression, got " (type curr)))
|
||||
)
|
||||
)
|
||||
|
@ -1021,7 +978,7 @@
|
|||
:lbracket (list parser)
|
||||
:startdict (dict parser)
|
||||
:startset (sett parser)
|
||||
:word (word-expr parser)
|
||||
:word (word parser)
|
||||
:pkg-name (pkg-name parser)
|
||||
:recur (recur parser)
|
||||
:if (iff parser)
|
||||
|
@ -1030,9 +987,6 @@
|
|||
:with (withh parser)
|
||||
:do (doo parser)
|
||||
:lbrace (block parser)
|
||||
:loop (loopp parser)
|
||||
:repeat (repeatt parser)
|
||||
:panic (panicc parser)
|
||||
(panic parser (string "expected expression, got " (type curr)))
|
||||
)
|
||||
)
|
||||
|
@ -1081,14 +1035,13 @@
|
|||
(do
|
||||
#(comment
|
||||
(def source `
|
||||
panic! foo
|
||||
fn foo (x) -> :foo
|
||||
`)
|
||||
(def scanned (s/scan source))
|
||||
(def a-parser (new-parser scanned))
|
||||
(def parsed (script a-parser))
|
||||
(print "\n***NEW PARSE***\n")
|
||||
(def parsed (toplevel a-parser))
|
||||
# (print (pp-ast parsed))
|
||||
(pp parsed)
|
||||
(print (pp-ast parsed))
|
||||
)
|
||||
|
||||
|
||||
|
@ -1096,3 +1049,4 @@ panic! foo
|
|||
# TODO:
|
||||
# DECIDE:
|
||||
# - when to use a flat try/catch format, and when to use capture/expect-ret to get values instead of errors
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@
|
|||
"\n" (add-token (update scanner :line inc) :newline)
|
||||
"\\" (add-token scanner :backslash)
|
||||
"=" (add-token scanner :equals)
|
||||
">" (add-token scanner :pipeline)
|
||||
">" (add-token (add-token scanner :break) :pipeline)
|
||||
|
||||
## two-character tokens
|
||||
## ->
|
||||
|
|
|
@ -13,8 +13,5 @@ Tracking here, before I start writing this code, the kinds of validation we're h
|
|||
* first-level property access with pkg, e.g. `Foo :bar`--bar must be on Foo
|
||||
* recur in tail position in `loop` forms
|
||||
* recur not called outside of `loop` forms
|
||||
* arity checking where possible
|
||||
- loop forms
|
||||
- try to resolve function name, if you can, check arity of call
|
||||
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Block a user