farseer 0.5.0 → 0.7.0

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: faf7eb2a08edee2ef9fac3c334377895fdec31998d3f4de95f97d87c6cdc8d25
4
- data.tar.gz: af09bea3a95f554886f66ef09034a0723c7384d57a924534a94da1166ea8d2fc
3
+ metadata.gz: 22cbc0c49fc2a306b2e0e7291dd58e09047bd2eef4b679d2be9f9e307c6db2e1
4
+ data.tar.gz: a3a1a49b2748d129931af363e3a4bcbb9fdbd174956de07a4de0daceb0cc07cb
5
5
  SHA512:
6
- metadata.gz: 9da67d2aeab63fc0d89e43d9034ebc9f3c4abe5e79736d2508231907ed1acaff01cb6e7cb0e3337f0c06540977a97c07d0badd1e632e8aaf474c07a42fe044f2
7
- data.tar.gz: a27eb0388cf156ee964a90788de733bd9ad923ef1abbde9a7121812ffd30021c15d806ea0a108f9772ed3af3e4a06c8e2f699b4412afa383dfab297ff98989f1
6
+ metadata.gz: 8b3bc436e67fcd46f61964cb6e3e70c7f3a8c374a1712680f4a91901daaf9ae071c79428ac40da19038619e8a05556cbbfd0167d43b5841020b082d730f909a6
7
+ data.tar.gz: 2303e7849b72c10e9353ff9faf362c3d8e0113f24247dbd95104ea45d2c5877e96bcf2444d402853909f14590f4a3c8295f813f99ebc23e1c4bbccbb33c11ae8
data/CHANGELOG.md ADDED
@@ -0,0 +1,103 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.7.0] - 2024-06-04
11
+ ### Added
12
+ - `Farseer::And` to run a sequence of parsers that must all succeed.
13
+ - `Farseer::Or` to try multiple parsers until one works.
14
+ - `Farseer::Word` to parse a keyword at the beginning of a string.
15
+ - `Farseer::Regexp` to parse a token using `regexp`.
16
+ - `mutant` development dependency for mutation testing.
17
+ - Achieve `100%` mutation test coverage.
18
+ - `byebug` development dependency for debugging.
19
+
20
+ ### Removed
21
+ - All helper methods of `Farseer`.
22
+
23
+ ### Changed
24
+ - Update development dependencies.
25
+
26
+ ## [0.6.0] - 2024-06-03
27
+ ### Added
28
+ - `Farseer::Opt` to parse `0` to `1` times the wrapped parser. (`?`)
29
+ - `Farseer::Any` to parse `0` to multiple times the wrapped parser. (`*`)
30
+ - `Farseer::Many` to parse `1` to multiple times the wrapped parser. (`+`)
31
+ - A couple of instances of `Farseer::Chars` as constants:
32
+ - `Farseer::Chars::DIGITS` to parse digits from `0` to `9`.
33
+ - `Farseer::Chars::BASIC_MATH_OP` to parse symbols `+`, `-`, `*`, `/`.
34
+ - Enabled more `Lint` `rubocop` rules.
35
+ - Enabled `Performance` `rubocop` rules.
36
+
37
+ ### Changed
38
+ - Updated development dependencies
39
+
40
+ ## [0.5.0] - 2024-06-03
41
+ ### Added
42
+ - `Farseer::Char` as a single character parser.
43
+ - `Farseer::Chars` as a single character from set parser.
44
+ - Multiple instances of `Farseer::Char` as constants:
45
+ - `Farseer::Char::L_PARENS` for `(`.
46
+ - `Farseer::Char::R_PARENS` for `)`.
47
+ - `Farseer::Char::PLUS` for `+`.
48
+ - `Farseer::Char::MINUS` for `-`.
49
+ - `Farseer::Char::STAR` for `*`.
50
+ - `Farseer::Char::SLASH` for `/`.
51
+ - Enabled `Lint` `rubocop` rules.
52
+ - Enabled a couple more `Layout` `rubocop` rules.
53
+
54
+ ### Changed
55
+ - Update `muina` version requirement to `~> 0.5`
56
+
57
+ ## [0.4.0] - 2024-06-03
58
+ ### Added
59
+ - `Farseer.any_char_parser` to parse a single character from a given set.
60
+ - `irb` development dependency.
61
+ - `.gitignore.local` symlink to `.git/info/exclude`.
62
+
63
+ ### Changed
64
+ - Stop using `module_function` and change methods into singleton methods.
65
+ - Update `bundler` version.
66
+
67
+ ## [0.3.0] - 2024-06-02
68
+ ### Added
69
+ - `Farseer#ws_parser` to parse all leading whitespace.
70
+ - Multiple development dependencies:
71
+ - `flay`, `flog`, `guard`, `guard-rspec`, `guard-rubocop`, `lefthook`, and
72
+ `rubocop-performance` with corresponding `binstubs`.
73
+ - `Guardfile` with `rspec` and `rubocop` guards.
74
+ - `.lefthook.yml` including `pre-commit` and `pre-push` hooks, and `audit` and
75
+ `full_audit` tasks.
76
+
77
+ ### Changed
78
+ - Bump `muina` required version to `~> 0.4`.
79
+ - Enabled `Lint` `rubocop` department.
80
+
81
+
82
+ ## [0.2.0] - 2024-06-02
83
+ ### Added
84
+ - `Farseer::Result` to hold the result of succesful parses.
85
+ - `Farseer#char_parser` to parse a single specific character.
86
+ - `muina` as a dependency.
87
+ - `bin/console` to jump into `irb` with the project loaded.
88
+
89
+
90
+ ## [0.1.0] - 2024-06-02
91
+ ### Added
92
+ - Initial gem relase.
93
+ - Set up code quality dependencies:
94
+ - `rake`: for running common tasks.
95
+ - `rubocop`: for linting.
96
+ - `rspec`: for testing.
97
+ - `simplecov`: for code coverage.
98
+ - License the project with `The Unlicense`.
99
+ - `Rakefile` with `gem`, `rubocop`, and `rspec` tasks.
100
+ - `SECURITY.md` to keep track of maintained versions.
101
+ - `Farseer::VERSION`: Keep the gem version in a constant.
102
+ - `.ruby-version` for rbenv, with version `3.2.2`
103
+ - This `CHANGELOG.md`
data/SECURITY.md ADDED
@@ -0,0 +1,14 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Currently supported version are:
6
+
7
+ | Version | Supported |
8
+ | ------- | ------------------ |
9
+ | 0.6.0 | :white_check_mark: |
10
+ | < 0.6.0 | :x: |
11
+
12
+ ## Reporting a Vulnerability
13
+
14
+ If you find any vulnerability please open an issue.
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farseer
4
+ class And
5
+ def initialize(*parsers)
6
+ @parsers = parsers.flatten
7
+ freeze
8
+ end
9
+
10
+ def parse(input)
11
+ return Maybe.none if @parsers.empty?
12
+
13
+ initial = Maybe.return(Result.new('', input))
14
+
15
+ @parsers.reduce(initial) do |maybe_acc, parser|
16
+ bind_accumulator(maybe_acc, parser)
17
+ end
18
+ end
19
+
20
+ def bind_accumulator(maybe_acc, parser)
21
+ maybe_acc.bind do |acc_result|
22
+ parse_with_rest(parser, acc_result)
23
+ end
24
+ end
25
+
26
+ def parse_with_rest(parser, acc_result)
27
+ parser.parse(acc_result.rest).bind do |result|
28
+ combine_results(acc_result, result)
29
+ end
30
+ end
31
+
32
+ def combine_results(acc_result, result)
33
+ combined_tokens = acc_result.token + result.token
34
+ Maybe.return(Result.new(combined_tokens, result.rest))
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farseer
4
+ class Any
5
+ def initialize(parser)
6
+ @parser = parser
7
+ freeze
8
+ end
9
+
10
+ def parse(input)
11
+ helper(input, '')
12
+ end
13
+
14
+ def helper(input, tokens)
15
+ @parser.parse(input)
16
+ .bind { |r| helper(r.rest, tokens + r.token) }
17
+ .map_none { Result.new(tokens, input) }
18
+ end
19
+ end
20
+ end
data/lib/farseer/chars.rb CHANGED
@@ -2,16 +2,18 @@
2
2
 
3
3
  module Farseer
4
4
  class Chars
5
- def initialize(chars)
6
- @chars = chars
5
+ def initialize(*chars)
6
+ @chars = chars.flatten
7
7
  freeze
8
8
  end
9
9
 
10
+ DIGITS = new(('0'..'9').to_a)
11
+ BASIC_MATH_OP = new(['+', '-', '*', '/'])
12
+
10
13
  def parse(input)
11
- if @chars.any? { |char| char == input[0] }
12
- Maybe.return(Result.new(input[0], input[1..]))
13
- else
14
- Maybe.none
14
+ case input[0]
15
+ when *@chars then Maybe.return(Result.new(input[0], input[1..]))
16
+ else Maybe.none
15
17
  end
16
18
  end
17
19
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farseer
4
+ class Many
5
+ def initialize(parser)
6
+ @parser = parser
7
+ freeze
8
+ end
9
+
10
+ def parse(input)
11
+ @parser.parse(input)
12
+ .bind { |r| helper(r.rest, r.token) }
13
+ end
14
+
15
+ def helper(input, tokens)
16
+ parse(input)
17
+ .bind { |r| helper(r.rest, tokens + r.token) }
18
+ .map_none { Result.new(tokens, input) }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farseer
4
+ class Opt
5
+ def initialize(parser)
6
+ @parser = parser
7
+ freeze
8
+ end
9
+
10
+ def parse(input)
11
+ @parser
12
+ .parse(input)
13
+ .map_none { Result.new('', input) }
14
+ end
15
+ end
16
+ end
data/lib/farseer/or.rb ADDED
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farseer
4
+ class Or
5
+ def initialize(*parsers)
6
+ @parsers = parsers.flatten
7
+ freeze
8
+ end
9
+
10
+ def parse(input)
11
+ case @parsers.length
12
+ when 0 then Maybe.none
13
+ when 1 then @parsers.first.parse(input)
14
+ else parse_helper(input)
15
+ end
16
+ end
17
+
18
+ def parse_helper(input)
19
+ @parsers.reduce do |acc, parser|
20
+ acc.parse(input).bind_none { parser.parse(input) }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farseer
4
+ class Regexp
5
+ WS_REGEXP = /^(?'token'\s*)(?'rest'.*)$/
6
+ RegexpError = Class.new(ArgumentError)
7
+
8
+ def initialize(regexp)
9
+ raise RegexpError unless regexp.names == ['token', 'rest']
10
+
11
+ @regexp = regexp
12
+ freeze
13
+ end
14
+
15
+ WS = new(WS_REGEXP)
16
+
17
+ def parse(input)
18
+ match = input.match(@regexp)
19
+
20
+ Maybe.return(Result.new(match[:token], match[:rest]))
21
+ end
22
+ end
23
+ end
@@ -11,8 +11,8 @@ module Farseer
11
11
 
12
12
  def eql?(other)
13
13
  self.class.eql?(other.class) and
14
- self.token.eql?(other.token) and
15
- self.rest.eql?(other.rest)
14
+ token.eql?(other.token) and
15
+ rest.eql?(other.rest)
16
16
  end
17
17
  alias == eql?
18
18
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Farseer
4
- VERSION = '0.5.0'
4
+ VERSION = '0.7.0'
5
5
  public_constant :VERSION
6
6
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farseer
4
+ class Word
5
+ def initialize(word)
6
+ @word = word
7
+ freeze
8
+ end
9
+
10
+ def parse(input)
11
+ case
12
+ when input.start_with?(@word) then Maybe.return(Result.new(@word, input[@word.length..]))
13
+ else Maybe.none
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/farseer.rb CHANGED
@@ -6,26 +6,7 @@ loader = Zeitwerk::Loader::for_gem
6
6
  loader.setup
7
7
 
8
8
  module Farseer
9
- WS_REGEX = /^(\s*)(.*)$/
10
9
  Maybe = Muina::Maybe
11
-
12
- def self.any_char_parser
13
- ->(chars, input) { Chars.new(chars).parse(input) }
14
- .curry
15
- end
16
-
17
- def self.char_parser
18
- ->(char, input) { Char.new(char).parse(input) }
19
- .curry
20
- end
21
-
22
- def self.ws_parser
23
- ->(input) {
24
- match = input.match(WS_REGEX)
25
-
26
- Maybe.return(Result.new(match[1], match[2]))
27
- }
28
- end
29
10
  end
30
11
 
31
12
  loader.eager_load
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: farseer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - vaporyhumo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-03 00:00:00.000000000 Z
11
+ date: 2024-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: muina
@@ -45,13 +45,22 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - CHANGELOG.md
48
49
  - LICENSE
49
50
  - README.md
51
+ - SECURITY.md
50
52
  - lib/farseer.rb
53
+ - lib/farseer/and.rb
54
+ - lib/farseer/any.rb
51
55
  - lib/farseer/char.rb
52
56
  - lib/farseer/chars.rb
57
+ - lib/farseer/many.rb
58
+ - lib/farseer/opt.rb
59
+ - lib/farseer/or.rb
60
+ - lib/farseer/regexp.rb
53
61
  - lib/farseer/result.rb
54
62
  - lib/farseer/version.rb
63
+ - lib/farseer/word.rb
55
64
  homepage: https://github.com/vaporyhumo/farseer
56
65
  licenses:
57
66
  - Unlicense