rparsec2 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rparsec/alt_parser.rb +38 -0
- data/lib/rparsec/any_parser.rb +12 -0
- data/lib/rparsec/are_parser.rb +20 -0
- data/lib/rparsec/atom_parser.rb +16 -0
- data/lib/rparsec/best_parser.rb +44 -0
- data/lib/rparsec/bound_parser.rb +11 -0
- data/lib/rparsec/boundn_parser.rb +11 -0
- data/lib/rparsec/catch_parser.rb +17 -0
- data/lib/rparsec/context.rb +5 -3
- data/lib/rparsec/{misc.rb → def_helper.rb} +5 -8
- data/lib/rparsec/eof_parser.rb +11 -0
- data/lib/rparsec/error.rb +8 -12
- data/lib/rparsec/expect_parser.rb +18 -0
- data/lib/rparsec/expressions.rb +5 -19
- data/lib/rparsec/failure_parser.rb +10 -0
- data/lib/rparsec/failures.rb +31 -0
- data/lib/rparsec/followed_parser.rb +13 -0
- data/lib/rparsec/fragment_parser.rb +12 -0
- data/lib/rparsec/functor_mixin.rb +10 -31
- data/lib/rparsec/get_index_parser.rb +9 -0
- data/lib/rparsec/keywords.rb +9 -9
- data/lib/rparsec/lazy_parser.rb +10 -0
- data/lib/rparsec/locator.rb +9 -5
- data/lib/rparsec/look_ahead_sensitive_parser.rb +46 -0
- data/lib/rparsec/many__parser.rb +20 -0
- data/lib/rparsec/many_parser.rb +27 -0
- data/lib/rparsec/map_current_parser.rb +11 -0
- data/lib/rparsec/map_parser.rb +12 -0
- data/lib/rparsec/mapn_current_parser.rb +11 -0
- data/lib/rparsec/mapn_parser.rb +12 -0
- data/lib/rparsec/nested_parser.rb +47 -0
- data/lib/rparsec/not_parser.rb +27 -0
- data/lib/rparsec/one_parser.rb +9 -0
- data/lib/rparsec/operator_table.rb +29 -63
- data/lib/rparsec/parser.rb +14 -20
- data/lib/rparsec/parser_monad.rb +4 -17
- data/lib/rparsec/parsers.rb +52 -626
- data/lib/rparsec/peek_parser.rb +16 -0
- data/lib/rparsec/plus_parser.rb +32 -0
- data/lib/rparsec/regexp_parser.rb +17 -0
- data/lib/rparsec/repeat__parser.rb +13 -0
- data/lib/rparsec/repeat_parser.rb +15 -0
- data/lib/rparsec/satisfies_parser.rb +15 -0
- data/lib/rparsec/sequence_parser.rb +25 -0
- data/lib/rparsec/set_index_parser.rb +10 -0
- data/lib/rparsec/some__parser.rb +19 -0
- data/lib/rparsec/some_parser.rb +28 -0
- data/lib/rparsec/string_case_insensitive_parser.rb +26 -0
- data/lib/rparsec/throw_parser.rb +10 -0
- data/lib/rparsec/token.rb +9 -28
- data/lib/rparsec/token_parser.rb +14 -0
- data/lib/rparsec/value_parser.rb +10 -0
- data/lib/rparsec/watch_parser.rb +11 -0
- data/lib/rparsec/watchn_parser.rb +11 -0
- data/lib/rparsec/zero_parser.rb +9 -0
- data/lib/rparsec.rb +1 -1
- metadata +52 -7
- data/lib/rparsec/id_monad.rb +0 -19
@@ -0,0 +1,27 @@
|
|
1
|
+
require "rparsec/parser"
|
2
|
+
|
3
|
+
module RParsec
|
4
|
+
class ManyParser < Parser # :nodoc:
|
5
|
+
init :parser, :least
|
6
|
+
def _parse ctxt
|
7
|
+
result = []
|
8
|
+
@least.times do
|
9
|
+
return false unless @parser._parse ctxt
|
10
|
+
result << ctxt.result
|
11
|
+
end
|
12
|
+
while true
|
13
|
+
ind = ctxt.index
|
14
|
+
if @parser._parse ctxt
|
15
|
+
result << ctxt.result
|
16
|
+
return ctxt.retn(result) if ind == ctxt.index # infinite loop
|
17
|
+
next
|
18
|
+
end
|
19
|
+
if ind == ctxt.index
|
20
|
+
return ctxt.retn(result)
|
21
|
+
else
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "rparsec/parser"
|
2
|
+
require "rparsec/context"
|
3
|
+
|
4
|
+
module RParsec
|
5
|
+
class NestedParser < Parser # :nodoc:
|
6
|
+
init :parser1, :parser2
|
7
|
+
def _parse ctxt
|
8
|
+
ind = ctxt.index
|
9
|
+
return false unless @parser1._parse ctxt
|
10
|
+
_run_nested(ind, ctxt, ctxt.result, @parser2)
|
11
|
+
end
|
12
|
+
private
|
13
|
+
def _run_nested(start, ctxt, src, parser)
|
14
|
+
ctxt.error = nil
|
15
|
+
new_ctxt = nil
|
16
|
+
if src.kind_of? String
|
17
|
+
new_ctxt = ParseContext.new(src)
|
18
|
+
return true if _run_parser parser, ctxt, new_ctxt
|
19
|
+
ctxt.index = start + new_ctxt.index
|
20
|
+
elsif src.kind_of? Array
|
21
|
+
new_ctxt = ParseContext.new(src)
|
22
|
+
return true if _run_parser parser, ctxt, new_ctxt
|
23
|
+
ctxt.index = start + _get_index(new_ctxt) unless new_ctxt.eof
|
24
|
+
else
|
25
|
+
new_ctxt = ParseContext.new([src])
|
26
|
+
return true if _run_parser parser, ctxt, new_ctxt
|
27
|
+
ctxt.index = ind unless new_ctxt.eof
|
28
|
+
end
|
29
|
+
ctxt.error.index = ctxt.index
|
30
|
+
false
|
31
|
+
end
|
32
|
+
def _get_index ctxt
|
33
|
+
cur = ctxt.current
|
34
|
+
return cur.index if cur.respond_to? :index
|
35
|
+
ctxt.index
|
36
|
+
end
|
37
|
+
def _run_parser parser, old_ctxt, new_ctxt
|
38
|
+
if parser._parse new_ctxt
|
39
|
+
old_ctxt.result = new_ctxt.result
|
40
|
+
true
|
41
|
+
else
|
42
|
+
old_ctxt.error = new_ctxt.error
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "rparsec/look_ahead_sensitive_parser"
|
2
|
+
|
3
|
+
module RParsec
|
4
|
+
class NotParser < LookAheadSensitiveParser # :nodoc:
|
5
|
+
def initialize(parser, msg, la = 1)
|
6
|
+
super(la)
|
7
|
+
@parser = parser
|
8
|
+
@msg = msg
|
9
|
+
@name = "~#{parser.name}"
|
10
|
+
end
|
11
|
+
def _parse ctxt
|
12
|
+
ind = ctxt.index
|
13
|
+
if @parser._parse ctxt
|
14
|
+
ctxt.index = ind
|
15
|
+
return ctxt.expecting(@msg)
|
16
|
+
end
|
17
|
+
return ctxt.retn(nil) if visible(ctxt, ind)
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
def withLookahead(n)
|
21
|
+
NotParser.new(@parser, @msg, n)
|
22
|
+
end
|
23
|
+
def not()
|
24
|
+
@parser
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,8 +1,25 @@
|
|
1
1
|
module RParsec
|
2
2
|
#
|
3
3
|
# This class holds information about operator precedences and
|
4
|
-
# associativities.
|
5
|
-
#
|
4
|
+
# associativities. +prefix+, +postfix+, +infixl+, +infixr+, +infixn+ can be
|
5
|
+
# called to register operators.
|
6
|
+
#
|
7
|
+
# +prefix+ :: Defines a prefix operator that returns a unary +Proc+ object
|
8
|
+
# with a precedence associated. Returns +self+.
|
9
|
+
#
|
10
|
+
# +postfix+ :: Defines a postfix operator that returns a unary +Proc+ object
|
11
|
+
# with a precedence associated. Returns +self+.
|
12
|
+
#
|
13
|
+
# +infixl+ :: Defines a left associative infix operator that returns a
|
14
|
+
# binary +Proc+ object with a precedence associated. Returns
|
15
|
+
# +self+.
|
16
|
+
#
|
17
|
+
# +infixr+ :: Defines a right associative infix operator that returns a
|
18
|
+
# binary +Proc+ object with a precedence associated. Returns
|
19
|
+
# +self+.
|
20
|
+
#
|
21
|
+
# +infixn+ :: Defines a non-associative infix operator that returns a binary
|
22
|
+
# +Proc+ object with a precedence associated. Returns +self+.
|
6
23
|
#
|
7
24
|
class OperatorTable
|
8
25
|
|
@@ -12,15 +29,8 @@ module RParsec
|
|
12
29
|
attr_reader :operators # :nodoc:
|
13
30
|
|
14
31
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
def reinit # :nodoc:
|
18
|
-
@operators = []
|
19
|
-
end
|
20
|
-
|
21
|
-
#
|
22
|
-
# To create an OperatorTable instance. If a block is given, it is
|
23
|
-
# invoked to do post-instantiation. For example:
|
32
|
+
# To create an OperatorTable instance. If a block is given, it is invoked
|
33
|
+
# to do post-instantiation. For example:
|
24
34
|
#
|
25
35
|
# OperatorTable.new do |tbl|
|
26
36
|
# tbl.infixl(char(?+) >> Plus, 10)
|
@@ -30,60 +40,16 @@ module RParsec
|
|
30
40
|
# tbl.prefix(char(?-) >> Neg, 50)
|
31
41
|
# end
|
32
42
|
#
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
if block_given?
|
37
|
-
yield this
|
38
|
-
end
|
39
|
-
this
|
40
|
-
end
|
41
|
-
|
42
|
-
#
|
43
|
-
# Defines a prefix operator that returns a unary +Proc+ object with a precedence associated.
|
44
|
-
# Returns +self+.
|
45
|
-
#
|
46
|
-
def prefix(op, precedence)
|
47
|
-
add(:prefix, op, precedence)
|
48
|
-
end
|
49
|
-
|
50
|
-
#
|
51
|
-
# Defines a postfix operator that returns a unary +Proc+ object with a precedence associated.
|
52
|
-
# Returns +self+.
|
53
|
-
#
|
54
|
-
def postfix(op, precedence)
|
55
|
-
add(:postfix, op, precedence)
|
56
|
-
end
|
57
|
-
|
58
|
-
#
|
59
|
-
# Defines a left associative infix operator that returns a binary +Proc+ object with a precedence
|
60
|
-
# associated. Returns +self+.
|
61
|
-
#
|
62
|
-
def infixl(op, precedence)
|
63
|
-
add(:infixl, op, precedence)
|
64
|
-
end
|
65
|
-
|
66
|
-
#
|
67
|
-
# Defines a right associative infix operator that returns a binary +Proc+ object with a precedence
|
68
|
-
# associated. Returns +self+.
|
69
|
-
#
|
70
|
-
def infixr(op, precedence)
|
71
|
-
add(:infixr, op, precedence)
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
# Defines a non-associative infix operator that returns a binary +Proc+ object with a precedence
|
76
|
-
# associated. Returns +self+.
|
77
|
-
#
|
78
|
-
def infixn(op, precedence)
|
79
|
-
add(:infixn, op, precedence)
|
43
|
+
def initialize
|
44
|
+
@operators = []
|
45
|
+
block_given? and yield self
|
80
46
|
end
|
81
47
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
48
|
+
%i[prefix postfix infixl infixr infixn].each do |method|
|
49
|
+
define_method(method) do |op, precedence|
|
50
|
+
@operators << [method, op, precedence]
|
51
|
+
self
|
52
|
+
end
|
87
53
|
end
|
88
54
|
end
|
89
55
|
end
|
data/lib/rparsec/parser.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "rparsec/functors"
|
4
4
|
require "rparsec/monad"
|
5
|
-
require "rparsec/
|
5
|
+
require "rparsec/def_helper"
|
6
6
|
require "rparsec/parser_monad"
|
7
7
|
require "rparsec/context"
|
8
8
|
require "rparsec/error"
|
@@ -17,7 +17,6 @@ module RParsec
|
|
17
17
|
class Parser
|
18
18
|
include Functors
|
19
19
|
include Monad
|
20
|
-
extend DefHelper
|
21
20
|
MyMonad = ParserMonad.new
|
22
21
|
attr_accessor :name
|
23
22
|
|
@@ -47,8 +46,14 @@ module RParsec
|
|
47
46
|
|
48
47
|
def _display_current_input(input, _code, _index)
|
49
48
|
return 'EOF' if input.nil?
|
50
|
-
c = input
|
51
|
-
|
49
|
+
case (c = input)
|
50
|
+
when Integer
|
51
|
+
"'" << c << "'"
|
52
|
+
when Token
|
53
|
+
c.text
|
54
|
+
else
|
55
|
+
c.to_s
|
56
|
+
end
|
52
57
|
end
|
53
58
|
|
54
59
|
def _add_encountered_error(msg, encountered)
|
@@ -78,16 +83,6 @@ module RParsec
|
|
78
83
|
_display_current_input(ctxt.error.input, src, ctxt.index)), src)
|
79
84
|
end
|
80
85
|
|
81
|
-
#
|
82
|
-
# Set name for the parser. +self+ is returned.
|
83
|
-
#
|
84
|
-
def set_name(nm)
|
85
|
-
@name = nm
|
86
|
-
self
|
87
|
-
end
|
88
|
-
|
89
|
-
alias setName set_name
|
90
|
-
|
91
86
|
#
|
92
87
|
# <tt>a.map { |x| x + 1 }</tt> will first execute parser +a+, when
|
93
88
|
# it succeeds, the associated block is executed to transform the
|
@@ -128,14 +123,14 @@ module RParsec
|
|
128
123
|
# input consumption is undone.
|
129
124
|
#
|
130
125
|
def atomize
|
131
|
-
AtomParser.new(self).
|
126
|
+
AtomParser.new(self).tap { |p| p.name = @name }
|
132
127
|
end
|
133
128
|
|
134
129
|
#
|
135
130
|
# Create a new parser that looks at inputs whthout consuming them.
|
136
131
|
#
|
137
132
|
def peek
|
138
|
-
PeekParser.new(self).
|
133
|
+
PeekParser.new(self).tap { |p| p.name = @name }
|
139
134
|
end
|
140
135
|
|
141
136
|
#
|
@@ -144,6 +139,7 @@ module RParsec
|
|
144
139
|
def not(msg = "#{self} unexpected")
|
145
140
|
NotParser.new(self, msg)
|
146
141
|
end
|
142
|
+
alias ~ not
|
147
143
|
|
148
144
|
#
|
149
145
|
# To create a parser that does "look ahead" for _n_ inputs.
|
@@ -168,6 +164,7 @@ module RParsec
|
|
168
164
|
def followed(other)
|
169
165
|
FollowedParser.new(self, other)
|
170
166
|
end
|
167
|
+
alias << followed
|
171
168
|
|
172
169
|
#
|
173
170
|
# To create a parser that repeats +self+ for a minimum +min+
|
@@ -184,6 +181,7 @@ module RParsec
|
|
184
181
|
Some_Parser.new(self, min, max)
|
185
182
|
end
|
186
183
|
end
|
184
|
+
alias * repeat_
|
187
185
|
|
188
186
|
#
|
189
187
|
# To create a parser that repeats +self+ for a minimum +min+
|
@@ -460,10 +458,6 @@ module RParsec
|
|
460
458
|
Parsers.sequence(operator, operand, &Idn)
|
461
459
|
end
|
462
460
|
|
463
|
-
alias ~ not
|
464
|
-
alias << followed
|
465
|
-
alias * repeat_
|
466
|
-
|
467
461
|
def _parse(_ctxt)
|
468
462
|
false
|
469
463
|
end
|
data/lib/rparsec/parser_monad.rb
CHANGED
@@ -3,23 +3,10 @@
|
|
3
3
|
module RParsec
|
4
4
|
|
5
5
|
class ParserMonad # :nodoc:
|
6
|
-
def fail msg
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def value v
|
11
|
-
return Nil if v.nil?
|
12
|
-
ValueParser.new(v);
|
13
|
-
end
|
14
|
-
|
15
|
-
def bind(v, &proc)
|
16
|
-
return v unless proc
|
17
|
-
BoundParser.new(v, proc);
|
18
|
-
end
|
19
|
-
|
20
|
-
def mplus(p1, p2)
|
21
|
-
PlusParser.new([p1, p2]);
|
22
|
-
end
|
6
|
+
def fail(msg) = FailureParser.new(msg)
|
7
|
+
def value(v) = v.nil? ? Nil : ValueParser.new(v)
|
8
|
+
def bind(v, &block) = block_given? ? BoundParser.new(v, block) : v
|
9
|
+
def mplus(p1, p2) = PlusParser.new([p1, p2])
|
23
10
|
end
|
24
11
|
|
25
12
|
end # module
|