l43_peg 0.1.4 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/l43_peg.svg)](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: {}
|