Skip to content

Parser State Functions

Armando Blancas edited this page May 26, 2018 · 6 revisions

The parser state is made up of the input text, the position record, and a single value supplied by client code. The position record contains a string to identify the input (e.g. a filename), line and column numbers. The following functions are used just like parsers but the work on the state. Kern has no mutable state; these are all pure functions.

The state functions are located in the blancas.kern.core namespace.

(use 'blancas.kern.core)

get-state obtains the user state from the parser state record. This value may have been placed there from the evaluation function (e.g. run or value) or a call to put-state. This can be any kind of value. Since this is technically a parser, we obtain the result as if it were parsed from the input, namely as the :value field in the parser state record.

(value (bind [x get-state] (return x)) "input" "testing" {:foo :bar})
;; {:foo :bar}

In the above sample we call value with a parser, some input, a label for testing, and a map as the initial value for user state. The given parser simply gets the user state and returns it.

put-state sets an arbitrary value as the new user state, replacing any previous one. Since the result of this function isn't visible as a parsed value, the following sample just ignores it; then it gets the new value with get-state.

(value (bind [_ (put-state {:foo :bar})
              x get-state] 
         (return x)) "xyz")
;; {:foo :bar}

modify-state changes the user state by applying the supplied function on it, along with any other arguments.

(value (bind [_ (put-state {:foo :bar})
              _ (modify-state assoc :foobar :baz)
              x get-state] 
         (return x)) "xyz")
;; {:foobar :baz, :foo :bar}

get-input provides the input text as a parser result.

(value (bind [_ (field* " ") 
              x get-input] 
         (return x)) 
       "Now is the time")
;; (\space \i \s \space \t \h \e \space \t \i \m \e)

This sample reads the first word and then gets the input, which is the rest of the text.

set-input puts a new text in place as input for the parser.

(value (bind [_ (set-input "1984")
              x dec-num] 
         (return x)) 
       "Now is the time")
;; 1984

get-position obtains the position record as a parsed value. This record has three fields: :src, :line, and :col.

(value (bind [_ (field* " ") 
              x get-position] 
         (return [(:src x) (:line x) (:col x)])) 
       "Now is the time" "testing")
;; ["testing" 1 4]

set-position sets a new position record in the parser record. The following sample starts with some input but the parser sets a new one and then parses it, much like an include file would be processed.

(value (bind [i get-input          ;; save input and position
              p get-position
              _ (set-input "747")  ;; set new input and position, as in an include file
              _ (set-position (->PPosition "plane" 1 1))
              n dec-num            ;; parse the new input
              _ (set-input i)      ;; restore the original input and position
              _ (set-position p)]
         (return n))
       "Now is the time" "testing")
;; 747
Clone this wiki locally