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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fd34fe9a8f6cc7dbcd31983b498f89d08b5a8cbb2ead84f279bfa1fdc97af2e
4
- data.tar.gz: 8ec2a0361e0a254e484648260d6835971a3c210b454bd30be5dc060e8a77518b
3
+ metadata.gz: e5b92019011d80442cfe66f4b3a841a31bba54547efd479a2d19b1f7e687adef
4
+ data.tar.gz: 75cb9467e13dc72e773bebe345b68b05d431bdbfc6671c7bc215bd063a86cd6c
5
5
  SHA512:
6
- metadata.gz: dbe9a870df4681c29c1fc65b173e831a31efbf15af88ebd3fa2b6003c8c7ac4321eb509b2b737f58051919669465a063c044e5cde187fb18c0de8af506d4a048
7
- data.tar.gz: 28f2eb73223629254c8329799d90abf012d18c67c1ab5ff9627a1b2cf55fd75a92e98b402ac6438ea398fc88f61f328429727066446ff239ffdd5ed7d92cc042
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(parser, %w[--start=42 --end=44 --inc=2], ast: {start: 42, end: 44, inc: 2}, rest: [])
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
- ## Author
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
@@ -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)
@@ -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
@@ -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) = L43Peg::Parsers::ArgsParser.new(args, name:)
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) = L43Peg::Parsers::TokensParser.new(map, name:, &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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43Peg
4
+ class Stop
5
+ extend L43::OpenObject
6
+ attributes
7
+ # A placeholder to halt many
8
+ end
9
+ end
10
+ # SPDX-License-Identifier: Apache-2.0
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.4"
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
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-22 00:00:00.000000000 Z
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://gitlab.com/l43-gems/l43_peg
49
+ homepage: https://codeberg.org/lab419/l43_peg
49
50
  licenses:
50
51
  - AGPL-3.0-or-later
51
52
  metadata: {}