regular_expression 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []