gpp 0.1.0 → 0.3.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.
- checksums.yaml +4 -4
- data/bin/gpp +12 -1
- data/lib/gpp/processor.rb +80 -33
- data/lib/gpp/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 539e909aab402cd55e8238e07e0f70e691716751
|
4
|
+
data.tar.gz: f3982fd692c0fb4df5a66b42abf53cb2d4715ee3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29e53154b0804e2f60f62755a5ffd6b22e244f9d6f7212895076c8e9c43ae0b90ad85e8c3f5a786b917c70e2e2d8677ea22849faccc22ae5492213be6d1f812d
|
7
|
+
data.tar.gz: f27500f9231e066812ede4af8c26716e73cec2cb6216ee5150c9ea6275a7289f6fc7073f23d530d2c01ec9225262d88f366d7f6eb0ab4b5827122455bc66888b
|
data/bin/gpp
CHANGED
@@ -3,15 +3,26 @@ require 'gpp'
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'optparse'
|
5
5
|
|
6
|
+
from, to = nil, nil
|
7
|
+
|
6
8
|
OptionParser.new do |opts|
|
7
9
|
opts.version = GPP::VERSION
|
8
10
|
opts.banner = "Usage: #{opts.program_name} [-hv] [files]"
|
11
|
+
opts.on "-r PATTERN" do |value|
|
12
|
+
_, from, to = value.split("/")
|
13
|
+
from = /#{from}/
|
14
|
+
end
|
9
15
|
end.order!
|
10
16
|
|
11
17
|
args = ARGV.empty? ? ["-"] : ARGV
|
12
18
|
|
13
19
|
args.each do |arg|
|
14
20
|
file = arg == "-" ? STDIN.read : File.read(arg)
|
15
|
-
|
21
|
+
out = if from
|
22
|
+
File.open(arg.gsub(from, to), "w")
|
23
|
+
else
|
24
|
+
STDOUT
|
25
|
+
end
|
26
|
+
rpp = GPP::Processor.new(file, out, arg, 1)
|
16
27
|
rpp.scan_all
|
17
28
|
end
|
data/lib/gpp/processor.rb
CHANGED
@@ -3,10 +3,15 @@ require 'strscan'
|
|
3
3
|
module GPP
|
4
4
|
class Processor < StringScanner
|
5
5
|
|
6
|
-
|
6
|
+
attr_reader :path, :trace
|
7
|
+
|
8
|
+
def initialize (in_, out, path, offset, defs = {}, trace = [])
|
7
9
|
super(in_)
|
8
10
|
@out = out
|
9
11
|
@defs = defs.to_h
|
12
|
+
@path = path
|
13
|
+
@offset = offset
|
14
|
+
@trace = trace
|
10
15
|
end
|
11
16
|
|
12
17
|
def loopcat (into = "")
|
@@ -40,9 +45,18 @@ module GPP
|
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
48
|
+
def indent_block (block, indent)
|
49
|
+
block.gsub(/^\n/, "").gsub(/\n$/, "").gsub("\n", "\n#{indent}")
|
50
|
+
end
|
51
|
+
|
52
|
+
def undent_block (block)
|
53
|
+
indent = block[/\A\n[ \t]+/]
|
54
|
+
indent ? block.gsub(/#{indent}/, "\n") : block
|
55
|
+
end
|
56
|
+
|
57
|
+
def scan_arg (bare = /\S+/)
|
58
|
+
if scan(/{/)
|
59
|
+
undent_block(scan_block())
|
46
60
|
elsif scan(/"/)
|
47
61
|
scan_string()
|
48
62
|
else
|
@@ -52,84 +66,117 @@ module GPP
|
|
52
66
|
|
53
67
|
def scan_args
|
54
68
|
if scan(/\(/)
|
55
|
-
|
69
|
+
scan(/[ \t]+/)
|
70
|
+
loopcat [scan_arg(/[^,)]*/)] do
|
56
71
|
if scan(/\)/)
|
57
72
|
nil
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
73
|
+
elsif scan(/,/)
|
74
|
+
scan(/[ \t]+/)
|
75
|
+
scan_arg(/[^,)]*/)
|
62
76
|
end
|
63
77
|
end
|
64
78
|
else
|
65
79
|
loopcat [] do
|
66
|
-
if scan(
|
80
|
+
if scan(/(?=\n)/)
|
67
81
|
nil
|
68
82
|
else
|
69
|
-
scan(/ +/)
|
70
|
-
|
83
|
+
scan(/[ \t]+/)
|
84
|
+
scan_arg
|
71
85
|
end
|
72
86
|
end
|
73
87
|
end
|
74
88
|
end
|
75
89
|
|
76
|
-
def run (string, args
|
90
|
+
def run (string, args, path, line)
|
91
|
+
trace = self.trace + [tracer]
|
77
92
|
if args == nil
|
78
|
-
self.class.new(string, s = "", @defs).scan_all
|
93
|
+
self.class.new(string, s = "", path, line, @defs, trace).scan_all
|
79
94
|
else
|
80
|
-
self.class.new(string, s = "", @defs.merge(args.to_h)).scan_all
|
95
|
+
self.class.new(string, s = "", path, line, @defs.merge(args.to_h), trace).scan_all
|
81
96
|
end
|
82
97
|
s
|
83
98
|
end
|
84
99
|
|
85
|
-
|
86
|
-
theargs = scan_args
|
87
|
-
run(body, args.zip(theargs))
|
88
|
-
end
|
100
|
+
Definition = Struct.new(:type, :args, :body, :path, :line)
|
89
101
|
|
90
102
|
def run_macro (id)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
run(d
|
103
|
+
rpos = pos - id.length - 2
|
104
|
+
w = string[(string.rindex("\n", rpos) || 0) + 1..rpos][/[ \t]+/]
|
105
|
+
res = if d = @defs[id]
|
106
|
+
case d.type
|
107
|
+
when :var
|
108
|
+
run(d.body, {}, d.path, d.line)
|
109
|
+
when :fun
|
110
|
+
args = scan_args.map{|arg| Definition.new(:var, {}, run(arg, {}, path, line), path, line)}
|
111
|
+
if d.args[-1] == "..."
|
112
|
+
la = d.args.length - 1
|
113
|
+
args[la..-1] = Definition.new(:var, {}, args[la..-1].map(&:body).join(" "), args[la].path, args[la].line)
|
114
|
+
end
|
115
|
+
if args.length != d.args.length
|
116
|
+
error "wrong argument count for #{id}: expected #{d.args.length} but got #{args.length}"
|
117
|
+
end
|
118
|
+
run(d.body, d.args.zip(args), d.path, d.line)
|
97
119
|
end
|
98
120
|
else
|
99
|
-
|
100
|
-
exit 1
|
121
|
+
error "undefined macro: #{id}"
|
101
122
|
end
|
123
|
+
indent_block(res, w)
|
102
124
|
end
|
103
125
|
|
104
126
|
def scan_define
|
127
|
+
line = self.line
|
105
128
|
name, *args, body = scan_args
|
106
|
-
|
129
|
+
if args == []
|
130
|
+
@defs[name] = Definition.new(:var, nil, body, @path, line)
|
131
|
+
else
|
132
|
+
@defs[name] = Definition.new(:fun, args, body, @path, line)
|
133
|
+
end
|
107
134
|
end
|
108
135
|
|
109
136
|
def scan_import ()
|
110
137
|
args = scan_args
|
111
138
|
args.each do |arg|
|
112
|
-
run File.read(arg)
|
139
|
+
run File.read(arg), nil, arg, 1
|
113
140
|
end
|
114
141
|
end
|
115
142
|
|
116
143
|
def scan_all
|
117
|
-
scan(/\s+/)
|
118
144
|
while !eos?
|
119
145
|
@out << (scan(/[^#@]+/) || "")
|
120
146
|
if scan(/#define\b/)
|
121
147
|
scan_define
|
148
|
+
scan(/\s+/)
|
122
149
|
elsif scan(/#import\b/)
|
123
150
|
scan_import
|
151
|
+
scan(/\s+/)
|
152
|
+
#elsif scan(/#(\w+)/)
|
153
|
+
# error "undefined meta-macro: #{self[1]}"
|
124
154
|
elsif scan(/@@/)
|
125
155
|
@out << "@"
|
126
|
-
elsif scan(/@(
|
156
|
+
elsif scan(/@(\.\.\.|\w+)/)
|
127
157
|
@out << (run_macro(self[1]) || "")
|
128
|
-
|
129
|
-
|
158
|
+
elsif s = scan(/./)
|
159
|
+
@out << s
|
130
160
|
end
|
131
161
|
end
|
132
162
|
end
|
133
163
|
|
164
|
+
def line
|
165
|
+
@offset + string[0..pos - 1].count("\n")
|
166
|
+
end
|
167
|
+
|
168
|
+
def tracer
|
169
|
+
[path, line]
|
170
|
+
end
|
171
|
+
|
172
|
+
def error (message)
|
173
|
+
STDERR.puts "#{message}"
|
174
|
+
STDERR.puts " in #{path}:#{line}"
|
175
|
+
trace.reverse.each do |path, line|
|
176
|
+
STDERR.puts " #{path}:#{line}"
|
177
|
+
end
|
178
|
+
exit 1
|
179
|
+
end
|
180
|
+
|
134
181
|
end
|
135
182
|
end
|
data/lib/gpp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gpp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Baum
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A text pre-processor
|
14
14
|
email: n@p12a.org.uk
|