class Pars3k::Parse

Defined in:

pars3k.cr

Class Method Summary

Class Method Detail

def self.alphabet #
Parse.alphabet_lower | Parse.alphabet_upper

Parses a character in the alphabet regardless of case.


[View source]
def self.alphabet_lower #
Parse.one_char_of "abcdefghijklmnopqrstuvwxyz"

Parses a character of the lowercase alphabet.


[View source]
def self.alphabet_upper #
Parse.one_char_of "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

Parses a character of the uppercase alphabet.


[View source]
def self.char(char : Char) #
p = Parse.char 'a'
puts p.parse "abc" #=> a
puts p.parse "bca" #=> expected 'a', got 'b'
puts p.parse "cab" #=> expected 'a', got 'c'

Parse.char(c : Char) creates a Parser(Char) that looks at the current parse position and expects c.


[View source]
def self.constant(value : T) : Parser(T) forall T #
p = Parse.constant "abc"
puts p.parse "abc" #=> abc
puts p.parse "123" #=> abc
puts p.parse "" #=> abc

Parse.constant(value : T) creates a Parser(T) that always succeeds with value. This method is used to create final parse results using the do_parse macro.


[View source]
def self.delimited_list(parser : Parser(A), delimiter : Parser(B)) : Parser(Array(A)) forall A, B #
whitespace = Parse.many_of Parse.char ' '
comma = whitespace >> Parse.char(',') >> whitespace
word = Parse.join Parse.one_or_more_of Parse.one_char_of "abcdefghijklmnopqrstuvwxyz01234567890"
list = Parse.delimited_list word, comma
puts list.parse "" #=> []
puts list.parse "hello, world" #=> ["hello", "world"]
puts list.parse "par ,  s3k" #=> ["par", "s3k"]
puts list.parse "!!!, hello" #=> []

Parse.delimited_list(p : Parser(T), d : Parser(B)) creates a Parser(Array(T)) that will continue to parse with p delimited by d until an error with either occurs.


[View source]
def self.digit #
Parse.one_char_of "0123456789"

Parses a digit as a character.


[View source]
def self.float #
do_parse({
  whole <= (Parse.join Parse.one_or_more_of Parse.digit),
  _ <= (Parse.one_of? char '.'),
  decimal <= (Parse.join Parse.many_of Parse.digit),
  Parse.constant "#{whole}#{decimal.size == 0 ? ".0" : "." + decimal}".to_f
})

Parses a float as an actual Float.


[View source]
def self.if_not_nil?(parser : Parser(T), value : B) : Parser(T | Nil) forall T, B #
parser = (Parse.one_of? Parse.char 'a').sequence do |a|
  (Parse.if_not_nil? Parse.char('b'), char).sequence do |b|
    Parse.constant({a, b})
  end
end
puts parser.parse "ab" #=> {'a', 'b'}
puts parser.parse "ac" #=> expected 'b', got 'c'
puts parser.parse "b" #=> {nil, nil}

Parse.if_not_nil?(p : Parser(T), value : B?) creates a Parser(T | Nil) that will always return nil if the initial value is nil. This is to be used with do_parse or Parser#sequence. It can be used to ignore parsers if one before it yielded a nil value.


[View source]
def self.int #
(Parse.join Parse.one_or_more_of Parse.digit).transform &.to_i

Parses an integer as an actual Int.


[View source]
def self.join(parser : Parser(Array(Char))) : Parser(String) #
alphabet = Parse.one_char_of "abcdefghijklmnopqrstuvwxyz"
word = Parse.many_of alphabet
word_joined = Parse.join word
puts word.parse "hello" #=> ['h', 'e', 'l', 'l', 'o']
puts word_joined.parse "hello" #=> hello

Parse.join(p : Parser(Char)) transforms the parser p by adding all of the characters of a result into a string.


[View source]
def self.many_of(parser : Parser(T)) : Parser(Array(T)) forall T #
char_a = Parse.char 'a'
many_space = Parse.many_of char_a
puts p.parse "abc" #=> ['a']
puts p.parse "aabbcc" #=> ['a', 'a']
puts p.parse "aaaaaah" #=> ['a', 'a', 'a', 'a', 'a', 'a']
puts p.parse "pars3k" #=> []

Parse.many_of(p : Parser(T)) creates a Parser(Array(T)) that continuously parses the parser p until it fails. It succeeds with an array of the successive values.


[View source]
def self.no_char_of(string : String) : Parser(Char) #
p = Parse.no_char_of "abc"
puts p.parse "apple" #=> expected no character of 'abc', got 'a'
puts p.parse "banana" #=> expected no character of 'abc', got 'b'
puts p.parse "carrot" #=> expected no character of 'abc', got 'c'
puts p.parse "dragonfruit" #=> d

Parse.no_char_of(s : String) functions identically to Parse.one_char_of, but reverses the expected input. If the current character is present in s, then the parse fails.


[View source]
def self.one_char_of(string : String) : Parser(Char) #
p = Parse.one_char_of "abc"
puts p.parse "apple" #=> a
puts p.parse "banana" #=> b
puts p.parse "carrot" #=> c
puts p.parse "dragonfruit" #=> expected 'c', got 'd'

Parse.one_char_of(s : String) creates a Parser(Char) that looks at the current parse position and expects the current character to be present in the string s.


[View source]
def self.one_of(parser : Parser(T)) : Parser(Array(T)) forall T #
char_a = Parse.char 'a'
set = Parse.one_of char_a
puts set.parse "" #=> []
puts set.parse "a" #=> ['a']
puts set.parse "aa" #=> ['a']

Parse.one_of(p : Parser(T)) is a shortcut to Parse.some_of(p, 0..1).


[View source]
def self.one_of?(parser : Parser(T)) : Parser(T | Nil) forall T #
set = Parse.one_of? Parse.char 'a'
puts set.parse "" #=> nil
puts set.parse "a" #=> a
puts set.parse "aa" #=> a

Parse.one_of?(p : Parser(T)) creates a Parser(T | Nil) that will return nil if no parse is found. Otherwise, it returns the value of T. To use the result effectively, check the return type with result.nil?.


[View source]
def self.one_or_more_of(parser : Parser(T)) : Parser(Array(T)) forall T #
char_a = Parse.one_char_of "act"
valid = Parse.one_or_more_of char_a
puts valid.parse "cat" #=> ['c', 'a', 't']
puts valid.parse "act" #=> ['a', 'c', 't']
puts valid.parse "t" #=> ['t']
puts valid.parse "nope" #=> expected 't', got 'n'

Parse.one_or_more_of(p : Parser(T)) creates a Parser(Array(T)) that works like Parse.many_of, but expects at least one parse to succeed. Returns with the error of the first failure if it does not succeed.


[View source]
def self.some_of(parser : Parser(T), range : Range) : Parser(Array(T)) forall T #
char_a = Parse.char 'a'
set = Parse.some_of char_a, 2..4
puts set.parse "" #=> expected 'a', got end of string
puts set.parse "a" #=> expected 'a', got end of string
puts set.parse "aa" #=> ['a', 'a']
puts set.parse "aaa" #=> ['a', 'a', 'a']
puts set.parse "aaaa" #=> ['a', 'a', 'a', 'a']
puts set.parse "aaaaa" #=> ['a', 'a', 'a', 'a']

Parse.some_of(p : Parser(T), r : Range) creates a Parser(Array(T)) that works like Parse.many_of, but fails if the number of successful parses is below the lower bound of the range r, and stops parsing if the number of successful parses goes over the limit. In this case, char_a is parsed between 2 and 4 times.


[View source]
def self.some_of(parser : Parser(T), count : Int32) : Parser(Array(T)) forall T #

[View source]
def self.string(string : String) : Parser(String) #
p = Parse.string "cat"
puts p.parse "cat" #=> cat
puts p.parse "dog" #=> expected 'c', got 'd'
puts p.parse "" #=> expected 'c', got end of string

Parse.string(s : String) creates a Parser(String) that looks at the current parse position expects the array of characters in the string s (s.chars) to be consecutively present.


[View source]
def self.word #
Parse.join Parse.one_or_more_of Parse.alphabet

Parses a full word of at least one character.


[View source]