class SimpleTemplates::Parser

Parsing the SimpleTemplate means verifying that there are no malformed tags, and all tags are in the ‘allowed’ list.

Constants

Error

A Struct that takes a message to create a parser error

FRIENDLY_TAG_NAMES

A static Hash with the meaning of each tag name @return [Hash{Symbol => String}]

Attributes

allowed_placeholders[R]
tokens[R]
unescapes[R]

Public Class Methods

new(unescapes, tokens, allowed_placeholders) click to toggle source

Initializes a new Parser. @param unescapes [SimpleTemplates::Unescapes] a Unescapes object @param tokens <Array> a list of tokens @param allowed_placeholders <Array> a list with allowed

placeholders if is left as nil, then all placeholders are permitted
# File lib/simple_templates/parser.rb, line 26
def initialize(unescapes, tokens, allowed_placeholders)
  @unescapes            = unescapes.clone.freeze
  @tokens               = tokens.clone.freeze

  @allowed_placeholders = allowed_placeholders &&
    allowed_placeholders.clone.freeze
end

Public Instance Methods

parse() click to toggle source

Returns a Parser::Result containing the parsed AST nodes, the errors found when parsing and the remaining tokens that have not been parsed. @return [Array<Array<SimpleTemplates::AST::Node>,

Array<SimpleTemplates::Parser::Error>,
Array<SimpleTemplates::Lexer::Token>>]
# File lib/simple_templates/parser.rb, line 39
def parse
  ast    = []
  errors = []

  tok_stream = tokens.dup

  while tok_stream.any?
    parser = detect_parser(tok_stream)

    if parser.nil?
      errors <<
      Error.new("Encountered unexpected token in stream " +
                "(#{FRIENDLY_TAG_NAMES[tok_stream.first.type]}), but expected to " +
                "see one of the following types: #{acceptable_starting_tokens}.")
      tok_stream = []

    else
      template, errors_result, remaining_tokens = parser.parse

      if remaining_tokens.nil?
        raise "Parser #{parser.class} shouldn't return nil remaining " +
              "tokens (should be an Array), please report this bug."
      end

      if errors_result.empty?
        tok_stream = remaining_tokens
        ast        = ast.concat(template)

      else
        # Once we get a syntax error, we can't really determine if anything
        # else is broken syntactically, so return with the first Error.
        tok_stream = []
        errors.concat(errors_result)

      end
    end
  end

  errors.concat(invalid_node_content_errors(ast))

  [ast, errors, tok_stream]
end

Private Instance Methods

acceptable_starting_tokens() click to toggle source
# File lib/simple_templates/parser.rb, line 93
def acceptable_starting_tokens
  (Placeholder::STARTING_TOKENS | Text::STARTING_TOKENS).map do |tag|
    FRIENDLY_TAG_NAMES[tag]
  end.join(', ')
end
detect_parser(tokens_to_parse) click to toggle source
# File lib/simple_templates/parser.rb, line 99
def detect_parser(tokens_to_parse)
  toks = tokens_to_parse.clone.freeze

  [Placeholder, Text].each do |parser_class|
    if parser_class.applicable?(toks)
      return parser_class.new(unescapes, toks, allowed_placeholders)
    end
  end

  nil
end
invalid_node_content_errors(ast) click to toggle source
# File lib/simple_templates/parser.rb, line 86
def invalid_node_content_errors(ast)
  ast.reject(&:allowed?).map do |node|
    Error.new("Invalid #{node.name} with contents, '#{node.contents}' " +
              "found starting at position #{node.pos}.")
  end
end