class VueCompiler::Parser

Constants

DIRECTIVE_RE

Public Class Methods

new(tokens) click to toggle source

@param tokens {Array}

# File lib/vue_component_compiler/parser.rb, line 6
def initialize(tokens)
  @tokens = tokens
  @comments = []
end

Public Instance Methods

eat() click to toggle source
# File lib/vue_component_compiler/parser.rb, line 69
def eat
  @tokens.shift
end
expect(token) click to toggle source
# File lib/vue_component_compiler/parser.rb, line 73
def expect(token)
  if @tokens[0].instance_of?(token)
    @tokens.shift
  else
    raise Exception.new("Found token type #{@tokens[0].class}, expecting #{token}")
  end
end
parse() click to toggle source
# File lib/vue_component_compiler/parser.rb, line 11
def parse
  root_children = []

  until @tokens[0].instance_of?(Token::EndOfSource)
    token = @tokens[0]
    if token.instance_of?(Token::ScriptBlock)
      token = self.eat
      root_children << Node::ScriptBlock.new(
        token.content,
        token.lang
      )
      next
    elsif token.instance_of?(Token::StyleBlock)
      token = self.eat
      root_children << Node::StyleBlock.new(
        token.content,
        token.lang,
        token.scoped
      )
      next
    elsif token.instance_of?(Token::CommentStart)
      self.parse_comment
      next
    elsif token.instance_of?(Token::CustomBlock)
      root_children << token
      self.eat
      next
    end

    self.expect(Token::OpenTagStart)
    self.expect(Token::OpenTagName)
    self.expect(Token::TagEnd)

    while token.instance_of?(Token::CommentStart)
      self.parse_comment
    end

    if @tokens[0].instance_of?(Token::OpenTagStart)
      element = Node::Element.new(
        'template',
        [],
        [self.parse_element]
      )
      root_children << Node::TemplateBlock.new(element)
    end

    while token.instance_of?(Token::CommentStart)
      self.parse_comment
    end

    self.expect(Token::ClosingTagStart)
    self.expect(Token::ClosingTagName)
    self.expect(Token::TagEnd)
  end

  Node::Program.new(root_children, @comments)
end
parse_attribute() click to toggle source
# File lib/vue_component_compiler/parser.rb, line 109
def parse_attribute
  name = self.eat.name
  value = nil

  if @tokens[0].instance_of?(Token::AttributeValue)
    value = self.eat.value
  end

  if name.start_with?(':')
    if value
      Node::Attribute.new(
        Node::Directive.new('bind', name[1..-1], true),
        Node::AttributeValue.new(value)
      )
    else
      raise Exception.new('Missing value of `v-bind` directive.')
    end
  elsif name.start_with?('@')
    if value
      Node::Attribute.new(
        Node::Directive.new('on', name[1..-1], true),
        Node::AttributeValue.new(value)
      )
    else
      raise Exception.new('Missing value of `v-on` directive.')
    end
  elsif name.start_with?('v-')
    matched = name.match(DIRECTIVE_RE)
    name = matched[1]
    argument = matched[2]
    Node::Attribute.new(
      Node::Directive.new(name, argument),
      Node::AttributeValue.new(value)
    )
  else
    Node::Attribute.new(
      Node::AttributeName.new(name),
      Node::AttributeValue.new(value)
    )
  end
end
parse_comment() click to toggle source
# File lib/vue_component_compiler/parser.rb, line 81
def parse_comment
  self.eat
  @comments << Node::Comment.new(self.eat.value)
  self.eat
end
parse_element() click to toggle source
# File lib/vue_component_compiler/parser.rb, line 87
def parse_element
  self.expect(Token::OpenTagStart)
  tag_name = self.expect(Token::OpenTagName).name
  attributes = []

  while @tokens[0].instance_of?(Token::AttributeName)
    attributes << self.parse_attribute
  end

  if self.eat.instance_of?(Token::SelfClosingTag)
    return Node::Element.new(tag_name, attributes)
  end

  children = self.parse_element_children

  self.expect(Token::ClosingTagStart)
  self.expect(Token::ClosingTagName)
  self.expect(Token::TagEnd)

  Node::Element.new(tag_name, attributes, children)
end
parse_element_children() click to toggle source
# File lib/vue_component_compiler/parser.rb, line 151
def parse_element_children
  children = []

  until @tokens[0].instance_of?(Token::ClosingTagStart)
    token = @tokens[0]

    if token.instance_of?(Token::OpenTagStart)
      children << self.parse_element
    elsif token.instance_of?(Token::Text)
      children << Node::Text.new(self.eat.content)
    elsif token.instance_of?(Token::InterpolationStart)
      children << self.parse_interpolation
    elsif token.instance_of?(Token::CommentStart)
      self.parse_comment
    else
      raise Exception.new('Unknown token type.')
    end
  end

  children
end
parse_interpolation() click to toggle source
# File lib/vue_component_compiler/parser.rb, line 173
def parse_interpolation
  self.eat
  interpolation = Node::Interpolation.new(self.eat.expression)
  self.eat

  interpolation
end