regular_expression 0.1.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.
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RegularExpression::Parser
4
+ rule
5
+ target:
6
+ root
7
+ { result = val[0] }
8
+ | /* none */
9
+ { result = nil }
10
+
11
+ root:
12
+ CARET expression
13
+ { result = RegularExpression::AST::Root.new(val[1], at_start: true) }
14
+ | expression
15
+ { result = RegularExpression::AST::Root.new(val[0]) }
16
+
17
+ expression:
18
+ subexpression PIPE expression
19
+ { result = [RegularExpression::AST::Expression.new(val[0])] + val[2] }
20
+ | subexpression
21
+ { result = [RegularExpression::AST::Expression.new(val[0])] }
22
+
23
+ subexpression:
24
+ item subexpression
25
+ { result = [val[0]] + val[1] }
26
+ | item
27
+ { result = [val[0]] }
28
+
29
+ item:
30
+ group
31
+ | match
32
+ | ANCHOR
33
+ { result = RegularExpression::AST::Anchor.new(val[0]) }
34
+
35
+ group:
36
+ LPAREN expression RPAREN quantifier
37
+ { result = RegularExpression::AST::Group.new(val[1], quantifier: val[3]) }
38
+ | LPAREN expression RPAREN
39
+ { result = RegularExpression::AST::Group.new(val[1]) }
40
+
41
+ match:
42
+ match_item quantifier
43
+ { result = RegularExpression::AST::Match.new(val[0], quantifier: val[1]) }
44
+ | match_item
45
+ { result = RegularExpression::AST::Match.new(val[0]) }
46
+
47
+ match_item:
48
+ LBRACKET CARET character_group_items RBRACKET
49
+ { result = RegularExpression::AST::CharacterGroup.new(val[2], invert: true) }
50
+ | LBRACKET character_group_items RBRACKET
51
+ { result = RegularExpression::AST::CharacterGroup.new(val[1]) }
52
+ | CHAR_CLASS
53
+ { result = RegularExpression::AST::CharacterClass.new(val[0]) }
54
+ | CHAR
55
+ { result = RegularExpression::AST::Character.new(val[0]) }
56
+ | PERIOD
57
+ { result = RegularExpression::AST::Period.new }
58
+
59
+ character_group_items:
60
+ character_group_item character_group_items
61
+ { result = [val[0]] + val[1] }
62
+ | character_group_item
63
+ { result = [val[0]] }
64
+
65
+ character_group_item:
66
+ CHAR_CLASS
67
+ | CHAR DASH CHAR
68
+ { result = RegularExpression::AST::CharacterRange.new(val[0], val[2]) }
69
+ | CHAR
70
+ { result = RegularExpression::AST::Character.new(val[0]) }
71
+
72
+ quantifier:
73
+ LBRACE INTEGER COMMA INTEGER RBRACE
74
+ { result = RegularExpression::AST::Quantifier::Range.new(val[1], val[3]) }
75
+ | LBRACE INTEGER COMMA RBRACE
76
+ { result = RegularExpression::AST::Quantifier::AtLeast.new(val[1]) }
77
+ | LBRACE INTEGER RBRACE
78
+ { result = RegularExpression::AST::Quantifier::Exact.new(val[1]) }
79
+ | STAR
80
+ { result = RegularExpression::AST::Quantifier::ZeroOrMore.new }
81
+ | PLUS
82
+ { result = RegularExpression::AST::Quantifier::OneOrMore.new }
83
+ | QMARK
84
+ { result = RegularExpression::AST::Quantifier::Optional.new }
85
+ end
86
+
87
+ ---- inner
88
+
89
+ def parse(str)
90
+ @tokens = RegularExpression::Lexer.new(str).tokens
91
+ do_parse
92
+ end
93
+
94
+ def next_token
95
+ @tokens.shift
96
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RegularExpression
4
+ class Pattern
5
+ attr_reader :bytecode
6
+
7
+ def initialize(source)
8
+ ast = Parser.new.parse(source)
9
+ @bytecode = Bytecode.compile(ast.to_nfa)
10
+ end
11
+
12
+ def compile(compiler: Generator::X86)
13
+ cfg = CFG.build(bytecode)
14
+
15
+ singleton_class.undef_method(:match?)
16
+ define_singleton_method(:match?, &compiler.compile(cfg))
17
+ end
18
+
19
+ def match?(string)
20
+ Interpreter.new(bytecode).match?(string)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RegularExpression
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/regular_expression/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "regular_expression"
7
+ spec.version = RegularExpression::VERSION
8
+ spec.authors = ["Kevin Newton"]
9
+ spec.email = ["kddnewton@gmail.com"]
10
+
11
+ spec.summary = "Regular expressions in Ruby"
12
+ spec.homepage = "https://github.com/kddeisz/regular_expression"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = Dir.chdir(__dir__) do
16
+ `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ end
20
+
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency "fisk"
24
+ spec.add_dependency "racc"
25
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: regular_expression
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Newton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-07-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fisk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: racc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - kddnewton@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".github/dependabot.yml"
49
+ - ".github/workflows/main.yml"
50
+ - ".gitignore"
51
+ - ".rubocop.yml"
52
+ - CODE_OF_CONDUCT.md
53
+ - CONTRIBUTING.md
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - LICENSE
57
+ - README.md
58
+ - Rakefile
59
+ - bin/console
60
+ - bin/parse
61
+ - build/.gitignore
62
+ - lib/regular_expression.rb
63
+ - lib/regular_expression/ast.rb
64
+ - lib/regular_expression/bytecode.rb
65
+ - lib/regular_expression/cfg.rb
66
+ - lib/regular_expression/compiler/ruby.rb
67
+ - lib/regular_expression/compiler/x86.rb
68
+ - lib/regular_expression/interpreter.rb
69
+ - lib/regular_expression/lexer.rb
70
+ - lib/regular_expression/nfa.rb
71
+ - lib/regular_expression/parser.rb
72
+ - lib/regular_expression/parser.y
73
+ - lib/regular_expression/pattern.rb
74
+ - lib/regular_expression/version.rb
75
+ - regular_expression.gemspec
76
+ homepage: https://github.com/kddeisz/regular_expression
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.2.3
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Regular expressions in Ruby
99
+ test_files: []