yaparc 0.2.3 → 0.4.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 +7 -0
- data/.document +3 -0
- data/.envrc +1 -0
- data/.rdoc_options +1 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README +106 -86
- data/Rakefile +27 -0
- data/TODO +11 -0
- data/lib/yaparc/abstract_parser.rb +16 -0
- data/lib/yaparc/alt.rb +22 -0
- data/lib/yaparc/apply.rb +18 -0
- data/lib/yaparc/char.rb +16 -0
- data/lib/yaparc/cr.rb +11 -0
- data/lib/yaparc/digit.rb +11 -0
- data/lib/yaparc/fail_parser.rb +11 -0
- data/lib/yaparc/ident.rb +18 -0
- data/lib/yaparc/identifier.rb +32 -0
- data/lib/yaparc/item.rb +17 -0
- data/lib/yaparc/literal.rb +13 -0
- data/lib/yaparc/many.rb +14 -0
- data/lib/yaparc/many_one.rb +27 -0
- data/lib/yaparc/nat.rb +11 -0
- data/lib/yaparc/natural.rb +12 -0
- data/lib/yaparc/no_fail.rb +20 -0
- data/lib/yaparc/parsable.rb +20 -0
- data/lib/yaparc/regex.rb +22 -0
- data/lib/yaparc/satisfy.rb +28 -0
- data/lib/yaparc/seq.rb +33 -0
- data/lib/yaparc/space.rb +11 -0
- data/lib/yaparc/string.rb +24 -0
- data/lib/yaparc/succeed.rb +14 -0
- data/lib/yaparc/symbol.rb +11 -0
- data/lib/yaparc/tokenize.rb +18 -0
- data/lib/yaparc/white_space.rb +11 -0
- data/lib/yaparc/zero_one.rb +20 -0
- data/lib/yaparc.rb +40 -605
- data/sig/yaparc.gen.rbs +217 -0
- data/sig/yaparc.rbs +4 -0
- data/yaparc.gemspec +36 -0
- metadata +115 -58
- data/test/n3-report.html +0 -169
- data/test/n3.bnf +0 -129
- data/test/test_abc.rb.bak +0 -112
- data/test/test_calc.rb +0 -112
- data/test/test_lambda.rb +0 -87
- data/test/test_metric.rb +0 -617
- data/test/test_owl.rb +0 -1039
- data/test/test_parser.rb +0 -460
- data/test/test_prolog.rb +0 -287
- data/test/test_sql.rb +0 -317
- data/test/test_uri.rb +0 -752
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: db3016ed938d0853130447ce2155b9e9978faf79798f137c99624d1539a9fc2b
|
|
4
|
+
data.tar.gz: 505b913fc07f99bf8cc7fb1be125aefedb767bb589d92f40c3bdc35ff6cccfb1
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d53c0470dac4fa661db80607a2e752ab830a751fdd14f3453f838a80ffcd13993b013d32a2aa4c171dc3e8d4cf85154651ed656179669796c8cdac5120503c66
|
|
7
|
+
data.tar.gz: 75a76818b13a77821106dd09c65c5ae2c3a005ca8361797b75167b708f57846c4664a267f1eb40bba2d7ec9e75ec995291a77e51353423bd232f921475374d59
|
data/.document
ADDED
data/.envrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
use guix ruby ruby-rubocop
|
data/.rdoc_options
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
main_page: README
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# yaparc change log
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.4.0 - 2026-06-23
|
|
6
|
+
|
|
7
|
+
* Remove `message` attribute from `Yaparc::Base`.
|
|
8
|
+
* Rename `Yaparc::Fail` to `Yaparc::FailParser`.
|
|
9
|
+
* Move `OK`, `Fail`, `Error` outside of `Result` and removed `Result` module.
|
|
10
|
+
* Remove `tree` attribute of `Parsable` module.
|
|
11
|
+
* Use newer keyword arguments. This might cause troubles with Ruby version 2
|
|
12
|
+
or lower.
|
|
13
|
+
* Limit `Tokenize`'s `prefix` and `postfix` write only.
|
|
14
|
+
|
|
15
|
+
## 0.3.0 - 2024-12-31
|
|
16
|
+
|
|
17
|
+
* Added `Yaparc::VERSION` constant.
|
|
18
|
+
* Removed `Yaparc` module's `@@identifier_regex` class variable.
|
|
19
|
+
* Added `Yaparc::IDENTIFIER_REGEX` constant.
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2007-2009 Akimichi Tatsukawa <akimichi.tatsukawa@gmail.com>
|
|
2
|
+
Copyright 2024 gemmaro <gemmaro.dev@gmail.com>
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the “Software”), to
|
|
6
|
+
deal in the Software without restriction, including without limitation the
|
|
7
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
8
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
data/README
CHANGED
|
@@ -1,57 +1,68 @@
|
|
|
1
|
-
=
|
|
1
|
+
= yaparc
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
== Synopsis
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
There are several implementations of parser combinator in Ruby. This is an
|
|
6
|
+
yet another simple combinator parser library in Ruby.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
* RubyGem (http://rubyforge.org/projects/rubygems/)
|
|
8
|
+
== Install
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
gem install yaparc
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
== Usage
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
In combinator parser, each parser is construct as a function taking input
|
|
15
|
+
string as arguments. Larger parsers are built from smaller parsers. Although
|
|
16
|
+
combinators are higher-order functions in ordinary functional languages, they
|
|
17
|
+
are constructed as classes in yaparc, because Ruby has more object-oriented
|
|
18
|
+
than functional property.
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
All parsers has +parse+ method, each of which takes input string as its
|
|
21
|
+
arguments except Yaparc::Satisfy parser. Every parser returns either
|
|
22
|
+
Yaparc::Result::OK or Yaparc::Result::Fail as their result of parsing. An
|
|
23
|
+
instance of Yaparc::Result::Fail denotes faiilure, and instance of
|
|
24
|
+
Yaparc::Result::OK indicates success.
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
=== Primitive Parsers
|
|
19
27
|
|
|
20
|
-
|
|
28
|
+
* Yaparc::Succeed
|
|
29
|
+
* Yaparc::FailParser
|
|
30
|
+
* Yaparc::Item
|
|
31
|
+
* Yaparc::Satisfy
|
|
21
32
|
|
|
22
|
-
|
|
23
|
-
* Fail
|
|
24
|
-
* Item
|
|
25
|
-
* Satisfy
|
|
33
|
+
==== Succeed class
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
The parser Yaparc::Succeed always succeeds with the result value, without
|
|
36
|
+
consuming any of the input string. In the following example,
|
|
37
|
+
Yaparc::Succeed#parse takes an input string <tt>blah, blah, blah</tt> and
|
|
38
|
+
returns the singleton array <tt>[[1, "blah, blah, blah"]]</tt>.
|
|
31
39
|
|
|
32
40
|
parser = Yaparc::Succeed.new(1)
|
|
33
41
|
parser.parse("blah, blah, blah")
|
|
34
|
-
|
|
42
|
+
#=> #<Yaparc::Result::OK:0xb7aaaf5c @input="blah, blah, blah", @value=1>
|
|
35
43
|
|
|
36
|
-
|
|
44
|
+
==== FailParser class
|
|
37
45
|
|
|
38
|
-
The parser
|
|
46
|
+
The parser Yaparc::FailParser always fails, regardless of the contents of the
|
|
47
|
+
input string.
|
|
39
48
|
|
|
40
|
-
parser = Yaparc::
|
|
49
|
+
parser = Yaparc::FailParser.new
|
|
41
50
|
parser.parse("abc")
|
|
42
|
-
|
|
51
|
+
#=> #<Yaparc::Result::FailParser:0xb7aa56b0 @value=nil>
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
==== Item class
|
|
45
54
|
|
|
46
|
-
The parser Item fails if the input string is empty, and succeeds with
|
|
55
|
+
The parser Yaparc::Item fails if the input string is empty, and succeeds with
|
|
56
|
+
the first character as the result value otherwise.
|
|
47
57
|
|
|
48
58
|
parser = Yaparc::Item.new
|
|
49
59
|
parser.parse("abc")
|
|
50
|
-
|
|
60
|
+
#=> #<Yaparc::Result::OK:0xb7a9fdb4 @input="bc", @value="a">
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
==== Satisfy class
|
|
53
63
|
|
|
54
|
-
The parser Satisfy recognizes a single input via predicate which
|
|
64
|
+
The parser Yaparc::Satisfy recognizes a single input via predicate which
|
|
65
|
+
determines if an arbitrary input is suitable for the predicate.
|
|
55
66
|
|
|
56
67
|
is_integer = lambda do |i|
|
|
57
68
|
begin
|
|
@@ -63,80 +74,71 @@ The parser Satisfy recognizes a single input via predicate which determines if a
|
|
|
63
74
|
end
|
|
64
75
|
parser = Yaparc::Satisfy.new(is_integer)
|
|
65
76
|
parser.parse("123")
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
== Combining Parsers
|
|
70
|
-
|
|
71
|
-
* Alt
|
|
72
|
-
* Seq
|
|
73
|
-
* Many
|
|
74
|
-
* ManyOne
|
|
77
|
+
#=> #<Yaparc::Result::OK:0xb7a8f284 @input="23", @value="1">
|
|
75
78
|
|
|
79
|
+
=== Combining Parsers
|
|
76
80
|
|
|
81
|
+
* Yaparc::Alt
|
|
82
|
+
* Yaparc::Seq
|
|
83
|
+
* Yaparc::Many
|
|
84
|
+
* Yaparc::ManyOne
|
|
77
85
|
|
|
78
|
-
|
|
86
|
+
==== Sequencing parser
|
|
79
87
|
|
|
80
|
-
The Seq corresponds to sequencing in BNF.
|
|
88
|
+
The Yaparc::Seq corresponds to sequencing in BNF. The following parser
|
|
89
|
+
recognizes anything that <tt>Symbol.new('+')</tt> or <tt>Natural.new</tt>
|
|
90
|
+
would if placed in succession.
|
|
81
91
|
|
|
82
92
|
parser = Seq.new(Symbol.new('+'), Natural.new)
|
|
83
93
|
parser.parse("+321")
|
|
84
|
-
|
|
94
|
+
#=> #<Yaparc::Result::OK:0xb7a81ae4 @input="", @value=321>
|
|
85
95
|
|
|
86
|
-
|
|
96
|
+
If a block given to Yaparc::Seq, it analyses input string to construct its
|
|
97
|
+
logical structure.
|
|
87
98
|
|
|
88
|
-
parser = Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do |
|
|
99
|
+
parser = Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do |plus, nat|
|
|
89
100
|
nat
|
|
90
101
|
end
|
|
91
102
|
parser.parse("+1234")
|
|
92
|
-
|
|
103
|
+
#=> #<Yaparc::Result::OK:0xb7a70a00 @input="", @value=1234>
|
|
93
104
|
|
|
94
105
|
It produces a parse tree which expounds the semantic structure of the program.
|
|
95
106
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
The parser Alt class is an alternation parser, which returns the result of the first parser to succeed, and failure if neither does.
|
|
107
|
+
==== Alternation parser
|
|
99
108
|
|
|
109
|
+
The parser Yaparc::Alt class is an alternation parser, which returns the
|
|
110
|
+
result of the first parser to succeed, and failure if neither does.
|
|
100
111
|
|
|
101
112
|
parser = Yaparc::Alt.new(
|
|
102
|
-
Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do |
|
|
113
|
+
Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do |_, nat|
|
|
103
114
|
nat
|
|
104
115
|
end,
|
|
105
116
|
Yaparc::Natural.new
|
|
106
117
|
)
|
|
107
118
|
parser.parse("1234")
|
|
108
|
-
|
|
119
|
+
#=> #<Yaparc::Result::OK:0xb7a5a610 @input="", @value=1234>
|
|
109
120
|
parser.parse("-1234")
|
|
110
|
-
|
|
121
|
+
#=> #<Yaparc::Result::Fail:0xb7a57ba4 @value=nil>
|
|
111
122
|
|
|
123
|
+
==== Many
|
|
112
124
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
In Many, zero or more applications of parser are admissible.
|
|
125
|
+
In Yaparc::Many, zero or more applications of parser are admissible.
|
|
116
126
|
|
|
117
127
|
parser = Yaparc::Many.new(Yaparc::Satisfy.new(lambda {|i| i > '0' and i < '9'}))
|
|
118
128
|
parser.parse("123abc")
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
=== ManyOne
|
|
122
|
-
|
|
123
|
-
The ManyOne requires at least one successfull application of parser.
|
|
124
|
-
|
|
129
|
+
#=> #<Yaparc::Result::OK:0xb7a49dc4 @input="abc", @value="123">
|
|
125
130
|
|
|
126
|
-
|
|
131
|
+
==== ManyOne
|
|
127
132
|
|
|
128
|
-
|
|
133
|
+
The Yaparc::ManyOne requires at least one successfull application of parser.
|
|
129
134
|
|
|
130
|
-
|
|
135
|
+
=== Tokenized parser
|
|
131
136
|
|
|
132
|
-
|
|
137
|
+
Yaparc::Identifier :: Parser for identifier
|
|
138
|
+
Yaparc::Natural :: Parser for natural number
|
|
139
|
+
Yaparc::Symbol :: Parser for symbol
|
|
133
140
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
* Symbol
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
== Regex parser
|
|
141
|
+
=== Regex parser
|
|
140
142
|
|
|
141
143
|
parser = Regex.new(/\A[0-9]+/)
|
|
142
144
|
result = parser.parse("1234ab")
|
|
@@ -148,10 +150,10 @@ The ManyOne requires at least one successfull application of parser.
|
|
|
148
150
|
result = parser.parse("1234:ab")
|
|
149
151
|
assert_equal ["ab", "1234"], result.value
|
|
150
152
|
|
|
153
|
+
=== Define your own parser
|
|
151
154
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
In order to construct parsers, you make parser class to be inherited from Yaparc::AbstractParser class.
|
|
155
|
+
In order to construct parsers, you make parser class to be inherited from
|
|
156
|
+
Yaparc::AbstractParser class.
|
|
155
157
|
|
|
156
158
|
class Identifier < Yaparc::AbstractParser
|
|
157
159
|
def initialize
|
|
@@ -161,36 +163,54 @@ In order to construct parsers, you make parser class to be inherited from Yaparc
|
|
|
161
163
|
end
|
|
162
164
|
end
|
|
163
165
|
|
|
164
|
-
If you want to nest the same parser class in the parser definition, you have
|
|
165
|
-
In the following example, note that Expr class is
|
|
166
|
+
If you want to nest the same parser class in the parser definition, you have
|
|
167
|
+
to choose this way. In the following example, note that +Expr+ class is
|
|
168
|
+
instantiated inside <tt>Expr#initialize</tt> method.
|
|
166
169
|
|
|
167
170
|
class Expr < Yaparc::AbstractParser
|
|
168
171
|
def initialize
|
|
169
172
|
@parser = lambda do
|
|
170
173
|
Yaparc::Alt.new(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
174
|
+
Yaparc::Seq.new(Term.new,
|
|
175
|
+
Yaparc::Symbol.new('+'),
|
|
176
|
+
Expr.new) do |term, _, expr|
|
|
177
|
+
['+', term, expr]
|
|
178
|
+
end,
|
|
179
|
+
Term.new
|
|
180
|
+
)
|
|
178
181
|
end
|
|
179
182
|
end
|
|
183
|
+
end
|
|
180
184
|
|
|
181
|
-
Constructing your parsers, it should be noted that left-recursion leads to
|
|
185
|
+
Constructing your parsers, it should be noted that left-recursion leads to
|
|
186
|
+
non-termination of the parser.
|
|
182
187
|
|
|
183
|
-
|
|
188
|
+
=== Avoiding left-recursion
|
|
184
189
|
|
|
185
190
|
A ::= A B | C
|
|
186
191
|
|
|
187
|
-
|
|
192
|
+
is equivalent to
|
|
188
193
|
|
|
189
194
|
A ::= C B*
|
|
190
195
|
|
|
196
|
+
=== Tokenization
|
|
197
|
+
|
|
198
|
+
When you want to tokenize input stream, use Yaparc::Tokenize class.
|
|
199
|
+
|
|
200
|
+
== About this project
|
|
201
|
+
|
|
202
|
+
RubyGems.org :: https://rubygems.org/gems/yaparc
|
|
203
|
+
RubyForge (archived) :: https://web.archive.org/web/20140515235842/http://rubyforge.org/projects/yaparc/
|
|
204
|
+
|
|
205
|
+
== Development
|
|
191
206
|
|
|
192
|
-
|
|
207
|
+
After checking out the repo, run <tt>bin/setup</tt> to install dependencies.
|
|
208
|
+
Then, run <tt>rake test</tt> to run the tests.
|
|
209
|
+
You can also run <tt>bin/console</tt> for an interactive prompt that will allow you to experiment.
|
|
193
210
|
|
|
194
|
-
|
|
211
|
+
To install this gem onto your local machine, run <tt>bundle exec rake install</tt>.
|
|
212
|
+
To release a new version, update the version number in the library file, and then run <tt>bundle exec rake release</tt>, which will create a git tag for the version, push git commits and the created tag, and push the <tt>.gem</tt> file to [rubygems.org](https://rubygems.org).
|
|
195
213
|
|
|
214
|
+
== Contributing
|
|
196
215
|
|
|
216
|
+
Bug reports and pull requests are welcome.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rake/testtask'
|
|
5
|
+
require "net/http"
|
|
6
|
+
|
|
7
|
+
Rake::TestTask.new(:test) do |t|
|
|
8
|
+
t.libs << 'test'
|
|
9
|
+
t.libs << 'lib'
|
|
10
|
+
t.test_files = FileList['test/**/*_test.rb']
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require 'rubocop/rake_task'
|
|
14
|
+
|
|
15
|
+
RuboCop::RakeTask.new
|
|
16
|
+
|
|
17
|
+
task default: %i[test rubocop]
|
|
18
|
+
|
|
19
|
+
desc 'Generate signatures'
|
|
20
|
+
task :gensig do
|
|
21
|
+
sh 'typeprof', '-o', 'sig/yaparc.gen.rbs', 'sig/yaparc.rbs', *Dir['lib/**/*.rb']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
file "test/abc.html" do |t|
|
|
25
|
+
doc = Net::HTTP.get("web.archive.org", "/web/20120814155205/http://www.norbeck.nu:80/abc/bnf/abc20bnf.htm")
|
|
26
|
+
File.write(t.name, doc)
|
|
27
|
+
end
|
data/TODO
ADDED
data/lib/yaparc/alt.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
class Alt
|
|
5
|
+
include Parsable
|
|
6
|
+
|
|
7
|
+
def initialize(*parsers)
|
|
8
|
+
@parser = lambda do |input|
|
|
9
|
+
final_result = Fail.new(input:)
|
|
10
|
+
parsers.each do |parser|
|
|
11
|
+
case result = parser.parse(input)
|
|
12
|
+
in Fail
|
|
13
|
+
next
|
|
14
|
+
in OK
|
|
15
|
+
break final_result = result
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
final_result
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/yaparc/apply.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
class Apply
|
|
5
|
+
include Parsable
|
|
6
|
+
|
|
7
|
+
def initialize(parser)
|
|
8
|
+
@parser = lambda do |input|
|
|
9
|
+
result = parser.parse(input)
|
|
10
|
+
if result.instance_of?(OK)
|
|
11
|
+
Succeed.new(yield(result.value)).parse(result.input)
|
|
12
|
+
else
|
|
13
|
+
FailParser.new.parse(input)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/yaparc/char.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
class Char
|
|
5
|
+
include Parsable
|
|
6
|
+
|
|
7
|
+
def initialize(char, case_sensitive = true)
|
|
8
|
+
equal_char = if case_sensitive
|
|
9
|
+
->(i) { i == char }
|
|
10
|
+
else # in case of case-insentive
|
|
11
|
+
->(i) { i.casecmp(char) == 0 }
|
|
12
|
+
end
|
|
13
|
+
@parser = proc { Satisfy.new(equal_char) }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/yaparc/cr.rb
ADDED
data/lib/yaparc/digit.rb
ADDED
data/lib/yaparc/ident.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
class Ident
|
|
5
|
+
include Parsable
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@parser = proc do
|
|
9
|
+
Seq.new(
|
|
10
|
+
Satisfy.new(IS_LOWER),
|
|
11
|
+
Many.new(Satisfy.new(IS_ALPHANUM), '')
|
|
12
|
+
) do |head, tail|
|
|
13
|
+
head + tail
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
# Refer to http://www.cs.nott.ac.uk/~gmh/monparsing.pdf, p.23
|
|
5
|
+
class Identifier
|
|
6
|
+
include Yaparc::Parsable
|
|
7
|
+
|
|
8
|
+
IDENTIFIER_REGEX = /\A[a-zA-Z_]+[a-zA-Z0-9_]*/
|
|
9
|
+
|
|
10
|
+
def initialize(regex: nil, exclude: nil)
|
|
11
|
+
identifier_regex = ::Yaparc::Regex.new(regex || IDENTIFIER_REGEX)
|
|
12
|
+
|
|
13
|
+
tokenizer = Tokenize.new(identifier_regex)
|
|
14
|
+
|
|
15
|
+
unless exclude
|
|
16
|
+
@parser = proc { tokenizer }
|
|
17
|
+
return
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@parser = lambda do |input|
|
|
21
|
+
keyword_parsers = exclude.map { |keyword| Yaparc::String.new(keyword) }
|
|
22
|
+
|
|
23
|
+
case result = Yaparc::Alt.new(*keyword_parsers).parse(input)
|
|
24
|
+
when Yaparc::OK
|
|
25
|
+
Yaparc::FailParser.new
|
|
26
|
+
else # Fail or Error
|
|
27
|
+
tokenizer
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/yaparc/item.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
class Item
|
|
5
|
+
include Parsable
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@parser = lambda do |input|
|
|
9
|
+
if input.nil? || input.empty?
|
|
10
|
+
Fail.new(input:)
|
|
11
|
+
else
|
|
12
|
+
OK.new(value: input[0], input: input[1..])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/yaparc/many.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
# permits zero or more applications of parser.
|
|
5
|
+
class Many
|
|
6
|
+
include Parsable
|
|
7
|
+
|
|
8
|
+
def initialize(parser, identity = [])
|
|
9
|
+
@parser = proc {
|
|
10
|
+
Alt.new(ManyOne.new(parser, identity), Succeed.new(identity))
|
|
11
|
+
}
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require_relative 'parsable'
|
|
2
|
+
|
|
3
|
+
module Yaparc
|
|
4
|
+
# requires at least one successfull application of parser.
|
|
5
|
+
class ManyOne
|
|
6
|
+
include Parsable
|
|
7
|
+
|
|
8
|
+
def initialize(parser, identity = [])
|
|
9
|
+
@parser = lambda do |_input|
|
|
10
|
+
Seq.new(parser, Many.new(parser, identity)) do |head, tail|
|
|
11
|
+
case head
|
|
12
|
+
when ::String, ::Array, ::Integer
|
|
13
|
+
head + tail
|
|
14
|
+
when ::Hash
|
|
15
|
+
head.merge(tail)
|
|
16
|
+
else
|
|
17
|
+
if tail.nil?
|
|
18
|
+
head
|
|
19
|
+
else
|
|
20
|
+
[head] + tail
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/yaparc/nat.rb
ADDED