lib/faml/parser.rb in faml-0.2.6 vs lib/faml/parser.rb in faml-0.2.7

- old
+ new

@@ -16,11 +16,11 @@ end def call(template_str) @ast = Ast::Root.new @stack = [] - @line_parser = LineParser.new(template_str) + @line_parser = LineParser.new(@filename, template_str) @indent_tracker = IndentTracker.new(on_enter: method(:indent_enter), on_leave: method(:indent_leave)) @filter_parser = FilterParser.new(@indent_tracker) while @line_parser.has_next? line = @line_parser.next_line @@ -61,16 +61,16 @@ def parse_line(line) text, indent = @indent_tracker.process(line, @line_parser.lineno) if text.empty? - @ast << Ast::Empty.new + @ast << create_node(Ast::Empty) return end if @ast.is_a?(Ast::HamlComment) - @ast << Ast::Text.new(text) + @ast << create_node(Ast::Text) { |t| t.text = text } return end case text[0] when ESCAPE_PREFIX @@ -99,16 +99,16 @@ parse_script(text) end end def parse_doctype(text) - @ast << Ast::Doctype.new(text[3 .. -1].strip) + @ast << create_node(Ast::Doctype) { |d| d.doctype = text[3 .. -1].strip } end def parse_comment(text) text = text[1, text.size-1].strip - comment = Ast::HtmlComment.new + comment = create_node(Ast::HtmlComment) comment.comment = text if text[0] == '[' comment.conditional, rest = parse_conditional_comment(text) text.replace(rest) end @@ -126,11 +126,11 @@ syntax_error!('Unmatched brackets in conditional comment') end end def parse_plain(text) - @ast << Ast::Text.new(text) + @ast << create_node(Ast::Text) { |t| t.text = text } end def parse_element(text) @ast << ElementParser.new(@line_parser).parse(text) end @@ -139,27 +139,28 @@ @ast << ScriptParser.new(@line_parser).parse(text) end def parse_silent_script(text) if text.start_with?('-#') - @ast << Ast::HamlComment.new + @ast << create_node(Ast::HamlComment) return end - script = text[/\A- *(.*)\z/, 1] - if script.empty? + node = create_node(Ast::SilentScript) + node.script = text[/\A- *(.*)\z/, 1] + if node.script.empty? syntax_error!("No Ruby code to evaluate") end - script += RubyMultiline.read(@line_parser, script) - @ast << Ast::SilentScript.new([], script) + node.script += RubyMultiline.read(@line_parser, node.script) + @ast << node end def parse_filter(text) filter_name = text[/\A#{FILTER_PREFIX}(\w+)\z/, 1] unless filter_name syntax_error!("Invalid filter name: #{text}") end - @filter_parser.start(filter_name) + @filter_parser.start(filter_name, @line_parser.filename, @line_parser.lineno) end def indent_enter(_, text) empty_lines = [] while @ast.children.last.is_a?(Ast::Empty) @@ -211,8 +212,18 @@ MID_BLOCK_KEYWORDS.include?(block_keyword(text)) end def syntax_error!(message) raise SyntaxError.new(message, @line_parser.lineno) + end + + def create_node(klass, &block) + klass.new.tap do |node| + node.filename = @line_parser.filename + node.lineno = @line_parser.lineno + if block + block.call(node) + end + end end end end