marrub
/
Lithia
Archived
1
0
Fork 0
This repository has been archived on 2023-06-17. You can view files and clone it, but cannot push or open issues/pull-requests.
Lithia/compilefs.rb

118 lines
3.1 KiB
Ruby

#!/usr/bin/env ruby
## Copyright © 2017 Graham Sanderson, all rights reserved.
## CompileFS: Formatted text → LANGUAGE processor.
def escape text
text.gsub(/((?<m>\\)(?!c))|(?<m>")/, "\\\\\\k<m>").gsub(/\n/, "\\n")
end
def split_arg text, sp
text.split(sp, 2).map {|s| s.strip}
end
def single_line outf, out, set
outf.write "\"#{out}\" = \"#{escape set}\";\n"
end
def comment outf, arg
outf.write "\n//#{arg}\n"
end
def buf_lines outf, type, buf
buf.pop if buf.last.chomp.empty?
case type
when :just
outf.write(buf.each.with_index.inject("") do |sum, (s, i)|
if i < buf.size-1 then sum + " \"#{escape s.chomp}\\n\"\n"
else sum + " \"#{escape s.chomp}\";\n" end
end)
when :conc
buf = [*buf, "\n"].each_cons(2).map do |s, n|
if s == "\n" then "\n\n"
elsif n == "\n" then s.chomp
else s.chomp + " " end
end
outf.write(buf.each.with_index.inject("") do |sum, (s, i)|
if i < buf.size-1 then sum + " \"#{escape s}\"\n"
else sum + " \"#{escape s.chomp}\";\n" end
end)
end
end
def parse_file outf, fp
wr, buf = nil, nil
for ln in fp
type, arg = ln[0..1], ln.chomp[2..-1]
case type
when "##"
buf_lines outf, wr, buf and wr = nil if wr
comment outf, arg
when "=="
buf_lines outf, wr, buf and wr = nil if wr
out, set = split_arg arg, "|"
single_line outf, out, set
when "%%"
buf_lines outf, wr, buf if wr
wr, buf = :just, []
outf.write "\"#{arg.strip}\" =\n"
when "@@"
buf_lines outf, wr, buf if wr
wr, buf = :conc, []
outf.write "\"#{arg.strip}\" =\n"
else
buf << ln if wr
end
end
buf_lines outf, wr, buf if wr
end
def procdir inf, type, arg
case type
when "comment"
comment inf[:f], " " + arg
when "put data"
set, out = split_arg arg, "->"
single_line inf[:f], out, set
when "put file"
fnam, out = split_arg arg, "->"
inf[:f].write "\"#{out}\" =\n"
comment inf[:f], " " + fnam
buf_lines inf[:f], :just, open(fnam, "rt").read.chomp.lines
when "parse file"
parse_file inf[:f], open(arg, "rt")
end
end
def procfdr inf, type, arg
case type
when "in"
if (type, arg = split_arg arg, " ") and type == "directory"
inf[:d] = arg
elsif type == "file"
inf[:f] = open("#{inf[:d]}/#{arg}", "wb")
inf[:f].write "// This file was generated by compilefs.\n" +
"// Edit only if you aren't going to recompile.\n" +
"[enu default]\n\n"
end
when "include"
run_file open(arg, "rt"), inf
end
end
def run_file fp, inf = nil
inf = {f: nil, d: nil} unless inf
for ln in fp
if (type, arg = split_arg ln, ":") and arg
procdir inf, type, arg
elsif (type, arg = split_arg ln, " ") and arg
procfdr inf, type, arg
end
end
end
for arg in ARGV
run_file open(arg, "rt")
end
## EOF