finally get when clauses & forms right
This commit is contained in:
parent
942f55fb39
commit
4f16cf5cb0
|
@ -116,8 +116,8 @@
|
||||||
|
|
||||||
(defn- expect-ret
|
(defn- expect-ret
|
||||||
"Same as expect, but captures the error, returning it as a value"
|
"Same as expect, but captures the error, returning it as a value"
|
||||||
[parser type]
|
[parser type & types]
|
||||||
(try (expect parser type) ([e] e)))
|
(try (expect parser type ;types) ([e] e)))
|
||||||
|
|
||||||
(defn- capture
|
(defn- capture
|
||||||
"Applies the parse function to the parser, returning the parsed AST. If there is a panic, captures the panic and returns it as a value."
|
"Applies the parse function to the parser, returning the parsed AST. If there is a panic, captures the panic and returns it as a value."
|
||||||
|
@ -126,13 +126,13 @@
|
||||||
|
|
||||||
(defn- accept-one
|
(defn- accept-one
|
||||||
"Accepts a single token of passed type, advancing the parser if a match, doing nothing if not."
|
"Accepts a single token of passed type, advancing the parser if a match, doing nothing if not."
|
||||||
[parser type]
|
[parser type & types]
|
||||||
(if (check parser type) (advance parser)))
|
(if (check parser type ;types) (advance parser)))
|
||||||
|
|
||||||
(defn- accept-many
|
(defn- accept-many
|
||||||
"Accepts any number of tokens of a passed type, advancing the parser on match until there are no more matches. Does nothing on no match."
|
"Accepts any number of tokens of a passed type, advancing the parser on match until there are no more matches. Does nothing on no match."
|
||||||
[parser type]
|
[parser type & types]
|
||||||
(while (check parser type) (advance parser)))
|
(while (check parser type ;types) (advance parser)))
|
||||||
|
|
||||||
# atoms
|
# atoms
|
||||||
(defn- bool [parser]
|
(defn- bool [parser]
|
||||||
|
@ -310,6 +310,8 @@
|
||||||
(advance parser)
|
(advance parser)
|
||||||
ast)
|
ast)
|
||||||
|
|
||||||
|
### patterns
|
||||||
|
|
||||||
### conditional forms
|
### conditional forms
|
||||||
# if {simple} then {nonbinding} else {nonbinding}
|
# if {simple} then {nonbinding} else {nonbinding}
|
||||||
(defn- iff [parser]
|
(defn- iff [parser]
|
||||||
|
@ -328,42 +330,39 @@
|
||||||
(array/push (ast :data) (capture nonbinding parser))
|
(array/push (ast :data) (capture nonbinding parser))
|
||||||
ast)
|
ast)
|
||||||
|
|
||||||
### XXX: We've got an off-by-one error here
|
|
||||||
# We're expecting a terminator, we panic until we get to a terminator, and we then return back to something that expects a terminator, and now we've started parsing again *at the terminator*
|
|
||||||
(defn- terminator [parser]
|
(defn- terminator [parser]
|
||||||
(if-not (terminates? parser)
|
(if-not (terminates? parser)
|
||||||
# this line panics, captures the panic, advances the parser, and re-throws the error
|
# this line panics, captures the panic, advances the parser, and re-throws the error; solves an off-by-one error
|
||||||
(try (panic parser "expected terminator") ([e] (advance parser) (error e))))
|
(panic parser "expected terminator"))
|
||||||
(advance parser)
|
(advance parser)
|
||||||
(while (terminates? parser) (advance parser)))
|
(while (terminates? parser) (advance parser)))
|
||||||
|
|
||||||
# {simple} -> {nonbinding} {terminator}
|
# {simple} -> {nonbinding} {terminator}
|
||||||
(defn- when-clause [parser]
|
(defn- when-clause [parser]
|
||||||
(def clause @[])
|
(try
|
||||||
(print "parsing lhs: " (-> parser current type))
|
(do
|
||||||
(array/push clause (capture simple parser))
|
(def lhs (simple parser))
|
||||||
(print "parsing arrow")
|
(expect parser :arrow)
|
||||||
(if-let [err (expect-ret parser :arrow)]
|
(advance parser)
|
||||||
(array/push clause err)
|
|
||||||
(advance parser))
|
|
||||||
(print "accepting newlines")
|
|
||||||
(accept-many parser :newline)
|
(accept-many parser :newline)
|
||||||
(print "parsing rhs")
|
(def rhs (nonbinding parser))
|
||||||
(array/push clause (nonbinding parser))
|
(terminator parser)
|
||||||
(print "parsing terminator")
|
[lhs rhs])
|
||||||
(try (terminator parser) ([e] (array/push clause e)))
|
([err]
|
||||||
clause)
|
(advance parser) # consume the breaking token
|
||||||
|
(accept-many parser :newline :semicolon :break) # ...and any additional ones
|
||||||
|
err)))
|
||||||
|
|
||||||
(defn- whenn [parser]
|
(defn- whenn [parser]
|
||||||
(def ast {:type :when :data @[] :origin (current parser)})
|
(def ast {:type :when :data @[] :origin (current parser)})
|
||||||
(advance parser) # consume cond
|
(advance parser) # consume when
|
||||||
(if-let [err (expect-ret parser :lbrace)]
|
(if-let [err (expect-ret parser :lbrace)]
|
||||||
(do
|
(do
|
||||||
(array/push (ast :data) err)
|
(array/push (ast :data) err)
|
||||||
(break ast))
|
(break ast)) # early return; just bail if we don't have {
|
||||||
(advance parser))
|
(advance parser))
|
||||||
(accept-many parser :newline)
|
(accept-many parser :newline)
|
||||||
(while (not (check parser :rbrace :eof))
|
(while (not (check parser :rbrace :eof)) # make sure we don't roll past eof
|
||||||
(array/push (ast :data) (capture when-clause parser)))
|
(array/push (ast :data) (capture when-clause parser)))
|
||||||
(advance parser)
|
(advance parser)
|
||||||
ast)
|
ast)
|
||||||
|
@ -515,8 +514,10 @@
|
||||||
(do
|
(do
|
||||||
#(comment
|
#(comment
|
||||||
(def source `when {
|
(def source `when {
|
||||||
|
a -> b
|
||||||
foo -> bar quux
|
foo -> bar quux
|
||||||
bar -> baz
|
-> baz
|
||||||
|
c -> d
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
(def scanned (s/scan source))
|
(def scanned (s/scan source))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user