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 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: {}