class Mustache::Parser

The Parser is responsible for taking a string template and converting it into an array of tokens and, really, expressions. It raises SyntaxError if there is anything it doesn't understand and knows which sigil corresponds to which tag type.

For example, given this template:

Hi {{thing}}!

Run through the Parser we'll get these tokens:

[:multi,
  [:static, "Hi "],
  [:mustache, :etag, "thing"],
  [:static, "!\n"]]

You can see the array of tokens for any template with the mustache(1) command line tool:

$ mustache --tokens test.mustache
[:multi, [:static, "Hi "], [:mustache, :etag, "thing"], [:static, "!\n"]]

Constants

ALLOWED_CONTENT

The content allowed in a tag name.

ANY_CONTENT

These types of tags allow any content, the rest only allow ALLOWED_CONTENT.

SKIP_WHITESPACE

After these types of tags, all whitespace until the end of the line will be skipped if they are the first (and only) non-whitespace content on the line.

VALID_TYPES

The sigil types which are valid after an opening `{{`

Attributes

ctag[R]
otag[R]

Public Class Methods

add_type(*types, &block) click to toggle source

Add a supported sigil type (with optional aliases) to the Parser.

Requires a block, which will be sent the following parameters:

  • content - The raw content of the tag

  • fetch- A mustache context fetch expression for the content

  • padding - Indentation whitespace from the currently-parsed line

  • pre_match_position - Location of the scanner before a match was made

The provided block will be evaluated against the current instance of Parser, and may append to the Parser's @result as needed.

# File lib/mustache/parser.rb, line 65
def self.add_type(*types, &block)
  types = types.map(&:to_s)
  type, *aliases = types
  method_name = "scan_tag_#{type}".to_sym
  define_method(method_name, &block)
  aliases.each { |a| alias_method "scan_tag_#{a}", method_name }
  types.each { |t| VALID_TYPES << t unless VALID_TYPES.include?(t) }
  @valid_types = nil
end
new(options = {}) click to toggle source

Accepts an options hash which does nothing but may be used in the future.

# File lib/mustache/parser.rb, line 91
def initialize(options = {})
  @options = options
  @option_inline_partials_at_compile_time = options[:inline_partials_at_compile_time]
  if @option_inline_partials_at_compile_time
    @partial_resolver = options[:partial_resolver]
    raise ArgumentError.new "Missing or invalid partial_resolver" unless @partial_resolver.respond_to? :call
  end

  # Initialize default tags
  self.otag ||= '{{'
  self.ctag ||= '}}'
end
valid_types() click to toggle source
# File lib/mustache/parser.rb, line 50
def self.valid_types
  @valid_types ||= Regexp.new(VALID_TYPES.map { |t| Regexp.escape(t) }.join('|') )
end

Public Instance Methods

compile(template) click to toggle source

Given a string template, returns an array of tokens.

# File lib/mustache/parser.rb, line 119
def compile(template)
  @encoding = nil

  if template.respond_to?(:encoding)
    @encoding = template.encoding
    template = template.dup.force_encoding("BINARY")
  end

  # Keeps information about opened sections.
  @sections = []
  @result = [:multi]
  @scanner = StringScanner.new(template)

  # Scan until the end of the template.
  until @scanner.eos?
    scan_tags || scan_text
  end

  unless @sections.empty?
    # We have parsed the whole file, but there's still opened sections.
    type, pos, _ = @sections.pop
    error "Unclosed section #{type.inspect}", pos
  end

  @result
end
ctag=(value) click to toggle source

The closing tag delimiter. This too may be changed at runtime.

# File lib/mustache/parser.rb, line 113
def ctag=(value)
  @ctag_regex = regexp value
  @ctag = value
end
otag=(value) click to toggle source

The opening tag delimiter. This may be changed at runtime.

# File lib/mustache/parser.rb, line 105
def otag=(value)
  regex = regexp value
  @otag_regex     = /([ \t]*)?#{regex}/
  @otag_not_regex = /(^[ \t]*)?#{regex}/
  @otag = value
end