3
0

Multi-lines + exceptions give the erroneous line.

This commit is contained in:
Philippe Pittoli 2021-03-01 16:13:22 +01:00
parent feeed2306c
commit 97e33c576a
2 changed files with 41 additions and 7 deletions

View File

@ -1,5 +1,5 @@
name: specparser name: specparser
version: 0.5.0 version: 0.5.1
authors: authors:
- Philippe Pittoli <karchnu@karchnu.fr> - Philippe Pittoli <karchnu@karchnu.fr>

View File

@ -81,13 +81,14 @@ class SpecParser
property assignments : Hash(String, StringContainer | LongStringContainer | ArrayContainer) property assignments : Hash(String, StringContainer | LongStringContainer | ArrayContainer)
property sections : Array(Section) property sections : Array(Section)
property current_line_number = 0
def initialize def initialize
@assignments = Hash(String, StringContainer | LongStringContainer | ArrayContainer).new @assignments = Hash(String, StringContainer | LongStringContainer | ArrayContainer).new
@sections = Array(Section).new @sections = Array(Section).new
end end
def parse_assignment (line : String) def parse_assignment (line : String, content : Array(String))
# puts "simple assignment: #{line}" # puts "simple assignment: #{line}"
name = /([a-zA-Z][a-zA-Z0-9-_]*):/.match(line).try &.[1] name = /([a-zA-Z][a-zA-Z0-9-_]*):/.match(line).try &.[1]
@ -100,6 +101,9 @@ class SpecParser
return return
end end
# In case the content is over several lines.
value = grab_content content, value
@assignments[name] = StringContainer.new value.lstrip(" ").rstrip(" ") @assignments[name] = StringContainer.new value.lstrip(" ").rstrip(" ")
end end
@ -110,14 +114,17 @@ class SpecParser
list = Array(String).new list = Array(String).new
while line = content.shift? while line = content.shift?
@current_line_number += 1
case line case line
when /^[ \t]*(#.*)?$/ when /^[ \t]*(#.*)?$/
# puts "blank line or comment, still in a list" # puts "blank line or comment, still in a list"
when /^[ \t]+-([^#]*)/ when /^[ \t]+-([^#]*)/
# puts "line content: #{$~[1]}" # puts "line content: #{$~[1]}"
list.push $~[1].lstrip(" ").rstrip(" ") current_line = $~[1].lstrip(" ")
list.push grab_content(content, current_line)
else else
content.unshift line content.unshift line
@current_line_number -= 1
break break
end end
end end
@ -138,6 +145,7 @@ class SpecParser
value = String.build do |str| value = String.build do |str|
while line = content.shift? while line = content.shift?
@current_line_number += 1
case line case line
when /^[ \t]*(#.*)?$/ when /^[ \t]*(#.*)?$/
# puts "blank line or comment, still in a code block" # puts "blank line or comment, still in a code block"
@ -148,6 +156,7 @@ class SpecParser
str << "#{$~[1]}\n" str << "#{$~[1]}\n"
else else
content.unshift line content.unshift line
@current_line_number -= 1
break break
end end
end end
@ -178,6 +187,7 @@ class SpecParser
end end
while line = content.shift? while line = content.shift?
@current_line_number += 1
case line case line
when /^[ \t]*#.*$/ when /^[ \t]*#.*$/
# puts "blank line or comment, still in a section" # puts "blank line or comment, still in a section"
@ -194,6 +204,7 @@ class SpecParser
codeblockvalue = String.build do |str| codeblockvalue = String.build do |str|
while line = content.shift? while line = content.shift?
@current_line_number += 1
case line case line
when /^[ \t]*#.*?$/ when /^[ \t]*#.*?$/
# puts "blank line or comment, still in a free text in a section" # puts "blank line or comment, still in a free text in a section"
@ -202,6 +213,7 @@ class SpecParser
str << "#{$~[1]}\n" str << "#{$~[1]}\n"
else else
content.unshift line content.unshift line
@current_line_number -= 1
break break
end end
end end
@ -216,6 +228,7 @@ class SpecParser
list = Array(String).new list = Array(String).new
while line = content.shift? while line = content.shift?
@current_line_number += 1
case line case line
when /^[ \t]*#.*?$/ when /^[ \t]*#.*?$/
# puts "blank line or comment, still in a list in a section" # puts "blank line or comment, still in a list in a section"
@ -225,6 +238,7 @@ class SpecParser
list.push lcontent list.push lcontent
else else
content.unshift line content.unshift line
@current_line_number -= 1
break break
end end
end end
@ -236,6 +250,7 @@ class SpecParser
section.content[lname] = ArrayContainer.new list section.content[lname] = ArrayContainer.new list
else else
content.unshift line content.unshift line
@current_line_number -= 1
break break
end end
end end
@ -243,13 +258,32 @@ class SpecParser
sections.push section sections.push section
end end
# Remove \n when line ends with a backslash.
def grab_content(content : Array(String), current_value : String)
while current_value =~ /\\$/
# Remove trailing backslash
current_value = current_value.rstrip "\\"
nl = content.shift?
if nl
@current_line_number += 1
current_value += nl.lstrip
else
raise Exception.new "last line is ending with a backslash"
end
end
current_value
end
def parse_lines(content : Array(String)) def parse_lines(content : Array(String))
while line = content.shift? while line = content.shift?
@current_line_number += 1
case line case line
when /^[a-zA-Z][a-zA-Z0-9-_]*:[ \t]*([#].*)?$/ when /^[a-zA-Z][a-zA-Z0-9-_]*:[ \t]*([#].*)?$/
parse_list line, content parse_list line, content
when /^[a-zA-Z][a-zA-Z0-9-_]*:[ \t]+[^#]+/ when /^[a-zA-Z][a-zA-Z0-9-_]*:[ \t]+[^#]+/
parse_assignment line parse_assignment line, content
when /^[@][a-zA-Z][a-zA-Z0-9-_]*[ \t]*([#].*)?/ when /^[@][a-zA-Z][a-zA-Z0-9-_]*[ \t]*([#].*)?/
parse_code_block line, content parse_code_block line, content
when /^[%][a-zA-Z][a-zA-Z0-9-_]*[ \t]*([#].*)?/ when /^[%][a-zA-Z][a-zA-Z0-9-_]*[ \t]*([#].*)?/
@ -259,7 +293,7 @@ class SpecParser
when /^[ \t]+$/ when /^[ \t]+$/
# puts "empty line" # puts "empty line"
when /^[ \t]+[^ \t#]/ when /^[ \t]+[^ \t#]/
raise "line starting with spaces or a tabulation outside a list or a section: should not happen" raise Exception.new "line #{@current_line_number}: line starting with spaces or a tabulation outside a list or a section: should not happen"
end end
end end
end end
@ -393,6 +427,6 @@ class SpecParser
specs specs
rescue e rescue e
raise Exception.new "unexpected parser error: #{e}" raise Exception.new "unexpected parser error: #{e}, current line #{specs.not_nil!.current_line_number}"
end end
end end