l43_peg 0.1.4 → 0.1.6
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/README.md +73 -2
- data/lib/l43_peg/combinators/many.rb +6 -1
- data/lib/l43_peg/combinators.rb +2 -2
- data/lib/l43_peg/helper.rb +2 -2
- data/lib/l43_peg/parsers/tokens_parser.rb +5 -3
- data/lib/l43_peg/parsers.rb +4 -2
- data/lib/l43_peg/stop.rb +10 -0
- data/lib/l43_peg.rb +23 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5b92019011d80442cfe66f4b3a841a31bba54547efd479a2d19b1f7e687adef
|
4
|
+
data.tar.gz: 75cb9467e13dc72e773bebe345b68b05d431bdbfc6671c7bc215bd063a86cd6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab3a4841408511554c96725a7659d7b5928336d195323e06dd8c707f247d48f5e2b7d1831768e018de7fdcfbd3d2dfba0aa791d10b1ab422fb08f8b225797066
|
7
|
+
data.tar.gz: be59e8841fcc4e9f22194555fa40c8573805a589f119a728a216e256d729fcdd4ce4abaac76df0547a109415b83208e333fc209ef00bb9e46fcd03ec3dafbd85
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# L43Peg
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/l43_peg)
|
4
|
+
|
3
5
|
## A Parse Expression Grammar library for Ruby
|
4
6
|
|
5
7
|
### This Version (v0.1.x) is Alpha Quality (many PEG features are missing, like recursion and even alternatives.
|
@@ -68,11 +70,80 @@ When we map the parser
|
|
68
70
|
Then we can convert the string valus
|
69
71
|
|
70
72
|
```ruby
|
71
|
-
assert_parse_success(
|
73
|
+
assert_parse_success(int_arg_parser, %w[--start=42 --end=44 --inc=2], ast: {start: 42, end: 44, inc: 2}, rest: [])
|
74
|
+
```
|
75
|
+
|
76
|
+
#### Context: Knowing When To Stop
|
77
|
+
|
78
|
+
An argument parser that respects itself provides a means to _end_ argument parsing even if more matches follow.
|
79
|
+
An exmaple for that is the posix argument `--`
|
80
|
+
|
81
|
+
We can use whatever we want in `args_parser`, here is a variation:
|
82
|
+
|
83
|
+
Given the specification
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
let :args do
|
87
|
+
{
|
88
|
+
width: "w:(\\d+)",
|
89
|
+
height: "h:(\\d+)",
|
90
|
+
__stop: "(::)"
|
91
|
+
}
|
92
|
+
end
|
93
|
+
let(:wh_parser) {args_parser(args, stop: :__stop, &:to_i)}
|
94
|
+
```
|
95
|
+
|
96
|
+
Then parsing the following input
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
input = %w[h:42 w:73 :: w:74]
|
100
|
+
ast = {height: 42, width: 73}
|
101
|
+
assert_parse_success(wh_parser, input, ast:, rest: %w[w:74])
|
102
|
+
```
|
103
|
+
|
104
|
+
### Context: User Interface
|
105
|
+
|
106
|
+
#### Context: Exposing the args_parser
|
107
|
+
|
108
|
+
Above we have seen that we had to include an internal module so to get access to the `args_parser`.
|
109
|
+
Client code might not want to use these intrusive methods and therefore the parsers are also exposed
|
110
|
+
as module methods
|
111
|
+
|
112
|
+
Given an _exposed_ `args_parser`
|
113
|
+
```ruby
|
114
|
+
let :parser do
|
115
|
+
L43Peg::Parsers.args_parser(
|
116
|
+
{
|
117
|
+
negative: "(-\\d+)",
|
118
|
+
positive: "\\+?(\\d+)"
|
119
|
+
},
|
120
|
+
&:to_i
|
121
|
+
)
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
But we are also not interested in the internal representation of success and failure of parsing which was
|
126
|
+
used in the speculations above. Nor do we want to transform our input into the internal representations
|
127
|
+
as was done above by the helpers. (If you need to see the details of this you can inspect the
|
128
|
+
file [`parser_test.rb` in `spec/support`](spec/support/parser_test.rb))
|
129
|
+
|
130
|
+
Then we can uses the interface of `L43Peg`
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
L43Peg.parse_tokens(parser, %w[43 -44 +45]) => :ok, result
|
134
|
+
expect(result).to eq(positive: [43, 45], negative: -44)
|
135
|
+
```
|
136
|
+
|
137
|
+
And if we get an error the result is as follows
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
parser = L43Peg::Parsers.char_parser('a')
|
141
|
+
L43Peg.parse_string(parser, 'b') => :error, message
|
142
|
+
expect(message).to eq("char \"b\"")
|
72
143
|
```
|
73
144
|
|
74
145
|
|
75
|
-
|
146
|
+
# Author
|
76
147
|
|
77
148
|
Copyright © 2024 Robert Dober
|
78
149
|
robert.dober@gmail.com
|
@@ -24,9 +24,14 @@ module L43Peg
|
|
24
24
|
count += 1
|
25
25
|
in L43Peg::Failure
|
26
26
|
if count < min
|
27
|
-
return fail_parser("many #{name} should match at least #{min} times but did only #{count} times")
|
27
|
+
return fail_parser("many #{name} should match at least #{min} times but did only #{count} times", input:)
|
28
28
|
end
|
29
29
|
return succeed_parser(ast, curr_input, cache: curr_cache)
|
30
|
+
in L43Peg::Stop
|
31
|
+
if count < min
|
32
|
+
return fail_parser("many #{name} should match at least #{min} times but did only #{count} times", input:)
|
33
|
+
end
|
34
|
+
return succeed_parser(ast, curr_input.drop, cache: curr_cache)
|
30
35
|
end
|
31
36
|
end
|
32
37
|
end
|
data/lib/l43_peg/combinators.rb
CHANGED
@@ -13,8 +13,8 @@ module L43Peg
|
|
13
13
|
include L43Peg::Mappers
|
14
14
|
include L43Peg::Parsers
|
15
15
|
|
16
|
-
def args_parser(definitions, name: nil, &block)
|
17
|
-
parser = tokens_parser(definitions, &block)
|
16
|
+
def args_parser(definitions, name: nil, stop: nil, &block)
|
17
|
+
parser = tokens_parser(definitions, stop:, &block)
|
18
18
|
name = name || "args_parser(#{definitions.inspect})"
|
19
19
|
inner = many(parser)
|
20
20
|
map(inner, name:, fn: join_maps)
|
data/lib/l43_peg/helper.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module L43Peg
|
4
4
|
module Helper
|
5
|
-
def fail_parser(reason)
|
6
|
-
L43Peg::Failure.new(reason:)
|
5
|
+
def fail_parser(reason, input: nil)
|
6
|
+
L43Peg::Failure.new(reason:, input:)
|
7
7
|
end
|
8
8
|
def succeed_parser(ast, input, cache: nil)
|
9
9
|
L43Peg::Success.new(ast:, rest: input, cache: cache || input.cache)
|
@@ -6,13 +6,13 @@ module L43Peg
|
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
-
def initialize(map, name: nil, &blk)
|
9
|
+
def initialize(map, name: nil, stop: nil, &blk)
|
10
10
|
map = _check_arg!(map)
|
11
11
|
name = name || "tokens_parser(#{map.inspect})"
|
12
12
|
super(name) do |tokens, cache, _name|
|
13
13
|
case _find_matching(map, tokens)
|
14
14
|
in [token, success]
|
15
|
-
_succeed(tokens:, token:, success:, &blk)
|
15
|
+
_succeed(tokens:, token:, stop:, success:, &blk)
|
16
16
|
else
|
17
17
|
reason = "no token matches (in #{name})"
|
18
18
|
L43Peg::Failure.new(cache:, input: tokens, parsed_by: self, reason:)
|
@@ -47,7 +47,9 @@ module L43Peg
|
|
47
47
|
end.to_h
|
48
48
|
end
|
49
49
|
|
50
|
-
def _succeed(success:, token:, tokens:, &blk)
|
50
|
+
def _succeed(stop:, success:, token:, tokens:, &blk)
|
51
|
+
return L43Peg::Stop.new if token == stop
|
52
|
+
|
51
53
|
result = if blk
|
52
54
|
blk.(success.ast)
|
53
55
|
else
|
data/lib/l43_peg/parsers.rb
CHANGED
@@ -5,14 +5,16 @@ require_subdir {}
|
|
5
5
|
|
6
6
|
module L43Peg
|
7
7
|
module Parsers extend self
|
8
|
-
def args_parser(args, name: nil
|
8
|
+
def args_parser(args, name: nil, stop: nil, &blk) =
|
9
|
+
L43Peg::Combinators.args_parser(args, name:, stop:, &blk)
|
9
10
|
def char_parser(charset = nil) = L43Peg::Parsers::CharParser.new(charset)
|
10
11
|
def end_parser = L43Peg::Parsers::EndParser.instance
|
11
12
|
def failure_parser = L43Peg::Parsers::FailureParser.instance
|
12
13
|
def int_parser = L43Peg::Parsers::IntParser.instance
|
13
14
|
def rgx_parser(rgx, name: nil, **o) = L43Peg::Parsers::RgxParser.new(rgx, name:, **o)
|
14
15
|
def token_parser(spc, name: nil, **o) = L43Peg::Parsers::TokenParser.new(spc, name:, **o)
|
15
|
-
def tokens_parser(map, name: nil, &b) =
|
16
|
+
def tokens_parser(map, name: nil, stop: nil, &b) =
|
17
|
+
L43Peg::Parsers::TokensParser.new(map, name:, stop:, &b)
|
16
18
|
def verb_parser(verb, name: nil) = L43Peg::Parsers::VerbParser.new(verb, name:)
|
17
19
|
end
|
18
20
|
end
|
data/lib/l43_peg/stop.rb
ADDED
data/lib/l43_peg.rb
CHANGED
@@ -4,7 +4,28 @@ require_relative 'l43/require_helper'
|
|
4
4
|
require_relative 'l43/open_object'
|
5
5
|
require_subdir {}
|
6
6
|
|
7
|
-
module L43Peg
|
8
|
-
VERSION = "0.1.
|
7
|
+
module L43Peg extend self
|
8
|
+
VERSION = "0.1.6"
|
9
|
+
|
10
|
+
def parse_string(parser, input, lnb: 1, col: 1, context: {})
|
11
|
+
input = Input.new(input:, col:, lnb:, context:)
|
12
|
+
_parse(parser, input)
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_tokens(parser, tokens, tnb: 1, context: {})
|
16
|
+
tokens = Tokens.new(tokens:, tnb:, context:)
|
17
|
+
_parse(parser, tokens)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def _parse(parser, input)
|
23
|
+
case parser.(input)
|
24
|
+
in Success => success
|
25
|
+
[:ok, success.ast]
|
26
|
+
in Failure => failure
|
27
|
+
[:error, failure.reason]
|
28
|
+
end
|
29
|
+
end
|
9
30
|
end
|
10
31
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: l43_peg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
A (still incomplete) PEG Library
|
@@ -43,9 +43,10 @@ files:
|
|
43
43
|
- lib/l43_peg/parsers/token_parser.rb
|
44
44
|
- lib/l43_peg/parsers/tokens_parser.rb
|
45
45
|
- lib/l43_peg/parsers/verb_parser.rb
|
46
|
+
- lib/l43_peg/stop.rb
|
46
47
|
- lib/l43_peg/success.rb
|
47
48
|
- lib/l43_peg/tokens.rb
|
48
|
-
homepage: https://
|
49
|
+
homepage: https://codeberg.org/lab419/l43_peg
|
49
50
|
licenses:
|
50
51
|
- AGPL-3.0-or-later
|
51
52
|
metadata: {}
|