Module: Rsec::Helpers
- Defined in:
- lib/rsec/helpers.rb
Overview
these are not callable from a parser
Instance Method Summary collapse
-
#lazy(&p) ⇒ Object
@ desc.helper Lazy parser is constructed when parsing starts.
-
#one_of(str, &p) ⇒ Object
@ desc.helper Parses one of chars in str @ example multiplicative = one_of ‘*/%’ assert_equal ‘/’, multiplicative.parse ‘/’ assert_equal Rsec::INVALID, actualmultiplicative.parse ‘+’.
-
#one_of_(str, &p) ⇒ Object
@ desc.helper See also #one_of#, with leading and trailing optional breakable spaces @ example additive = one_of_(‘+-’) assert_equal ‘+’, additive.parse(‘ +’).
-
#prim(type, options = {}, &p) ⇒ Object
@ desc.helper Primitive parser, returns nil if overflow or underflow.
-
#seq(*xs, &p) ⇒ Object
@ desc.helper Sequence parser @ example assert_equal [‘a’, ‘b’, ‘c’], actualseq(‘a’, ‘b’, ‘c’).parse(‘abc’).
-
#seq_(*xs, &p) ⇒ Object
@ desc.helper Sequence parser with skippable pattern(or parser) option :skip default= /s*/ @ example assert_equal [‘a’, ‘b’, ‘c’], actualseq_(‘a’, ‘b’, ‘c’, skip: ‘,’).parse(‘a,b,c’).
-
#symbol(pattern, skip = /\s*/, &p) ⇒ Object
@ desc.helper A symbol is something wrapped with optional space.
-
#word(pattern, &p) ⇒ Object
@ desc.helper A word is wrapped with word boundaries @ example assert_equal [‘yes’, ‘3’], seq(‘yes’, ‘3’).parse(‘yes3’) assert_equal INVALID, seq(word(‘yes’), ‘3’).parse(‘yes3’).
Instance Method Details
#lazy(&p) ⇒ Object
@ desc.helper
Lazy parser is constructed when parsing starts. It is useful to reference a parser not defined yet
@ example
parser = lazy{future}
future = 'jim'.r
assert_equal 'jim', parser.parse '12323'
17 18 19 20 |
# File 'lib/rsec/helpers.rb', line 17 def lazy &p raise ArgumentError, 'lazy() requires a block' unless p Lazy[p] end |
#one_of(str, &p) ⇒ Object
@ desc.helper
Parses one of chars in str
@ example
multiplicative = one_of '*/%'
assert_equal '/', multiplicative.parse '/'
assert_equal Rsec::INVALID, actualmultiplicative.parse '+'
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/rsec/helpers.rb', line 28 def one_of str, &p Rsec.assert_type str, String raise ArgumentError, 'str len should > 0' if str.empty? one_of_klass = if (str.bytesize == str.size) and Rsec.const_defined?(:OneOfByte) # for C-ext OneOfByte else OneOf end one_of_klass[str.dup.freeze].map p end |
#one_of_(str, &p) ⇒ Object
@ desc.helper
See also #one_of#, with leading and trailing optional breakable spaces
@ example
additive = one_of_('+-')
assert_equal '+', additive.parse(' +')
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/rsec/helpers.rb', line 46 def one_of_ str, &p Rsec.assert_type str, String raise ArgumentError, 'str len should > 0' if str.empty? raise ArgumentError, 'str should be ascii' unless str.bytesize == str.size raise ArgumentError, 'str should not contain space' if str =~ /\s/ spaced_one_of_klass = if (str.bytesize == str.size) and Rsec.const_defined?(:OneOfByte_) # for C-ext OneOfByte_ else OneOf_ end spaced_one_of_klass[str.dup.freeze].map p end |
#prim(type, options = {}, &p) ⇒ Object
@ desc.helper
Primitive parser, returns nil if overflow or underflow.
There can be an optional '+' or '-' at the beginning of string except unsinged_int32 | unsinged_int64.
type =
:double |
:hex_double |
:int32 |
:int64 |
:unsigned_int32 |
:unsigned_int64
options:
:allowed_sign => '+' | '-' | '' | '+-' (default '+-')
:allowed_signs => (same as :allowed_sign)
:base => integer only (default 10)
@ example
p = prim :double
assert_equal 1.23, p.parse('1.23')
p = prim :double, allowed_sign: '-'
assert_equal 1.23, p.parse('1.23')
assert_equal -1.23, p.parse('-1.23')
assert_equal Rsec::INVALID, p.parse('+1.23')
p = prim :int32, base: 36
assert_equal 49713, p.parse('12cx')
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/rsec/helpers.rb', line 84 def prim type, ={}, &p base = [:base] if [:double, :hex_double].index base raise 'Floating points does not allow :base' end base ||= 10 Rsec.assert_type base, Integer unless (2..36).include? base raise RangeError, ":base should be in 2..36, but got #{base}" end sign_strategy = \ case ([:allowed_sign] or [:allowed_signs]) when nil, '+-', '-+'; 3 when '+'; 2 when '-'; 1 when ''; 0 else raise "allowed_sign should be one of nil, '', '+', '-', '+-', '-+'" end parser = \ case type when :double; PDouble.new sign_strategy, false # decimal when :hex_double; raise "Removed because Ruby 1.9.3 removed float from hex" # PDouble.new sign_strategy, true # hex when :int32; PInt32.new sign_strategy, base when :int64; PInt64.new sign_strategy, base when :unsigned_int32; raise 'unsigned int not allow - sign' if [:allowed_signs] =~ /-/ PUnsignedInt32.new sign_strategy, base when :unsigned_int64; raise 'unsigned int not allow - sign' if [:allowed_signs] =~ /-/ PUnsignedInt64.new sign_strategy, base else raise "Invalid primitive type #{type}" end parser.map p end |
#seq(*xs, &p) ⇒ Object
@ desc.helper
Sequence parser
@ example
assert_equal ['a', 'b', 'c'], actualseq('a', 'b', 'c').parse('abc')
126 127 128 129 |
# File 'lib/rsec/helpers.rb', line 126 def seq *xs, &p xs.map! {|x| Rsec.make_parser x } Seq[xs].map p end |
#seq_(*xs, &p) ⇒ Object
@ desc.helper
Sequence parser with skippable pattern(or parser)
option
:skip default= /\s*/
@ example
assert_equal ['a', 'b', 'c'], actualseq_('a', 'b', 'c', skip: ',').parse('a,b,c')
137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/rsec/helpers.rb', line 137 def seq_ *xs, &p skipper = if (xs.last.is_a? Hash) xs.pop[:skip] end skipper = skipper ? Rsec.make_parser(skipper) : /\s*/.r xs.map! {|x| Rsec.make_parser x } first, *rest = xs raise 'sequence should not be empty' unless first Seq_[first, rest, skipper].map p end |
#symbol(pattern, skip = /\s*/, &p) ⇒ Object
@ desc.helper
A symbol is something wrapped with optional space
151 152 153 154 155 |
# File 'lib/rsec/helpers.rb', line 151 def symbol pattern, skip=/\s*/, &p pattern = Rsec.make_parser pattern skip = Rsec.try_skip_pattern Rsec.make_parser skip SeqOne[[skip, pattern, skip], 1].map p end |
#word(pattern, &p) ⇒ Object
@ desc.helper
A word is wrapped with word boundaries
@ example
assert_equal ['yes', '3'], seq('yes', '3').parse('yes3')
assert_equal INVALID, seq(word('yes'), '3').parse('yes3')
162 163 164 165 166 |
# File 'lib/rsec/helpers.rb', line 162 def word pattern, &p parser = Rsec.make_parser pattern # TODO check pattern type Pattern[/\b#{parser.some}\b/].map p end |