fupeg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e5cd2184b66fd7961603e8e21fbdf82514619001cff01cbe230f218c6f2737b1
4
+ data.tar.gz: 74af0b350f4f966c7c7da490609f18c982c4aed3541a9e279f5eff318c4f698f
5
+ SHA512:
6
+ metadata.gz: ac6a5f6588125e13597104c4c9969fbcf85825b73c76d677ea525eae81791111658733bc366a0b129af86bd85d017bec36b2b6a5c48d2677a574b63334b32bb7
7
+ data.tar.gz: 8988b71fe64ea7202cc08c996a58ab0c461df6bdba19e1cf7f32315fa039d3412048235e752a7ae4895847f1215b2dd7716255c8b7c03782154926bfb43fd874
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ## [0.1.0] - 2023-08-11
2
+
3
+ - Initial release
4
+ - Simplest rule definition in Ruby code without magic
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in fupeg.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ gem "rubocop", "~> 1.21"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Yura Sokolov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Fupeg
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/fupeg`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Install the gem and add to the application's Gemfile by executing:
10
+
11
+ $ bundle add fupeg
12
+
13
+ If bundler is not being used to manage dependencies, install the gem by executing:
14
+
15
+ $ gem install fupeg
16
+
17
+ ## Usage
18
+
19
+ TODO: Write usage instructions here
20
+
21
+ ## Development
22
+
23
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
24
+
25
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
26
+
27
+ ## Contributing
28
+
29
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/fupeg.
30
+
31
+ ## License
32
+
33
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "strscan"
4
+
5
+ module FuPeg
6
+ class Parser
7
+ def initialize(str, pos = 0)
8
+ reset!(str, pos)
9
+ end
10
+
11
+ def reset!(str = nil, pos = nil)
12
+ if str
13
+ @str = str.dup
14
+ @str_size = str.size
15
+ init_line_ends
16
+ @scan = StringScanner.new(str)
17
+ end
18
+ if pos
19
+ @scan.pos = pos
20
+ end
21
+ @failed = nil
22
+ @cut = CutPoint.new
23
+ end
24
+
25
+ attr_reader :failed
26
+
27
+ def bytepos
28
+ @scan.pos
29
+ end
30
+
31
+ def charpos
32
+ @str_size - @str.byteslice(@scan.pos..).size
33
+ end
34
+
35
+ Fail = Struct.new(:stack, :pos, :bytepos)
36
+
37
+ def fail!(skip = 2)
38
+ if !@failed || bytepos > @failed.bytepos
39
+ stack = caller_locations(skip)
40
+ stack.delete_if do |loc|
41
+ if loc.path == __FILE__
42
+ loc.label =~ /\b(_bt|each|block)\b/
43
+ end
44
+ end
45
+ pos = position_for_charpos(charpos)
46
+ @failed = Fail.new(stack, pos, bytepos)
47
+ end
48
+ nil
49
+ end
50
+
51
+ def report_failed(out)
52
+ pos = @failed.pos
53
+ out << "Failed at #{pos.lineno}:#{pos.colno} :\n"
54
+ out << pos.line + "\n"
55
+ out << (" " * (pos.colno - 1) + "^\n")
56
+ out << "Call stack:\n"
57
+ @failed.stack.each do |loc|
58
+ out << "#{loc.path}:#{loc.lineno} in #{loc.label}\n"
59
+ end
60
+ out
61
+ end
62
+
63
+ def dot
64
+ @scan.scan(/./m) || fail!
65
+ end
66
+
67
+ begin
68
+ StringScanner.new("x").skip("x")
69
+ def lit(reg_or_str)
70
+ @scan.scan(reg_or_str) || fail!
71
+ end
72
+ rescue
73
+ def lit(reg_or_str)
74
+ if String === reg_or_str
75
+ @__match_lit_cache ||= Hash.new { |h, s| h[s] = Regexp.new(Regexp.escape(s)) }
76
+ reg_or_str = @__match_lit_cache[reg_or_str]
77
+ end
78
+ @scan.scan(reg_or_str) || fail!
79
+ end
80
+ end
81
+
82
+ def seq(*args, &block)
83
+ _bt(&block)
84
+ end
85
+
86
+ def opt(&block)
87
+ _rewind(nil, @failed, _bt(&block) || true)
88
+ end
89
+
90
+ def rep(range = 0.., &block)
91
+ range = range..range if Integer === range
92
+ range = 0..range.max if range.begin.nil?
93
+ unless Integer === range.min && (range.end.nil? || Integer === range.max)
94
+ raise "Range malformed #{range}"
95
+ end
96
+ _bt do
97
+ max = range.end && range.max
98
+ ar = []
99
+ (1..max).each do
100
+ res = _bt(&block)
101
+ break unless res
102
+ ar << res
103
+ end
104
+ (ar.size >= range.min) ? ar : fail!
105
+ end
106
+ end
107
+
108
+ def text(&block)
109
+ pos = @scan.pos
110
+ _bt(&block) && @str.byteslice(pos, @scan.pos - pos)
111
+ end
112
+
113
+ def will?(&block)
114
+ _rewind(@scan.pos, false, _bt(&block))
115
+ end
116
+
117
+ def wont!(&block)
118
+ _rewind(@scan.pos, @failed, !_bt(&block)) || fail!
119
+ end
120
+
121
+ # cut point handling
122
+ # cut do
123
+ # seq { lit("{") && cut! && lit("}") } ||
124
+ # !cut? && seq { lit("[") && cut! && lit("]") } ||
125
+ # !cut? && dot
126
+ # end
127
+ class CutPoint
128
+ attr_accessor :next
129
+
130
+ def initialize
131
+ @cut = false
132
+ @next = nil
133
+ end
134
+
135
+ def cut!
136
+ @next&.cut!
137
+ @cut = true
138
+ end
139
+
140
+ def cut?
141
+ @cut
142
+ end
143
+ end
144
+
145
+ # for use with cut! and cut?
146
+ def cut
147
+ prev_cut = @cut
148
+ @cut = CutPoint.new
149
+ prev_cut.next = @cut
150
+ yield @cut
151
+ ensure
152
+ prev_cut.next = nil
153
+ @cut = prev_cut
154
+ end
155
+
156
+ def cut!
157
+ @cut.cut!
158
+ end
159
+
160
+ def cut?
161
+ @cut.cut?
162
+ end
163
+
164
+ # Position handling for failures
165
+
166
+ Position = Struct.new(:lineno, :colno, :line, :charpos)
167
+
168
+ private
169
+
170
+ def init_line_ends
171
+ @line_ends = [-1]
172
+ pos = 0
173
+ while (pos = @str.index("\n", pos))
174
+ @line_ends << @pos
175
+ pos += 1
176
+ end
177
+ @line_ends << @str.size
178
+ end
179
+
180
+ public
181
+
182
+ def position_for_charpos(charpos)
183
+ lineno = @line_ends.bsearch_index { |x| x >= charpos }
184
+ case lineno
185
+ when nil
186
+ raise "Position #{charpos} is larger than string size #{@str.size}"
187
+ else
188
+ prev_end = @line_ends[lineno - 1]
189
+ line_start = prev_end + 1
190
+ column = charpos - prev_end
191
+ end
192
+ line = @str[line_start..@line_ends[lineno]]
193
+ Position.new(lineno, column, line, charpos)
194
+ end
195
+
196
+ # helper methods
197
+
198
+ private
199
+
200
+ def _bt
201
+ pos = @scan.pos
202
+ res = yield
203
+ if res
204
+ @failed = nil if @failed && @failed.bytepos <= @scan.pos
205
+ res
206
+ else
207
+ @scan.pos = pos
208
+ nil
209
+ end
210
+ rescue
211
+ @scan.pos = pos
212
+ raise
213
+ end
214
+
215
+ def _rewind(pos, failed, val)
216
+ @scan.pos = pos if pos
217
+ @failed = failed if failed != false
218
+ val
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FuPeg
4
+ VERSION = "0.1.0"
5
+ end
data/lib/fupeg.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "fupeg/version"
4
+ require_relative "fupeg/parser"
5
+
6
+ module FuPeg
7
+ VERSION = "0.1.0"
8
+
9
+ class Error < StandardError; end
10
+ # Your code goes here...
11
+ end
data/sig/fupeg.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Fupeg
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fupeg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yura Sokolov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-08-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: "\n Simple backtracing parser, using ruby logical operators for primitive
14
+ sequence/choice\n and slim wrappers for other PEG style operators and backtrace.\n
15
+ \ "
16
+ email:
17
+ - funny.falcon@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".rspec"
23
+ - ".rubocop.yml"
24
+ - CHANGELOG.md
25
+ - Gemfile
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - lib/fupeg.rb
30
+ - lib/fupeg/parser.rb
31
+ - lib/fupeg/version.rb
32
+ - sig/fupeg.rbs
33
+ homepage: https://github.com/funny-falcon/fupeg
34
+ licenses:
35
+ - MIT
36
+ metadata:
37
+ homepage_uri: https://github.com/funny-falcon/fupeg
38
+ source_code_uri: https://github.com/funny-falcon/fupeg
39
+ changelog_uri: https://github.com/funny-falcon/fupeg/blob/master/CHANGELOG.md
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 2.6.0
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.3.15
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: Over simplificated PEG/Parser Combinator
59
+ test_files: []