Types
ParseError = object of ValueError
- Source Edit
ParseFn[T; R] = proc (s: var State[T]): Result[R]
- function defined to manipulate State for the next parser and return a result Source Edit
Parser[T; R] = object fn*: ParseFn[T, R] description*: string
- central object to wrap all ParseFns in Source Edit
Result[T] = object of RootObj kind*: ResultType ## states whether the result is a `Match` or `Failure` value*: Stream[T] ## `Parser`s translate from one stream to another hence result values are `Stream`s start_index*, end_index*: int ## start and end indices for the value/expected tag*: seq[string] ## an optional seq of strings that can be used to mark results for further processing description*: string ## describes what the value would represent. used when erroring on failed parsing expected*: Stream[T] ## for failures, what value wanted to be. used when erroring on failed parsing
- Result objects are returned by all parsers Source Edit
ResultType = enum Match, Failure
- Source Edit
Procs
proc `and`[T, R](parser, other: Parser[T, R]): Parser[T, R]
-
parser and other must both match at the current position in the stream
let p = test_proc(proc(c: char): auto = parseInt($c)>2, "greater than 2") and test_proc(proc(c: char): auto = parseInt($c)<= 10, "less than or equal to 10") echo p echo p.parse("4") # <Parser: greater than 2 and less than or equal to 10> # @['4'] p.parse("1") # Error: unhandled exception: failed to parse with error: Expected `greater than 2` got @['1'] @ 0:1 [ParseError]
Source Edit proc `not`[T, R](parser: Parser[T, R]): Parser[T, R]
-
inverts a Result so that a failure is instead a match and vice-versa
let p = not test_char('c') echo p echo p.parse("p") # <Parser: not char c> # @['p']
Source Edit proc `or`[T, R](parser, other: Parser[T, R]): Parser[T, R]
-
parser or other must match
let p = test_char('c') or test_char('p') echo p echo p.parse("p") # <Parser: char c or char p> # @['p']
Source Edit proc failure[T](start_index, end_index: int; description: string): Result[T]
- function to generate Failure Results without an expected value Source Edit
proc failure[T](start_index, end_index: int; expected: Stream[T]; description: string): Result[T]
- function to generate Failure Results with an expected value Source Edit
proc many(parser: Parser): Parser
-
finds parser until it doesn't
let t = (test_char('c')).many().then(test_char('p')) echo t echo t.parse("ccccp") # <Parser: char c many times then char p> # @['c', 'c', 'c', 'c', 'p']
Source Edit proc map[T, R, NR](parser: Parser[T, R]; item: NR): Parser[T, NR]
- takes a parser that goes from Stream[T]->Stream[R] and transforms it to Stream[T]->Stream[NR] Source Edit
proc map[T, R, NR](parser: Parser[T, R]; map_fn: proc (x: R): NR): Parser[T, NR]
- takes a parser that goes from Stream[T]->Stream[R] and transforms it to Stream[T]->Stream[NR] Source Edit
proc map[T, R, NR](parser: Parser[T, R]; map_fn: proc (x: seq[R]): seq[NR]): Parser[ T, NR]
- takes a parser that goes from Stream[T]->Stream[R] and transforms it to Stream[T]->Stream[NR] Source Edit
proc pad(parser: Parser[char, char]): Parser[char, char] {. ...raises: [ValueError, RegexError], tags: [].}
-
optional whitespace
echo test_char('c').pad.parse("c ") # @['c']
Source Edit proc pad(parser: Parser[char, string]): Parser[char, string] {. ...raises: [ValueError, RegexError], tags: [].}
-
optional whitespace
echo test_string("hello").pad.parse("hello ") # @["hello"]
Source Edit proc parse[char, R](parser: Parser[char, R]; stream: string): Stream[R]
- run a parser on a stream that is a string Source Edit
proc parse[T, R](parser: Parser[T, R]; stream: Stream[T]): Stream[R]
- run a parser on a stream Source Edit
proc skip[T, R](parser, other: Parser[T, R]): Parser[T, R]
- parses parser then other but ignores other result Source Edit
proc space(parser: Parser[char, char]): Parser[char, char] {. ...raises: [ValueError], tags: [].}
-
optional whitespace
echo test_char('c').space.parse("c ") # @['c']
Source Edit proc space(parser: Parser[char, string]): Parser[char, string] {. ...raises: [ValueError], tags: [].}
-
optional whitespace
let p = test_string("9").space echo p.parse("9") # @["9"]
Source Edit proc success[T](start_index, end_index: int; value: Stream[T]; description: string): Result[T]
- function to generate Match Results Source Edit
proc tag[T, R](parser: Parser[T, R]; tag: string): Parser[T, R]
- creates a parser that tags parser results Source Edit
proc test_char(test: char): Parser[char, char] {....raises: [], tags: [].}
- test if a char is next in the stream (usually a string for char test) Source Edit
proc test_item[T](test: T; description: string): auto
- test if a single test item is next in the stream Source Edit
proc test_proc[T](test_proc_var: proc (x: T): bool; description: string): Parser[ T, T]
-
tests a procedure against the next value in the stream
let p = test_proc(proc(c: char): auto = parseInt($c)>2, "greater than 2") echo p echo p.parse("4") # <Parser: greater than 2> # @['4']
Source Edit proc test_proc[T](test_proc_var: proc (x: T): bool; description: string; expected: T): Parser[T, T]
-
tests a procedure against the next value in the stream
let p = test_proc(proc(c: char): auto = c== '4', "the character '4'", "'4'") echo p echo p.parse("4") # <Parser: the character '4'> # @['4']
Source Edit proc test_regex(pattern: Regex; description: string): Parser[char, string] {. ...raises: [ValueError], tags: [].}
-
tests if a regex pattern is next in a stream
let r = test_regex(re"[a-zA-Z_][a-zA-Z0-9_]*", "identifier") echo r echo r.parse("_hello1984") # <Parser: regex identifier> # @["_hello1984"]
Source Edit proc test_regex_string(pattern: Regex; description: string): Parser[string, string] {....raises: [], tags: [].}
- Source Edit
proc test_seq[T](test_seq: Stream[T]; description: string): Parser[T, T]
-
tests if the test_seq is the next sequence of the state's stream
let t = test_seq("abc".to_seq, "alphabet") echo t echo t.parse("abc") # <Parser: alphabet> # @['a', 'b', 'c']
Source Edit proc test_string(test: string): auto {....raises: [ValueError], tags: [].}
-
tests if a string is next in a stream (special case of test_seq)
let t = test_string("abc") echo t echo t.parse("abc") # <Parser: string abc> # @["abc"]
Source Edit proc then[T, R](parser, other: Parser[T, R]): Parser[T, R]
-
parses parser then other and rolls them together
let t = test_char('c').then(test_char('p')) echo t echo t.parse("cp") # <Parser: char c then char p> # @['c', 'p']
Source Edit