srl_ruby 0.4.5 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +298 -23
  3. data/CHANGELOG.md +41 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +1 -1
  7. data/Rakefile +3 -0
  8. data/appveyor.yml +14 -12
  9. data/bin/srl2ruby +13 -9
  10. data/bin/srl2ruby_cli_parser.rb +3 -3
  11. data/features/lib/step_definitions/srl_testing_steps.rb +2 -0
  12. data/features/lib/support/env..rb +2 -0
  13. data/lib/regex/abstract_method.rb +2 -0
  14. data/lib/regex/alternation.rb +3 -3
  15. data/lib/regex/anchor.rb +3 -0
  16. data/lib/regex/atomic_expression.rb +2 -0
  17. data/lib/regex/capturing_group.rb +8 -3
  18. data/lib/regex/char_class.rb +4 -2
  19. data/lib/regex/char_range.rb +3 -3
  20. data/lib/regex/char_shorthand.rb +3 -0
  21. data/lib/regex/character.rb +5 -2
  22. data/lib/regex/compound_expression.rb +2 -0
  23. data/lib/regex/concatenation.rb +3 -1
  24. data/lib/regex/expression.rb +6 -1
  25. data/lib/regex/lookaround.rb +3 -1
  26. data/lib/regex/match_option.rb +2 -0
  27. data/lib/regex/monadic_expression.rb +2 -0
  28. data/lib/regex/multiplicity.rb +8 -9
  29. data/lib/regex/non_capturing_group.rb +3 -1
  30. data/lib/regex/polyadic_expression.rb +2 -0
  31. data/lib/regex/quantifiable.rb +3 -1
  32. data/lib/regex/raw_expression.rb +2 -0
  33. data/lib/regex/repetition.rb +2 -0
  34. data/lib/regex/wildcard.rb +2 -5
  35. data/lib/srl_ruby/ast_builder.rb +81 -121
  36. data/lib/srl_ruby/grammar.rb +80 -92
  37. data/lib/srl_ruby/regex_repr.rb +2 -0
  38. data/lib/srl_ruby/tokenizer.rb +10 -4
  39. data/lib/srl_ruby/version.rb +3 -1
  40. data/lib/srl_ruby.rb +2 -0
  41. data/spec/acceptance/srl_test_suite_spec.rb +2 -0
  42. data/spec/acceptance/support/rule_file_ast_builder.rb +2 -0
  43. data/spec/acceptance/support/rule_file_grammar.rb +7 -5
  44. data/spec/acceptance/support/rule_file_nodes.rb +2 -0
  45. data/spec/acceptance/support/rule_file_parser.rb +2 -0
  46. data/spec/acceptance/support/rule_file_tokenizer.rb +10 -3
  47. data/spec/regex/atomic_expression_spec.rb +2 -0
  48. data/spec/regex/character_spec.rb +16 -6
  49. data/spec/regex/match_option_spec.rb +2 -0
  50. data/spec/regex/monadic_expression_spec.rb +2 -0
  51. data/spec/regex/multiplicity_spec.rb +4 -0
  52. data/spec/regex/repetition_spec.rb +2 -0
  53. data/spec/spec_helper.rb +2 -0
  54. data/spec/srl_ruby/srl_ruby_spec.rb +2 -0
  55. data/spec/srl_ruby/tokenizer_spec.rb +2 -0
  56. data/spec/srl_ruby_spec.rb +8 -6
  57. data/srl_ruby.gemspec +6 -4
  58. metadata +13 -14
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Grammar for SRL (Simple Regex Language)
2
4
  require 'rley' # Load the gem
3
5
  module SrlRuby
4
6
  ########################################
5
7
  # SRL grammar
6
- builder = Rley::Syntax::GrammarBuilder.new do
8
+ builder = Rley::grammar_builder do
7
9
  # Separators...
8
10
  add_terminals('LPAREN', 'RPAREN', 'COMMA')
9
11
 
@@ -29,97 +31,83 @@ module SrlRuby
29
31
  add_terminals('LAZY')
30
32
 
31
33
  # Grammar rules...
32
- rule('srl' => 'expression').as 'start_rule'
33
- rule('expression' => %w[pattern flags]).as 'flagged_expr'
34
- rule('expression' => 'pattern').as 'simple_expr'
35
- rule('pattern' => %w[pattern separator sub_pattern]).as 'pattern_sequence'
36
- rule('pattern' => 'sub_pattern').as 'basic_pattern'
37
- rule('sub_pattern' => 'quantifiable').as 'quantifiable_sub_pattern'
38
- rule('sub_pattern' => 'assertion').as 'assertion_sub_pattern'
39
- rule('separator' => 'COMMA').as 'comma_separator'
40
- rule('separator' => []).as 'void_separator'
41
- rule('flags' => %w[flags separator single_flag]).as 'flag_sequence'
42
- rule('flags' => %w[separator single_flag]).as 'flag_simple'
43
- rule('single_flag' => %w[CASE INSENSITIVE]).as 'case_insensitive'
44
- rule('single_flag' => %w[MULTI LINE]).as 'multi_line'
45
- rule('single_flag' => %w[ALL LAZY]).as 'all_lazy'
46
- rule('quantifiable' => %w[begin_anchor anchorable end_anchor]).as 'pinned_quantifiable'
47
- rule('quantifiable' => %w[begin_anchor anchorable]).as 'begin_anchor_quantifiable'
48
- rule('quantifiable' => %w[anchorable end_anchor]).as 'end_anchor_quantifiable'
49
- rule('quantifiable' => 'anchorable').as 'simple_quantifiable'
50
- rule('begin_anchor' => %w[STARTS WITH]).as 'starts_with'
51
- rule('begin_anchor' => %w[BEGIN WITH]).as 'begin_with'
52
- rule('end_anchor' => %w[separator MUST END]).as 'end_anchor'
53
- rule('anchorable' => 'assertable').as 'simple_anchorable'
54
- rule('assertion' => %w[IF FOLLOWED BY assertable]).as 'if_followed'
55
- rule('assertion' => %w[IF NOT FOLLOWED BY assertable]).as 'if_not_followed'
56
- rule('assertion' => %w[IF ALREADY HAD assertable]).as 'if_had'
57
- rule('assertion' => %w[IF NOT ALREADY HAD assertable]).as 'if_not_had'
58
- rule('assertable' => 'term').as 'simple_assertable'
59
- rule('assertable' => %w[term quantifier]).as 'quantified_assertable'
60
- rule('term' => 'atom').as 'atom_term'
61
- rule('term' => 'alternation').as 'alternation_term'
62
- rule('term' => 'grouping').as 'grouping_term'
63
- rule('term' => 'capturing_group').as 'capturing_group_atom'
64
- rule('atom' => 'letter_range').as 'letter_range_atom'
65
- rule('atom' => 'digit_range').as 'digit_range_atom'
66
- rule('atom' => 'character_class').as 'character_class_atom'
67
- rule('atom' => 'special_char').as 'special_char_atom'
68
- rule('atom' => 'literal').as 'literal_atom'
69
- rule('atom' => 'raw').as 'raw_atom'
70
- rule('letter_range' => %w[LETTER FROM LETTER_LIT TO LETTER_LIT]).as 'lowercase_from_to'
71
- rule('letter_range' => %w[UPPERCASE LETTER FROM LETTER_LIT TO LETTER_LIT]).as 'uppercase_from_to'
72
- rule('letter_range' => 'LETTER').as 'any_lowercase'
73
- rule('letter_range' => %w[UPPERCASE LETTER]).as 'any_uppercase'
74
- rule('digit_range' => %w[digit_or_number FROM DIGIT_LIT TO DIGIT_LIT]).as 'digits_from_to'
75
- rule('character_class' => %w[ANY CHARACTER]).as 'any_character'
76
- rule('character_class' => %w[NO CHARACTER]).as 'no_character'
77
- rule('character_class' => 'digit_or_number').as 'digit'
78
- rule('character_class' => %w[NO DIGIT]).as 'non_digit'
79
- rule('character_class' => 'WHITESPACE').as 'whitespace'
80
- rule('character_class' => %w[NO WHITESPACE]).as 'no_whitespace'
81
- rule('character_class' => 'ANYTHING').as 'anything'
82
- rule('character_class' => %w[ONE OF cclass]).as 'one_of'
83
- rule('character_class' => %w[NONE OF cclass]).as 'none_of'
84
- rule('cclass' => 'STRING_LIT').as 'quoted_cclass' # Preferred syntax
85
- rule('cclass' => 'INTEGER').as 'digits_cclass'
86
- rule('cclass' => 'IDENTIFIER').as 'identifier_cclass'
87
- rule('cclass' => 'CHAR_CLASS').as 'unquoted_cclass'
88
- rule('special_char' => 'TAB').as 'tab'
89
- rule('special_char' => 'VERTICAL TAB').as 'vtab'
90
- rule('special_char' => 'BACKSLASH').as 'backslash'
91
- rule('special_char' => %w[NEW LINE]).as 'new_line'
92
- rule('special_char' => %w[CARRIAGE RETURN]).as 'carriage_return'
93
- rule('special_char' => %w[WORD]).as 'word'
94
- rule('special_char' => %w[NO WORD]).as 'no_word'
95
- rule('literal' => %w[LITERALLY STRING_LIT]).as 'literally'
96
- rule('raw' => 'RAW STRING_LIT').as 'raw_literal'
97
- rule('alternation' => %w[any_or_either OF LPAREN alternatives RPAREN]).as 'any_of'
98
- rule('alternatives' => %w[alternatives separator quantifiable]).as 'alternative_list'
99
- rule('alternatives' => 'quantifiable').as 'simple_alternative'
100
- rule('any_or_either' => 'ANY').as 'any_keyword'
101
- rule('any_or_either' => 'EITHER').as 'either_keyword'
102
- rule('grouping' => %w[LPAREN pattern RPAREN]).as 'grouping_parenthenses'
103
- rule('capturing_group' => %w[CAPTURE assertable]).as 'capture'
104
- rule('capturing_group' => %w[CAPTURE assertable UNTIL assertable]).as 'capture_until'
105
- rule('capturing_group' => %w[CAPTURE assertable AS var_name]).as 'named_capture'
106
- rule('capturing_group' => %w[CAPTURE assertable AS var_name UNTIL assertable]).as 'named_capture_until'
107
- rule('var_name' => 'STRING_LIT').as 'var_name'
108
- rule('var_name' => 'IDENTIFIER').as 'var_ident' # capture name not enclosed between quotes
109
- rule('quantifier' => 'ONCE').as 'once'
110
- rule('quantifier' => 'TWICE').as 'twice'
111
- rule('quantifier' => %w[EXACTLY count TIMES]).as 'exactly'
112
- rule('quantifier' => %w[BETWEEN count AND count times_suffix]).as 'between_and'
113
- rule('quantifier' => 'OPTIONAL').as 'optional'
114
- rule('quantifier' => %w[ONCE OR MORE]).as 'once_or_more'
115
- rule('quantifier' => %w[NEVER OR MORE]).as 'never_or_more'
116
- rule('quantifier' => %w[AT LEAST count TIMES]).as 'at_least'
117
- rule('digit_or_number' => 'DIGIT').as 'digit_keyword'
118
- rule('digit_or_number' => 'NUMBER').as 'number_keyword'
119
- rule('count' => 'DIGIT_LIT').as 'single_digit'
120
- rule('count' => 'INTEGER').as 'integer_count'
121
- rule('times_suffix' => 'TIMES').as 'times_keyword'
122
- rule('times_suffix' => []).as 'times_dropped'
34
+ rule('srl' => 'expression').tag 'start_rule'
35
+ rule('expression' => 'pattern flags?').tag 'flagged_expr'
36
+ rule('pattern' => 'sub_pattern (separator sub_pattern)*').tag 'pattern_sequence'
37
+ rule('sub_pattern' => 'quantifiable').tag 'quantifiable_sub_pattern'
38
+ rule('sub_pattern' => 'assertion').tag 'assertion_sub_pattern'
39
+ rule('separator' => 'COMMA?')
40
+ rule('flags' => '(separator single_flag)+').tag 'flag_sequence'
41
+ rule('single_flag' => 'CASE INSENSITIVE').tag 'case_insensitive'
42
+ rule('single_flag' => 'MULTI LINE').tag 'multi_line'
43
+ rule('single_flag' => 'ALL LAZY').tag 'all_lazy'
44
+ rule('quantifiable' => 'begin_anchor? anchorable end_anchor?').tag 'quantifiable'
45
+ rule('begin_anchor' => 'STARTS WITH').tag 'starts_with'
46
+ rule('begin_anchor' => 'BEGIN WITH').tag 'begin_with'
47
+ rule('end_anchor' => 'separator MUST END').tag 'end_anchor'
48
+ rule('anchorable' => 'assertable').tag 'simple_anchorable'
49
+ rule('assertion' => 'IF NOT? FOLLOWED BY assertable').tag 'if_followed'
50
+ rule('assertion' => 'IF NOT? ALREADY HAD assertable').tag 'if_had'
51
+ rule('assertable' => 'term quantifier?').tag 'assertable'
52
+ rule('term' => 'atom').tag 'atom_term'
53
+ rule('term' => 'alternation').tag 'alternation_term'
54
+ rule('term' => 'grouping').tag 'grouping_term'
55
+ rule('term' => 'capturing_group').tag 'capturing_group_atom'
56
+ rule('atom' => 'letter_range').tag 'letter_range_atom'
57
+ rule('atom' => 'digit_range').tag 'digit_range_atom'
58
+ rule('atom' => 'character_class').tag 'character_class_atom'
59
+ rule('atom' => 'special_char').tag 'special_char_atom'
60
+ rule('atom' => 'literal').tag 'literal_atom'
61
+ rule('atom' => 'raw').tag 'raw_atom'
62
+ rule('letter_range' => 'LETTER FROM LETTER_LIT TO LETTER_LIT').tag 'lowercase_from_to'
63
+ rule('letter_range' => 'UPPERCASE LETTER FROM LETTER_LIT TO LETTER_LIT').tag 'uppercase_from_to'
64
+ rule('letter_range' => 'LETTER').tag 'any_lowercase'
65
+ rule('letter_range' => 'UPPERCASE LETTER').tag 'any_uppercase'
66
+ rule('digit_range' => 'digit_or_number FROM DIGIT_LIT TO DIGIT_LIT').tag 'digits_from_to'
67
+ rule('character_class' => 'ANY CHARACTER').tag 'any_character'
68
+ rule('character_class' => 'NO CHARACTER').tag 'no_character'
69
+ rule('character_class' => 'digit_or_number').tag 'digit'
70
+ rule('character_class' => 'NO DIGIT').tag 'non_digit'
71
+ rule('character_class' => 'WHITESPACE').tag 'whitespace'
72
+ rule('character_class' => 'NO WHITESPACE').tag 'no_whitespace'
73
+ rule('character_class' => 'ANYTHING').tag 'anything'
74
+ rule('character_class' => 'ONE OF cclass').tag 'one_of'
75
+ rule('character_class' => 'NONE OF cclass').tag 'none_of'
76
+ rule('cclass' => 'STRING_LIT').tag 'quoted_cclass' # Preferred syntax
77
+ rule('cclass' => 'INTEGER').tag 'digits_cclass'
78
+ rule('cclass' => 'IDENTIFIER').tag 'identifier_cclass'
79
+ rule('cclass' => 'CHAR_CLASS').tag 'unquoted_cclass'
80
+ rule('special_char' => 'TAB').tag 'tab'
81
+ rule('special_char' => 'VERTICAL TAB').tag 'vtab'
82
+ rule('special_char' => 'BACKSLASH').tag 'backslash'
83
+ rule('special_char' => 'NEW LINE').tag 'new_line'
84
+ rule('special_char' => 'CARRIAGE RETURN').tag 'carriage_return'
85
+ rule('special_char' => 'WORD').tag 'word'
86
+ rule('special_char' => 'NO WORD').tag 'no_word'
87
+ rule('literal' => 'LITERALLY STRING_LIT').tag 'literally'
88
+ rule('raw' => 'RAW STRING_LIT').tag 'raw_literal'
89
+ rule('alternation' => 'any_or_either OF LPAREN alternatives RPAREN').tag 'any_of'
90
+ rule('alternatives' => 'alternatives separator quantifiable').tag 'alternative_list'
91
+ rule('alternatives' => 'quantifiable').tag 'simple_alternative'
92
+ rule('any_or_either' => 'ANY').tag 'any_keyword'
93
+ rule('any_or_either' => 'EITHER').tag 'either_keyword'
94
+ rule('grouping' => 'LPAREN pattern RPAREN').tag 'grouping_parenthenses'
95
+ rule('capturing_group' => 'CAPTURE assertable (UNTIL assertable)?').tag 'capture'
96
+ rule('capturing_group' => 'CAPTURE assertable AS var_name (UNTIL assertable)?').tag 'named_capture'
97
+ rule('var_name' => 'STRING_LIT').tag 'var_name'
98
+ rule('var_name' => 'IDENTIFIER').tag 'var_ident' # capture name not enclosed between quotes
99
+ rule('quantifier' => 'ONCE').tag 'once'
100
+ rule('quantifier' => 'TWICE').tag 'twice'
101
+ rule('quantifier' => 'EXACTLY count TIMES').tag 'exactly'
102
+ rule('quantifier' => 'BETWEEN count AND count TIMES?').tag 'between_and'
103
+ rule('quantifier' => 'OPTIONAL').tag 'optional'
104
+ rule('quantifier' => 'ONCE OR MORE').tag 'once_or_more'
105
+ rule('quantifier' => 'NEVER OR MORE').tag 'never_or_more'
106
+ rule('quantifier' => 'AT LEAST count TIMES').tag 'at_least'
107
+ rule('digit_or_number' => 'DIGIT').tag 'digit_keyword'
108
+ rule('digit_or_number' => 'NUMBER').tag 'number_keyword'
109
+ rule('count' => 'DIGIT_LIT').tag 'single_digit'
110
+ rule('count' => 'INTEGER').tag 'integer_count'
123
111
  end
124
112
 
125
113
  # And now build the grammar and make it accessible via a global constant
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../regex/character'
2
4
  require_relative '../regex/char_range'
3
5
  require_relative '../regex/concatenation'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: srl_tokenizer.rb
2
4
  # Tokenizer for SRL (Simple Regex Language)
3
5
  require 'strscan'
@@ -15,10 +17,14 @@ module SrlRuby
15
17
  # Delimiters: parentheses '(' and ')'
16
18
  # Separators: comma (optional)
17
19
  class Tokenizer
20
+ # @return [StringScanner]
18
21
  attr_reader(:scanner)
22
+
23
+ # @return [Integer] current line number
19
24
  attr_reader(:lineno)
25
+
26
+ # @return [Integer] offset of start of current line within input
20
27
  attr_reader(:line_start)
21
- # attr_reader(:column)
22
28
 
23
29
  @@lexeme2name = {
24
30
  '(' => 'LPAREN',
@@ -84,7 +90,7 @@ module SrlRuby
84
90
  WHITESPACE
85
91
  WITH
86
92
  WORD
87
- ].map { |x| [x, x] } .to_h
93
+ ].map { |x| [x, x] }.to_h
88
94
 
89
95
  class ScanError < StandardError; end
90
96
 
@@ -151,9 +157,9 @@ module SrlRuby
151
157
  col = scanner.pos - aLexeme.size - @line_start + 1
152
158
  pos = Rley::Lexical::Position.new(@lineno, col)
153
159
  token = Rley::Lexical::Token.new(aLexeme, aSymbolName, pos)
154
- rescue StandardError => exc
160
+ rescue StandardError => e
155
161
  puts "Failing with '#{aSymbolName}' and '#{aLexeme}'"
156
- raise exc
162
+ raise e
157
163
  end
158
164
 
159
165
  return token
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SrlRuby
2
- VERSION = '0.4.5'.freeze
4
+ VERSION = '0.4.9'
3
5
  end
data/lib/srl_ruby.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative './srl_ruby/version'
2
4
  require_relative './srl_ruby/tokenizer'
3
5
  require_relative './srl_ruby/grammar'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper'
2
4
  require_relative './support/rule_file_parser'
3
5
  require_relative '../../lib/srl_ruby'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'rule_file_nodes'
2
4
 
3
5
  module Acceptance
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: rule_file_grammar.rb
2
4
  require 'rley' # Load the Rley gem
3
5
 
@@ -5,20 +7,20 @@ require 'rley' # Load the Rley gem
5
7
  # [File format](https://github.com/SimpleRegex/Test-Rules/blob/master/README.md)
6
8
  ########################################
7
9
  # Define a grammar for basic arithmetical expressions
8
- builder = Rley::Syntax::GrammarBuilder.new do
10
+ builder = Rley::grammar_builder do
9
11
  # Punctuation
10
12
  add_terminals('COLON', 'DASH')
11
13
 
12
14
  # Keywords
13
15
  add_terminals('CAPTURE', 'FOR')
14
- add_terminals('MATCH:', 'NO', 'SRL:')
16
+ add_terminals('MATCH', 'NO', 'SRL')
15
17
 
16
18
  # Literals
17
19
  add_terminals('INTEGER', 'STRING_LIT')
18
20
  add_terminals('IDENTIFIER', 'SRL_SOURCE')
19
21
 
20
22
  rule('rule_file' => 'srl_heading srl_tests').as 'start_rule'
21
- rule('srl_heading' => 'SRL: SRL_SOURCE').as 'srl_source'
23
+ rule('srl_heading' => 'SRL SRL_SOURCE').as 'srl_source'
22
24
  rule('srl_tests' => 'srl_tests single_test').as 'test_list'
23
25
  rule('srl_tests' => 'single_test').as 'one_test'
24
26
  rule('single_test' => 'atomic_test').as 'single_atomic_test'
@@ -26,8 +28,8 @@ builder = Rley::Syntax::GrammarBuilder.new do
26
28
  rule('atomic_test' => 'match_test').as 'atomic_match'
27
29
  rule('atomic_test' => 'no_match_test').as 'atomic_no_match'
28
30
  rule('compound_test' => 'capture_test').as 'compound_capture'
29
- rule('match_test' => 'MATCH: STRING_LIT').as 'match_string'
30
- rule('no_match_test' => 'NO MATCH: STRING_LIT').as 'no_match_string'
31
+ rule('match_test' => 'MATCH STRING_LIT').as 'match_string'
32
+ rule('no_match_test' => 'NO MATCH STRING_LIT').as 'no_match_string'
31
33
  rule('capture_test' => 'capture_heading capture_expectations').as 'capture_test'
32
34
  rule('capture_heading' => 'CAPTURE FOR STRING_LIT COLON').as 'capture_string'
33
35
  rule('capture_expectations' => 'capture_expectations single_expectation').as 'assertion_list'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Classes that implement nodes of Abstract Syntax Trees (AST) representing
2
4
  # rule file contents.
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'rule_file_tokenizer'
2
4
  require_relative 'rule_file_grammar'
3
5
  require_relative 'rule_file_ast_builder'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: rule_tokenizer.rb
2
4
  # Tokenizer for SimpleRegex Test-Rule files
3
5
  # [File format](https://github.com/SimpleRegex/Test-Rules/blob/master/README.md)
@@ -14,8 +16,13 @@ module Acceptance
14
16
  # Delimiters: parentheses '(' and ')'
15
17
  # Separators: comma (optional)
16
18
  class RuleFileTokenizer
19
+ # @return [StringScanner]
17
20
  attr_reader(:scanner)
21
+
22
+ # @return [Integer] current line number
18
23
  attr_reader(:lineno)
24
+
25
+ # @return [Integer] offset of start of current line within input
19
26
  attr_reader(:line_start)
20
27
 
21
28
  # Can be :default, :expecting_srl
@@ -80,7 +87,7 @@ module Acceptance
80
87
  elsif (lexeme = scanner.scan(/[0-9]+/))
81
88
  token = build_token('INTEGER', lexeme)
82
89
  elsif (lexeme = scanner.scan(/srl:|match:/))
83
- token = build_token(@@keywords[lexeme], lexeme)
90
+ token = build_token(@@keywords[lexeme].chop, lexeme.chop)
84
91
  @state = :expecting_srl if lexeme == 'srl:'
85
92
  elsif (lexeme = scanner.scan(/[a-zA-Z_][a-zA-Z0-9_]*/))
86
93
  keyw = @@keywords[lexeme]
@@ -111,9 +118,9 @@ module Acceptance
111
118
  col = scanner.pos - aLexeme.size - @line_start + 1
112
119
  pos = Rley::Lexical::Position.new(@lineno, col)
113
120
  token = Rley::Lexical::Token.new(aLexeme, aSymbolName, pos)
114
- rescue StandardError => exc
121
+ rescue StandardError => e
115
122
  puts "Failing with '#{aSymbolName}' and '#{aLexeme}'"
116
- raise exc
123
+ raise e
117
124
  end
118
125
 
119
126
  return token
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: atomic_expression_spec.rb
2
4
  require_relative '../spec_helper' # Use the RSpec test framework
3
5
  require_relative '../../lib/regex/atomic_expression'
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: character_spec.rb
2
4
  require_relative '../spec_helper' # Use the RSpec test framework
3
5
  require_relative '../../lib/regex/character'
4
6
 
5
7
  module Regex # Open this namespace, to get rid of scope qualifiers
6
8
  describe Character do
9
+ # rubocop: disable Lint/ConstantDefinitionInBlock
10
+
7
11
  # This constant holds an arbitrary selection of characters
8
12
  SampleChars = [?a, ?\0, ?\u0107].freeze
9
13
 
@@ -85,6 +89,8 @@ module Regex # Open this namespace, to get rid of scope qualifiers
85
89
 
86
90
  # Try with our escape sequence samples
87
91
  (SampleDigrams + SampleNumEscs).each do |escape_seq|
92
+
93
+ # Build a string from escape sequence literal
88
94
  expectation = String.class_eval(%Q|"#{escape_seq}"|, __FILE__, __LINE__)
89
95
  new_ch = Character.new(escape_seq).to_str
90
96
  new_ch == expectation
@@ -109,11 +115,20 @@ module Regex # Open this namespace, to get rid of scope qualifiers
109
115
 
110
116
  # Try with our escape sequence samples
111
117
  (SampleDigrams + SampleNumEscs).each do |escape_seq|
118
+
119
+ # Get ordinal value of given escape sequence
112
120
  expectation = String.class_eval(%Q|"#{escape_seq}".ord()|, __FILE__, __LINE__)
113
121
  expect(Character.new(escape_seq).codepoint).to eq(expectation)
114
122
  end
115
123
  end
116
124
 
125
+ # Create a module that re-defines the existing to_s method
126
+ module Tweak_to_s
127
+ def to_s # Overwrite the existing to_s method
128
+ ?\u03a3
129
+ end
130
+ end # module
131
+
117
132
  it 'should known whether it is equal to another Object' do
118
133
  newOne = Character.new(?\u03a3)
119
134
 
@@ -145,12 +160,6 @@ module Regex # Open this namespace, to get rid of scope qualifiers
145
160
  expect(simulator).to receive(:to_s).and_return(?\u03a3)
146
161
  expect(newOne).to eq(simulator)
147
162
 
148
- # Create a module that re-defines the existing to_s method
149
- module Tweak_to_s
150
- def to_s # Overwrite the existing to_s method
151
- ?\u03a3
152
- end
153
- end # module
154
163
  weird = Object.new
155
164
  weird.extend(Tweak_to_s)
156
165
  expect(newOne).to eq(weird)
@@ -164,6 +173,7 @@ module Regex # Open this namespace, to get rid of scope qualifiers
164
173
  expect(ch2.explain).to eq("the character '\u03a3'")
165
174
  end
166
175
  end # context
176
+ # rubocop: enable Lint/ConstantDefinitionInBlock
167
177
  end # describe
168
178
  end # module
169
179
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: match_option_spec.rb
2
4
 
3
5
  require_relative '../spec_helper' # Use the RSpec test framework
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: monadic_expression_spec.rb
2
4
  require_relative '../spec_helper' # Use the RSpec test framework
3
5
  require_relative '../../lib/regex/monadic_expression'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: multiplicity_spec.rb
2
4
 
3
5
  require_relative '../spec_helper' # Use the RSpec test framework
@@ -21,6 +23,7 @@ module Regex # This module is used as a namespace
21
23
  end
22
24
 
23
25
  context 'Provided services' do
26
+ # rubocop: disable Style/CombinableLoops
24
27
  it 'should know its text representation' do
25
28
  policy2text = { greedy: '', lazy: '?', possessive: '+' }
26
29
 
@@ -71,6 +74,7 @@ module Regex # This module is used as a namespace
71
74
  end
72
75
  end
73
76
  end
77
+ # rubocop: enable Style/CombinableLoops
74
78
  end
75
79
  end
76
80
  end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: repetition_spec.rb
2
4
  require_relative '../spec_helper' # Use the RSpec test framework
3
5
  require_relative '../../lib/regex/repetition'
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/setup'
2
4
  require 'rspec' # Use the RSpec framework
3
5
  require_relative '../lib/srl_ruby'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper'
2
4
 
3
5
  RSpec.describe SrlRuby do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper' # Use the RSpec framework
2
4
  require_relative '../../lib/srl_ruby/tokenizer' # Load the class under test
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'spec_helper' # Use the RSpec framework
2
4
  require_relative '../lib/srl_ruby'
3
5
 
@@ -224,7 +226,7 @@ SRL
224
226
  let(:prefix) { 'letter from p to t ' }
225
227
 
226
228
  it "should parse 'once' syntax" do
227
- regexp = SrlRuby.parse(prefix + 'once')
229
+ regexp = SrlRuby.parse("#{prefix}once")
228
230
  expect(regexp.source).to eq('[p-t]{1}')
229
231
  end
230
232
 
@@ -244,26 +246,26 @@ SRL
244
246
  end
245
247
 
246
248
  it "should parse 'between ... and ... times' syntax" do
247
- regexp = SrlRuby.parse(prefix + 'between 2 and 4 times')
249
+ regexp = SrlRuby.parse("#{prefix}between 2 and 4 times")
248
250
  expect(regexp.source).to eq('[p-t]{2,4}')
249
251
 
250
252
  # Dropping 'times' keyword is a shorter alternative syntax
251
- regexp = SrlRuby.parse(prefix + 'between 2 and 4')
253
+ regexp = SrlRuby.parse("#{prefix}between 2 and 4")
252
254
  expect(regexp.source).to eq('[p-t]{2,4}')
253
255
  end
254
256
 
255
257
  it "should parse 'once or more' syntax" do
256
- regexp = SrlRuby.parse(prefix + 'once or more')
258
+ regexp = SrlRuby.parse("#{prefix}once or more")
257
259
  expect(regexp.source).to eq('[p-t]+')
258
260
  end
259
261
 
260
262
  it "should parse 'never or more' syntax" do
261
- regexp = SrlRuby.parse(prefix + 'never or more')
263
+ regexp = SrlRuby.parse("#{prefix}never or more")
262
264
  expect(regexp.source).to eq('[p-t]*')
263
265
  end
264
266
 
265
267
  it "should parse 'at least ... times' syntax" do
266
- regexp = SrlRuby.parse(prefix + 'at least 10 times')
268
+ regexp = SrlRuby.parse("#{prefix}at least 10 times")
267
269
  expect(regexp.source).to eq('[p-t]{10,}')
268
270
  end
269
271
  end # context
data/srl_ruby.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('../lib', __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'srl_ruby/version'
@@ -63,14 +65,14 @@ SUMMARY
63
65
  spec.require_paths = ['lib']
64
66
  PkgExtending.pkg_files(spec)
65
67
  PkgExtending.pkg_documentation(spec)
66
- spec.required_ruby_version = '>= 2.1.0'
68
+ spec.required_ruby_version = '>= 2.5.0'
67
69
 
68
70
  # Runtime dependencies
69
- spec.add_dependency 'rley', '~> 0.7.00'
71
+ spec.add_dependency 'rley', '~> 0.8.08'
70
72
 
71
73
  # Development dependencies
72
- spec.add_development_dependency 'bundler', '~> 1.16'
74
+ spec.add_development_dependency 'bundler', '~> 2.2.0'
73
75
  spec.add_development_dependency 'cucumber', '>= 2.2.0'
74
- spec.add_development_dependency 'rake', '~> 10.0'
76
+ spec.add_development_dependency 'rake', '~> 12.0'
75
77
  spec.add_development_dependency 'rspec', '~> 3.0'
76
78
  end