packcr 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/packcr/buffer.rb +47 -0
- data/lib/packcr/code_block.rb +13 -0
- data/lib/packcr/context.rb +982 -0
- data/lib/packcr/generator.rb +35 -0
- data/lib/packcr/node/action_node.rb +52 -0
- data/lib/packcr/node/alternate_node.rb +71 -0
- data/lib/packcr/node/capture_node.rb +34 -0
- data/lib/packcr/node/charclass_node.rb +75 -0
- data/lib/packcr/node/error_node.rb +52 -0
- data/lib/packcr/node/expand_node.rb +36 -0
- data/lib/packcr/node/predicate_node.rb +51 -0
- data/lib/packcr/node/quantity_node.rb +55 -0
- data/lib/packcr/node/reference_node.rb +46 -0
- data/lib/packcr/node/rule_node.rb +30 -0
- data/lib/packcr/node/sequence_node.rb +61 -0
- data/lib/packcr/node/string_node.rb +43 -0
- data/lib/packcr/node.rb +17 -0
- data/lib/packcr/stream.rb +101 -0
- data/lib/packcr/util.rb +94 -0
- data/lib/packcr/version.rb +3 -0
- data/lib/packcr.rb +33 -0
- metadata +77 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
|
3
|
+
class Packcr
|
4
|
+
class Stream
|
5
|
+
def initialize(io, name, line)
|
6
|
+
@io = io
|
7
|
+
@name = name
|
8
|
+
@line = line
|
9
|
+
@line_directive_tag = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(s, rewrite_line_directive: false)
|
13
|
+
if rewrite_line_directive && @line_directive_tag && @line.respond_to?(:+)
|
14
|
+
s.gsub!(@line_directive_tag) { (@line + $`.count("\n") + 1).to_s }
|
15
|
+
@line_directive_tag = nil
|
16
|
+
end
|
17
|
+
@io.write(s)
|
18
|
+
if @line.respond_to?(:+)
|
19
|
+
@line += s.count("\n")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def write_text(s)
|
24
|
+
write s.gsub(/\r\n/, "\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_line_directive(fname, lineno)
|
28
|
+
return unless @line
|
29
|
+
if lineno.respond_to?(:+)
|
30
|
+
write("#line #{lineno + 1} \"")
|
31
|
+
else
|
32
|
+
@line_directive_tag ||= "<#{SecureRandom.uuid}>"
|
33
|
+
write("#line #{@line_directive_tag} \"")
|
34
|
+
end
|
35
|
+
|
36
|
+
write(Packcr.escape_string(fname))
|
37
|
+
write("\"\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
def write_output_line_directive
|
41
|
+
write_line_directive(@name, @line)
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_code_block(code, indent, fname)
|
45
|
+
text = code.text
|
46
|
+
ptr = text.b
|
47
|
+
len = code.len
|
48
|
+
lineno = code.line
|
49
|
+
if len == nil
|
50
|
+
return # for safety
|
51
|
+
end
|
52
|
+
|
53
|
+
ptr.sub!(/\A\n+/) do
|
54
|
+
lineno += $&.length
|
55
|
+
""
|
56
|
+
end
|
57
|
+
ptr.sub!(/[ \v\f\t\r\n]*\z/, "")
|
58
|
+
|
59
|
+
min_indent_spaces = nil
|
60
|
+
ptr.gsub!(/^([ \v\f\t]+)([^ \v\f\t\r\n])/) do
|
61
|
+
spaces = $1
|
62
|
+
char = $2
|
63
|
+
|
64
|
+
next char if char == "#"
|
65
|
+
|
66
|
+
Packcr.unify_indent_spaces(spaces)
|
67
|
+
|
68
|
+
if !min_indent_spaces || min_indent_spaces.length > spaces.length
|
69
|
+
min_indent_spaces = spaces
|
70
|
+
end
|
71
|
+
|
72
|
+
spaces + char
|
73
|
+
end
|
74
|
+
|
75
|
+
if min_indent_spaces
|
76
|
+
indent_spaces = " " * indent
|
77
|
+
ptr.gsub!(/^#{min_indent_spaces}( *[^\n#])/) do
|
78
|
+
"#{indent_spaces}#{$1}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
return if ptr.empty?
|
83
|
+
|
84
|
+
write_line_directive(fname, lineno)
|
85
|
+
ptr.scan(/^(.+?)[ \v\f\t\r]*$|^\r?\n/) do
|
86
|
+
write $1 if $1
|
87
|
+
write "\n"
|
88
|
+
end
|
89
|
+
write_output_line_directive
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_code_block(code, indent, fname)
|
93
|
+
buf = StringIO.new
|
94
|
+
line, io, @io, @line = @line, @io, buf, @line && :uuid
|
95
|
+
write_code_block(code, indent, fname)
|
96
|
+
return buf.string
|
97
|
+
ensure
|
98
|
+
@line, @io = line, io
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/packcr/util.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
class Packcr
|
2
|
+
module Util
|
3
|
+
def is_identifier_string(str)
|
4
|
+
str.match?(/\A(?!\d)\w+\z/)
|
5
|
+
end
|
6
|
+
|
7
|
+
def unescape_string(str, is_charclass)
|
8
|
+
if is_charclass
|
9
|
+
str.gsub!("\\" * 2) { "\\" * 4 }
|
10
|
+
end
|
11
|
+
str.gsub!(/\\(.)/) do
|
12
|
+
c = $1
|
13
|
+
case c
|
14
|
+
when "0"
|
15
|
+
"\\x00"
|
16
|
+
when "'"
|
17
|
+
c
|
18
|
+
else
|
19
|
+
"\\#{c}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
str.gsub!(/[^\x00-\x7f]/) do
|
23
|
+
"\\x%02x" % $&.ord
|
24
|
+
end
|
25
|
+
str.replace "\"#{str}\"".undump
|
26
|
+
end
|
27
|
+
|
28
|
+
def escape_character(c)
|
29
|
+
escape_string(c.chr)
|
30
|
+
end
|
31
|
+
|
32
|
+
def escape_string(str)
|
33
|
+
str = str.b
|
34
|
+
str.gsub(/(\0+)|(\e+)|("+)|('+)|(\\+)|((?:(?![\0\e"'\\])[ -~])+)|([\x01-\x1a\x1c-\x1f\x7f-\xff]+)/n) do
|
35
|
+
n = $&.size
|
36
|
+
next "\\0" * n if $1
|
37
|
+
next "\\x1b" * n if $2
|
38
|
+
next "\\\"" * n if $3
|
39
|
+
next "\\\'" * n if $4
|
40
|
+
next "\\\\" * n if $5
|
41
|
+
next $6 if $6
|
42
|
+
$7.dump[1..-2].downcase
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def dump_integer_value(value)
|
47
|
+
if value == nil
|
48
|
+
$stdout.print "void"
|
49
|
+
else
|
50
|
+
$stdout.print value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def dump_escaped_string(str)
|
55
|
+
if !str
|
56
|
+
$stdout.print "null"
|
57
|
+
return
|
58
|
+
end
|
59
|
+
$stdout.print escape_string(str)
|
60
|
+
end
|
61
|
+
|
62
|
+
def find_trailing_blanks(str)
|
63
|
+
str =~ /[ \v\f\t\n\r]*\z/
|
64
|
+
end
|
65
|
+
|
66
|
+
def unify_indent_spaces(spaces)
|
67
|
+
offset = 0
|
68
|
+
spaces.tr!("\v\f", " ")
|
69
|
+
spaces.gsub!(/\t+/) do
|
70
|
+
chars = $`.length
|
71
|
+
o = 8 * $&.length - (offset + chars) % 8
|
72
|
+
offset = (7 - chars) % 8
|
73
|
+
" " * o
|
74
|
+
end
|
75
|
+
spaces
|
76
|
+
end
|
77
|
+
|
78
|
+
def template(path, b, indent: 0, unwrap: false)
|
79
|
+
template_path = File.join(File.dirname(__FILE__), "templates", path)
|
80
|
+
erb = ERB.new(File.read(template_path), trim_mode: "%-")
|
81
|
+
erb.filename = template_path
|
82
|
+
result = erb.result(b)
|
83
|
+
if unwrap
|
84
|
+
result.gsub!(/\A\{|\}\z/, "")
|
85
|
+
indent -= 4
|
86
|
+
end
|
87
|
+
result.gsub!(/^(?!$)/, " " * indent)
|
88
|
+
result.gsub!(/^( *?) {0,4}<<<</) { $1 }
|
89
|
+
result
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
extend Util
|
94
|
+
end
|
data/lib/packcr.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class Packcr
|
2
|
+
end
|
3
|
+
|
4
|
+
require "packcr/util"
|
5
|
+
require "packcr/code_block"
|
6
|
+
require "packcr/stream"
|
7
|
+
require "packcr/generator"
|
8
|
+
require "packcr/buffer"
|
9
|
+
require "packcr/node"
|
10
|
+
require "packcr/context"
|
11
|
+
require "packcr/version"
|
12
|
+
|
13
|
+
class Packcr
|
14
|
+
CODE_REACH__BOTH = 0
|
15
|
+
CODE_REACH__ALWAYS_SUCCEED = 1
|
16
|
+
CODE_REACH__ALWAYS_FAIL = -1
|
17
|
+
|
18
|
+
def initialize(path, **opt)
|
19
|
+
@path = path.to_s
|
20
|
+
@opt = opt
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
Context.new(@path.to_s, **@opt) do |ctx|
|
25
|
+
if !ctx.parse
|
26
|
+
raise "PackCR error: can't parse"
|
27
|
+
end
|
28
|
+
if !ctx.generate
|
29
|
+
raise "PackCR error: can't generate"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: packcr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- wanabe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-01-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: test-unit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.5'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/packcr.rb
|
34
|
+
- lib/packcr/buffer.rb
|
35
|
+
- lib/packcr/code_block.rb
|
36
|
+
- lib/packcr/context.rb
|
37
|
+
- lib/packcr/generator.rb
|
38
|
+
- lib/packcr/node.rb
|
39
|
+
- lib/packcr/node/action_node.rb
|
40
|
+
- lib/packcr/node/alternate_node.rb
|
41
|
+
- lib/packcr/node/capture_node.rb
|
42
|
+
- lib/packcr/node/charclass_node.rb
|
43
|
+
- lib/packcr/node/error_node.rb
|
44
|
+
- lib/packcr/node/expand_node.rb
|
45
|
+
- lib/packcr/node/predicate_node.rb
|
46
|
+
- lib/packcr/node/quantity_node.rb
|
47
|
+
- lib/packcr/node/reference_node.rb
|
48
|
+
- lib/packcr/node/rule_node.rb
|
49
|
+
- lib/packcr/node/sequence_node.rb
|
50
|
+
- lib/packcr/node/string_node.rb
|
51
|
+
- lib/packcr/stream.rb
|
52
|
+
- lib/packcr/util.rb
|
53
|
+
- lib/packcr/version.rb
|
54
|
+
homepage: https://github.com/wanabe/packcr
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubygems_version: 3.4.1
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: Parser generator for C or Ruby
|
77
|
+
test_files: []
|