gpp 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|