iregexp 0.0.1
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 +7 -0
- data/bin/iregexp +119 -0
- data/bin/iregexp~ +102 -0
- data/iregexp.gemspec +21 -0
- data/lib/iregexp.rb +39 -0
- data/lib/parser/iregexp-util.rb +12 -0
- data/lib/parser/iregexpgrammar.rb +1978 -0
- data/lib/writer/iregexp-writer.rb +92 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e6fe6ee35f1dd62cd10b9aa7105cf58c46f76c16f20a23a752c70ffd3e043fb6
|
4
|
+
data.tar.gz: 93a7a857b277c22f055b922761cdd152524fd48c8755ca503501f5082bf78263
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c8dc4f7369ab2e828fb3be27f848369a7763a4345f0aec9026a11b4397a3ef2b3bfc34648bcf18013435be8fac05582203b965f5bbd9ead54cbcc10d48774354
|
7
|
+
data.tar.gz: 1d43505cf373b29f6cf8e670b644e879e10b0dba00a4efc06c56610026be8fb3c796fd96f1ca9247ef170682b92f0b8d223f96367bc78c86453eef153c621a11
|
data/bin/iregexp
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pp'
|
3
|
+
require 'yaml'
|
4
|
+
require 'treetop'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
require_relative '../lib/iregexp'
|
8
|
+
|
9
|
+
Encoding.default_external = Encoding::UTF_8
|
10
|
+
require 'optparse'
|
11
|
+
require 'ostruct'
|
12
|
+
|
13
|
+
FUNCSIG_CHARS = {"l" => :logical, "n" => :nodes, "v" => :value}
|
14
|
+
|
15
|
+
$options = OpenStruct.new
|
16
|
+
begin
|
17
|
+
op = OptionParser.new do |opts|
|
18
|
+
opts.banner = "Usage: jpt.rb [options] file.jp"
|
19
|
+
|
20
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
21
|
+
$options.verbose = v
|
22
|
+
end
|
23
|
+
opts.on("-l", "--[no-]lines", "multi-line mode") do |v|
|
24
|
+
$options.lines = v
|
25
|
+
end
|
26
|
+
opts.on("-eREGEXP", "--e=REGEXP", "supply iregexp on command line") do |v|
|
27
|
+
$options.regexp = v
|
28
|
+
end
|
29
|
+
opts.on("-tFMT", "--to=FMT", [:basic, :neat, :json, :yaml, :iregexp, :ire, :pcre, :js, :example, :random], "Target format") do |v|
|
30
|
+
$options.target = v
|
31
|
+
end
|
32
|
+
end
|
33
|
+
op.parse!
|
34
|
+
rescue Exception => e
|
35
|
+
warn e
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
if !$options.regexp
|
40
|
+
if ARGV == []
|
41
|
+
puts op
|
42
|
+
exit 1
|
43
|
+
end
|
44
|
+
$options.regexp = ARGF.read
|
45
|
+
else
|
46
|
+
if ARGV != []
|
47
|
+
warn "*** file names #{ARGV.join(", ")} ignored due to -e given"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
input_file = $options.regexp
|
52
|
+
|
53
|
+
if $options.lines
|
54
|
+
require_relative '../lib/writer/iregexp-writer.rb'
|
55
|
+
require "regexp-examples"
|
56
|
+
|
57
|
+
lines = input_file.lines(chomp: true)
|
58
|
+
col = lines.map(&:length).max
|
59
|
+
form = "%-#{col}s %s"
|
60
|
+
lines.each do |line|
|
61
|
+
re = line[1..-1]
|
62
|
+
next unless re
|
63
|
+
ok = line[0] =~ /\A[=*]\z/ # * = error in example generator
|
64
|
+
begin
|
65
|
+
ire = IREGEXP.from_iregexp(re)
|
66
|
+
result = ire.tree.inspect
|
67
|
+
puts form % [line, result]
|
68
|
+
fail "is marked as failing, but seems to be ok" unless ok
|
69
|
+
if line[0] == "*"
|
70
|
+
puts form % ["", "bug in regexp example generator:"]
|
71
|
+
end
|
72
|
+
puts form % ["", ire.to_regexp.
|
73
|
+
examples(max_repeater_variance: 4, max_group_results: 20).
|
74
|
+
map{ |s| JSON.dump(s)}.
|
75
|
+
join(", ")]
|
76
|
+
rescue IREGEXP::ParseError => e
|
77
|
+
l = line
|
78
|
+
e.to_s.lines.each do |li|
|
79
|
+
puts form % [l, li]
|
80
|
+
l = ""
|
81
|
+
end
|
82
|
+
fail "is marked as ok, but seems to be failing" if ok
|
83
|
+
end
|
84
|
+
end
|
85
|
+
else
|
86
|
+
|
87
|
+
ire = IREGEXP.from_iregexp(input_file)
|
88
|
+
result = ire.tree
|
89
|
+
|
90
|
+
case $options.target
|
91
|
+
when :basic, nil
|
92
|
+
pp result
|
93
|
+
when :neat, :json
|
94
|
+
require 'neatjson'
|
95
|
+
puts JSON.neat_generate(result, after_comma: 1, after_colon: 1)
|
96
|
+
when :yaml
|
97
|
+
puts result.to_yaml
|
98
|
+
when :iregexp, :ire
|
99
|
+
require_relative '../lib/writer/iregexp-writer.rb'
|
100
|
+
puts ire.to_s
|
101
|
+
when :pcre
|
102
|
+
require_relative '../lib/writer/iregexp-writer.rb'
|
103
|
+
puts ire.to_pcre
|
104
|
+
when :js
|
105
|
+
require_relative '../lib/writer/iregexp-writer.rb'
|
106
|
+
puts ire.to_js
|
107
|
+
when :example
|
108
|
+
require_relative '../lib/writer/iregexp-writer.rb'
|
109
|
+
require "regexp-examples"
|
110
|
+
puts ire.to_regexp.examples(max_repeater_variance: 4, max_group_results: 20)
|
111
|
+
when :random
|
112
|
+
require_relative '../lib/writer/iregexp-writer.rb'
|
113
|
+
require "regexp-examples"
|
114
|
+
puts ire.to_regexp.random_example(max_repeater_variance: 4)
|
115
|
+
else
|
116
|
+
warn ["Unknown target format: ", $options.target].inspect
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
data/bin/iregexp~
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pp'
|
3
|
+
require 'yaml'
|
4
|
+
require 'treetop'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
require_relative '../lib/jpt'
|
8
|
+
|
9
|
+
Encoding.default_external = Encoding::UTF_8
|
10
|
+
require 'optparse'
|
11
|
+
require 'ostruct'
|
12
|
+
|
13
|
+
FUNCSIG_CHARS = {"l" => :logical, "n" => :nodes, "v" => :value}
|
14
|
+
|
15
|
+
$options = OpenStruct.new
|
16
|
+
begin
|
17
|
+
op = OptionParser.new do |opts|
|
18
|
+
opts.banner = "Usage: jpt.rb [options] file.jp"
|
19
|
+
|
20
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
21
|
+
$options.verbose = v
|
22
|
+
end
|
23
|
+
opts.on("-l", "--[no-]lines", "multi-line mode") do |v|
|
24
|
+
$options.lines = v
|
25
|
+
end
|
26
|
+
opts.on("-q", "--[no-]test", "test-file mode") do |v|
|
27
|
+
$options.test = v
|
28
|
+
end
|
29
|
+
opts.on("-fFUNCSIG", "--[no-]f=FUNCSIG", "add function signature name=rppp") do |v|
|
30
|
+
fail "funcsig format must be name=rppp" unless v =~ /\A([a-z][_a-z0-9]*)-([lnv]+)\z/
|
31
|
+
|
32
|
+
JPTType.add_funcsig($1, $2)
|
33
|
+
end
|
34
|
+
opts.on("-tFMT", "--to=FMT", [:basic, :neat, :json, :yaml, :enum, :jp], "Target format") do |v|
|
35
|
+
$options.target = v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
op.parse!
|
39
|
+
rescue Exception => e
|
40
|
+
warn e
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
if ARGV == []
|
45
|
+
puts op
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
jp_file = ARGF.read
|
49
|
+
|
50
|
+
if $options.test
|
51
|
+
argument = query = output = nil
|
52
|
+
jp_file.scan(/((?:^(?:$|[^$=].*)\n)+)|([$].*)|=(.*)|#.*/) do |arg,qy,out|
|
53
|
+
begin
|
54
|
+
if arg
|
55
|
+
argument = JSON.parse(arg)
|
56
|
+
puts
|
57
|
+
puts JSON.dump(argument)
|
58
|
+
elsif qy
|
59
|
+
jpt = JPT.from_jp(qy)
|
60
|
+
output = jpt.apply(argument)
|
61
|
+
print jpt.tree.inspect << " "
|
62
|
+
puts "➔ #{JSON.dump(output)}"
|
63
|
+
elsif out
|
64
|
+
suggested = JSON.parse(out)
|
65
|
+
if output != suggested
|
66
|
+
p [:SUGGESTED, suggested]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
rescue => e
|
70
|
+
warn "*** #{e.detailed_message} #{e.backtrace}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
elsif $options.lines
|
74
|
+
lines = jp_file.lines(chomp: true)
|
75
|
+
col = lines.map(&:length).max
|
76
|
+
form = "%-#{col}s %s"
|
77
|
+
lines.each do |line|
|
78
|
+
jpt = JPT.from_jp(line)
|
79
|
+
result = jpt.tree.inspect
|
80
|
+
puts form % [line, result]
|
81
|
+
end
|
82
|
+
else
|
83
|
+
|
84
|
+
jpt = JPT.from_jp(jp_file)
|
85
|
+
result = jpt.tree
|
86
|
+
|
87
|
+
case $options.target
|
88
|
+
when :basic, nil
|
89
|
+
pp result
|
90
|
+
when :neat, :json
|
91
|
+
require 'neatjson'
|
92
|
+
puts JSON.neat_generate(result, after_comma: 1, after_colon: 1)
|
93
|
+
when :yaml
|
94
|
+
puts result.to_yaml
|
95
|
+
when :jp
|
96
|
+
require_relative '../lib/writer/jp-writer.rb'
|
97
|
+
puts jpt.to_s
|
98
|
+
else
|
99
|
+
warn ["Unknown target format: ", $options.target].inspect
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
data/iregexp.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "iregexp"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.summary = "I-Regexp Tools"
|
5
|
+
s.description = %q{iregexp implements converters and miscellaneous tools for I-Regexp}
|
6
|
+
s.author = "Carsten Bormann"
|
7
|
+
s.email = "cabo@tzi.org"
|
8
|
+
s.license = "MIT"
|
9
|
+
s.homepage = "http://github.com/cabo/iregexp"
|
10
|
+
s.files = Dir['lib/**/*.rb'] + %w(iregexp.gemspec) + Dir['data/*'] + Dir['bin/**/*.rb']
|
11
|
+
s.executables = Dir['bin/*'].map {|x| File.basename(x)}
|
12
|
+
s.required_ruby_version = '>= 3.0'
|
13
|
+
|
14
|
+
s.require_paths = ["lib"]
|
15
|
+
|
16
|
+
s.add_development_dependency 'bundler', '~>1'
|
17
|
+
s.add_dependency 'treetop', '~>1'
|
18
|
+
# s.add_dependency 'json'
|
19
|
+
s.add_dependency 'neatjson', '~>0.10'
|
20
|
+
s.add_dependency 'regexp-examples', '~>1.5.1'
|
21
|
+
end
|
data/lib/iregexp.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative "parser/iregexp-util.rb"
|
2
|
+
|
3
|
+
class IREGEXP
|
4
|
+
@@parser = IREGEXPGRAMMARParser.new
|
5
|
+
# include ::IREGEXPType
|
6
|
+
|
7
|
+
class ParseError < ArgumentError; end
|
8
|
+
|
9
|
+
DATA_DIR = Pathname.new(__FILE__) + "../../data/"
|
10
|
+
|
11
|
+
def self.reason(parser, s)
|
12
|
+
reason = [parser.failure_reason]
|
13
|
+
parser.failure_reason =~ /^(Expected .+) after/m
|
14
|
+
reason = ["#{$1.gsub("\n", '<<<NEWLINE>>>')}:"] if $1
|
15
|
+
if line = s.lines.to_a[parser.failure_line - 1]
|
16
|
+
reason << line
|
17
|
+
reason << "#{'~' * (parser.failure_column - 1)}^"
|
18
|
+
end
|
19
|
+
reason.join("\n").gsub(/[\u0000-\u0009\u000b\u001f\u007f]/) {|c| "\\u%04x" % c.ord}
|
20
|
+
end
|
21
|
+
|
22
|
+
SAFE_FN = /\A[-._a-zA-Z0-9]+\z/
|
23
|
+
|
24
|
+
def self.from_iregexp(s)
|
25
|
+
ast = @@parser.parse s
|
26
|
+
if !ast
|
27
|
+
fail ParseError.new(self.reason(@@parser, s))
|
28
|
+
end
|
29
|
+
ret = IREGEXP.new(ast)
|
30
|
+
|
31
|
+
ret
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_accessor :ast, :tree, :directives
|
35
|
+
def initialize(ast_)
|
36
|
+
@ast = ast_
|
37
|
+
@tree = ast.ast
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'treetop'
|
2
|
+
require_relative './iregexpgrammar'
|
3
|
+
require_relative '../iregexp'
|
4
|
+
|
5
|
+
class Treetop::Runtime::SyntaxNode
|
6
|
+
def ast
|
7
|
+
fail "undefined_ast #{inspect}"
|
8
|
+
end
|
9
|
+
def ast1 # devhack
|
10
|
+
"#{inspect[10..20]}--#{text_value[0..15]}"
|
11
|
+
end
|
12
|
+
end
|