Class: GPP::Processor
- Inherits:
-
StringScanner
- Object
- StringScanner
- GPP::Processor
- Defined in:
- lib/gpp/processor.rb
Defined Under Namespace
Classes: Definition
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#trace ⇒ Object
readonly
Returns the value of attribute trace.
Instance Method Summary collapse
- #error(message) ⇒ Object
- #indent_block(block, indent) ⇒ Object
-
#initialize(in_, out, path, offset, defs = {}, trace = []) ⇒ Processor
constructor
A new instance of Processor.
- #line ⇒ Object
- #loopcat(into = "") ⇒ Object
- #run(string, args, path, line) ⇒ Object
- #run_macro(id) ⇒ Object
- #scan_all ⇒ Object
- #scan_arg(bare = /\S+/) ⇒ Object
- #scan_args ⇒ Object
- #scan_block ⇒ Object
- #scan_define ⇒ Object
- #scan_import ⇒ Object
- #scan_string ⇒ Object
- #tracer ⇒ Object
- #undent_block(block) ⇒ Object
Constructor Details
#initialize(in_, out, path, offset, defs = {}, trace = []) ⇒ Processor
Returns a new instance of Processor.
8 9 10 11 12 13 14 15 |
# File 'lib/gpp/processor.rb', line 8 def initialize (in_, out, path, offset, defs = {}, trace = []) super(in_) @out = out @defs = defs.to_h @path = path @offset = offset @trace = trace end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
6 7 8 |
# File 'lib/gpp/processor.rb', line 6 def path @path end |
#trace ⇒ Object (readonly)
Returns the value of attribute trace.
6 7 8 |
# File 'lib/gpp/processor.rb', line 6 def trace @trace end |
Instance Method Details
#error(message) ⇒ Object
172 173 174 175 176 177 178 179 |
# File 'lib/gpp/processor.rb', line 172 def error () STDERR.puts "#{}" STDERR.puts " in #{path}:#{line}" trace.reverse.each do |path, line| STDERR.puts " #{path}:#{line}" end exit 1 end |
#indent_block(block, indent) ⇒ Object
48 49 50 |
# File 'lib/gpp/processor.rb', line 48 def indent_block (block, indent) block.gsub(/^\n/, "").gsub(/\n$/, "").gsub("\n", "\n#{indent}") end |
#line ⇒ Object
164 165 166 |
# File 'lib/gpp/processor.rb', line 164 def line @offset + string[0..pos - 1].count("\n") end |
#loopcat(into = "") ⇒ Object
17 18 19 20 21 22 23 24 |
# File 'lib/gpp/processor.rb', line 17 def loopcat (into = "") loop do val = yield break unless val into << val end into end |
#run(string, args, path, line) ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'lib/gpp/processor.rb', line 90 def run (string, args, path, line) trace = self.trace + [tracer] if args == nil self.class.new(string, s = "", path, line, @defs, trace).scan_all else self.class.new(string, s = "", path, line, @defs.merge(args.to_h), trace).scan_all end s end |
#run_macro(id) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/gpp/processor.rb', line 102 def run_macro (id) rpos = pos - id.length - 2 w = string[(string.rindex("\n", rpos) || 0) + 1..rpos][/[ \t]+/] res = if d = @defs[id] case d.type when :var run(d.body, {}, d.path, d.line) when :fun args = scan_args.map{|arg| Definition.new(:var, {}, run(arg, {}, path, line), path, line)} if d.args[-1] == "..." la = d.args.length - 1 args[la..-1] = Definition.new(:var, {}, args[la..-1].map(&:body).join(" "), args[la].path, args[la].line) end if args.length != d.args.length error "wrong argument count for #{id}: expected #{d.args.length} but got #{args.length}" end run(d.body, d.args.zip(args), d.path, d.line) end else error "undefined macro: #{id}" end indent_block(res, w) end |
#scan_all ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/gpp/processor.rb', line 143 def scan_all while !eos? @out << (scan(/[^#@]+/) || "") if scan(/#define\b/) scan_define scan(/\s+/) elsif scan(/#import\b/) scan_import scan(/\s+/) #elsif scan(/#(\w+)/) # error "undefined meta-macro: #{self[1]}" elsif scan(/@@/) @out << "@" elsif scan(/@(\.\.\.|\w+)/) @out << (run_macro(self[1]) || "") elsif s = scan(/./) @out << s end end end |
#scan_arg(bare = /\S+/) ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/gpp/processor.rb', line 57 def scan_arg ( = /\S+/) if scan(/{/) undent_block(scan_block()) elsif scan(/"/) scan_string() else scan() end end |
#scan_args ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/gpp/processor.rb', line 67 def scan_args if scan(/\(/) scan(/[ \t]+/) loopcat [scan_arg(/[^,)]*/)] do if scan(/\)/) nil elsif scan(/,/) scan(/[ \t]+/) scan_arg(/[^,)]*/) end end else loopcat [] do if scan(/(?=\n)/) nil else scan(/[ \t]+/) scan_arg end end end end |
#scan_block ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/gpp/processor.rb', line 26 def scan_block loopcat do if scan(/{/) "{" + scan_block + "}" elsif scan(/}/) nil else scan(/[^{}]+/) end end end |
#scan_define ⇒ Object
126 127 128 129 130 131 132 133 134 |
# File 'lib/gpp/processor.rb', line 126 def scan_define line = self.line name, *args, body = scan_args if args == [] @defs[name] = Definition.new(:var, nil, body, @path, line) else @defs[name] = Definition.new(:fun, args, body, @path, line) end end |
#scan_import ⇒ Object
136 137 138 139 140 141 |
# File 'lib/gpp/processor.rb', line 136 def scan_import () args = scan_args args.each do |arg| run File.read(arg), nil, arg, 1 end end |
#scan_string ⇒ Object
38 39 40 41 42 43 44 45 46 |
# File 'lib/gpp/processor.rb', line 38 def scan_string loopcat do if scan(/"/) nil else scan(/\\?.|[^"\\]/) end end end |
#tracer ⇒ Object
168 169 170 |
# File 'lib/gpp/processor.rb', line 168 def tracer [path, line] end |
#undent_block(block) ⇒ Object
52 53 54 55 |
# File 'lib/gpp/processor.rb', line 52 def undent_block (block) indent = block[/\A\n[ \t]+/] indent ? block.gsub(/#{indent}/, "\n") : block end |