309 lines
5.8 KiB
Crystal
309 lines
5.8 KiB
Crystal
require "./parser"
|
|
|
|
class Specs
|
|
class StringContainer
|
|
property value : String
|
|
|
|
def initialize(@value)
|
|
end
|
|
end
|
|
|
|
class LongStringContainer
|
|
property value : String
|
|
|
|
def initialize(@value)
|
|
end
|
|
end
|
|
|
|
class SectionContainer
|
|
property value : String
|
|
|
|
def initialize(@value)
|
|
end
|
|
end
|
|
|
|
class ArrayContainer
|
|
property value : Array(String)
|
|
|
|
def initialize(@value)
|
|
end
|
|
end
|
|
|
|
|
|
property assignments : Hash(String, StringContainer | LongStringContainer | SectionContainer | ArrayContainer)
|
|
|
|
def initialize
|
|
@assignments = Hash(String, StringContainer | LongStringContainer | SectionContainer | ArrayContainer).new
|
|
end
|
|
|
|
def parse_hashglob(tree)
|
|
# hashglob = hash hashglob | any hashglob | any | hash
|
|
str = String.build do |str|
|
|
case tree
|
|
when Pegasus::Generated::TerminalTree
|
|
str << tree.string
|
|
when Pegasus::Generated::NonterminalTree
|
|
tree.children.each do |it|
|
|
str << parse_hashglob it
|
|
end
|
|
end
|
|
end
|
|
|
|
str
|
|
end
|
|
|
|
def parse_freetext(tree)
|
|
# tabs hashglob cr freetext?
|
|
|
|
case tree
|
|
when Pegasus::Generated::TerminalTree
|
|
raise "freetext: should not be terminal"
|
|
when Pegasus::Generated::NonterminalTree
|
|
current_line = parse_hashglob tree.children[1]
|
|
current_line = current_line.lstrip(" ").rstrip(" ")
|
|
|
|
str = String.build do |str|
|
|
str << current_line
|
|
str << "\n"
|
|
if tree.children.size == 4
|
|
str << parse_freetext tree.children[3]
|
|
end
|
|
end
|
|
|
|
str
|
|
end
|
|
end
|
|
|
|
def parse_list_items(tree)
|
|
# tabs dash glob cr listitem? | tabs comment cr listitem
|
|
|
|
case tree
|
|
when Pegasus::Generated::TerminalTree
|
|
raise "parse_list_items: should not be terminal"
|
|
when Pegasus::Generated::NonterminalTree
|
|
|
|
if tree.children[1] == Pegasus::Generated::NonterminalTree
|
|
str = String.build do |str|
|
|
str << parse_list_items tree.children[3]
|
|
end
|
|
|
|
str
|
|
else
|
|
current_line = parse_glob tree.children[2]
|
|
current_line = current_line.lstrip(" ").rstrip(" ")
|
|
|
|
str = String.build do |str|
|
|
str << current_line
|
|
str << "\n"
|
|
if tree.children.size == 5
|
|
str << parse_list_items tree.children[4]
|
|
end
|
|
end
|
|
|
|
str
|
|
end
|
|
end
|
|
end
|
|
|
|
def parse_list(tree)
|
|
# string colon cr listitem
|
|
name = parse_string tree.children[0]
|
|
value = parse_list_items tree.children[3]
|
|
|
|
if name.nil?
|
|
return
|
|
end
|
|
|
|
if value.nil?
|
|
return
|
|
end
|
|
|
|
@assignments[name] = ArrayContainer.new value.split("\n")
|
|
end
|
|
|
|
def parse_freetextblock(tree)
|
|
# at multiplealphanum cr freetext
|
|
|
|
name = parse_multiplealphanum tree.children[1]
|
|
value = parse_freetext tree.children[3]
|
|
|
|
if name.nil?
|
|
return
|
|
end
|
|
|
|
if value.nil?
|
|
return
|
|
end
|
|
|
|
@assignments[name] = SectionContainer.new value
|
|
end
|
|
|
|
def parse_glob (tree)
|
|
# glob = any glob | any
|
|
str = String.build do |str|
|
|
case tree
|
|
when Pegasus::Generated::TerminalTree
|
|
str << tree.string
|
|
when Pegasus::Generated::NonterminalTree
|
|
tree.children.each do |it|
|
|
str << parse_glob it
|
|
end
|
|
end
|
|
end
|
|
|
|
str
|
|
end
|
|
|
|
def parse_multiplealphanum(tree)
|
|
# multiplealphanum = alphanum multiplealphanum?
|
|
# alphanum = string | numbers
|
|
str = String.build do |str|
|
|
case tree
|
|
when Pegasus::Generated::TerminalTree
|
|
str << tree.string
|
|
when Pegasus::Generated::NonterminalTree
|
|
tree.children.each do |it|
|
|
str << parse_multiplealphanum it
|
|
end
|
|
end
|
|
end
|
|
|
|
str
|
|
end
|
|
|
|
def parse_string(tree)
|
|
case tree
|
|
when Pegasus::Generated::TerminalTree
|
|
return tree.string
|
|
else
|
|
raise "this should be a string but this is non terminal"
|
|
end
|
|
end
|
|
|
|
def parse_assignment(tree)
|
|
# string colon glob
|
|
name = parse_string tree.children[0]
|
|
value = parse_glob tree.children[2]
|
|
value = value.lstrip(" ").rstrip(" ")
|
|
|
|
if name.nil?
|
|
return
|
|
end
|
|
|
|
if value.nil?
|
|
return
|
|
end
|
|
|
|
@assignments[name] = StringContainer.new value
|
|
end
|
|
|
|
def parse_tree(tree)
|
|
case tree
|
|
when Pegasus::Generated::TerminalTree
|
|
# do nothing
|
|
when Pegasus::Generated::NonterminalTree
|
|
case tree.name
|
|
when "freetextblock" ; parse_freetextblock tree
|
|
when "freetext" ; parse_freetext tree
|
|
when "assignment" ; parse_assignment tree
|
|
when "list" ; parse_list tree
|
|
when "comment"
|
|
# do nothing
|
|
else
|
|
tree.children.each { |it| parse_tree(it) }
|
|
end
|
|
end
|
|
end
|
|
|
|
def replace_string_obj (v : StringContainer | SectionContainer | LongStringContainer)
|
|
reg = /%\{([^}]*)\}/
|
|
|
|
|
|
value = v.value
|
|
|
|
while value =~ reg
|
|
|
|
x = reg.match(value)
|
|
unless x.nil?
|
|
var = x.captures()
|
|
|
|
replacement_object = @assignments[var[0]]
|
|
case replacement_object
|
|
when StringContainer
|
|
replacement_value = replacement_object.value
|
|
value = value.gsub "%{#{var[0]}}", "#{replacement_value}"
|
|
end
|
|
end
|
|
|
|
v.value = value
|
|
|
|
value = v.value
|
|
end
|
|
end
|
|
|
|
def replace_array_obj (v : ArrayContainer)
|
|
reg = /%\{([^}]*)\}/
|
|
|
|
str_array = v.value
|
|
|
|
newarray = Array(String).new
|
|
|
|
str_array.each do |value|
|
|
tmp = value
|
|
while tmp =~ reg
|
|
|
|
x = reg.match(tmp)
|
|
unless x.nil?
|
|
var = x.captures()
|
|
|
|
replacement_object = @assignments[var[0]]
|
|
case replacement_object
|
|
when StringContainer
|
|
replacement_value = replacement_object.value
|
|
tmp = tmp.gsub "%{#{var[0]}}", "#{replacement_value}"
|
|
end
|
|
end
|
|
end
|
|
|
|
newarray.push tmp
|
|
end
|
|
|
|
v.value = newarray
|
|
end
|
|
|
|
def rewrite
|
|
# replaces all occurences of %{variable} by the content of @assignments[variable]
|
|
@assignments.map do |k, v|
|
|
case v
|
|
when StringContainer
|
|
replace_string_obj v
|
|
when SectionContainer
|
|
replace_string_obj v
|
|
when LongStringContainer
|
|
replace_string_obj v
|
|
when ArrayContainer
|
|
replace_array_obj v
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.parse(file_name : String) : Specs | Nil
|
|
begin
|
|
content = File.read(file_name)
|
|
content = content.rchop
|
|
|
|
specs = Specs.new
|
|
tree = Pegasus::Generated.process(content)
|
|
specs.parse_tree tree
|
|
|
|
specs.rewrite
|
|
|
|
specs
|
|
rescue e
|
|
puts "Exception: #{e}"
|
|
|
|
nil
|
|
end
|
|
end
|
|
end
|