class Aspen::Parser

Public Instance Methods

parse() click to toggle source

narrative = statements; statements = { statement } statement = COMMENT | CUSTOM_STATEMENT | list_statement | vanilla_statement

# Variant 1. TODO: Variant 2 list_statement = node, edge, [ list_label ], START_LIST, list_items, END_LIST list_label = OPEN_PARENS, LABEL, CLOSE_PARENS list_items = { list_item } list_item = BULLET, CONTENT, [ list_item_label ] list_item_label = OPEN_PARENS, LABEL, CLOSE_PARENS vanilla_statement = node | node, edge, node, { END_STATEMENT } node = node_short_form | node_grouped_form | node_cypher_form node_short_form = OPEN_PARENS, CONTENT, CLOSE_PARENS node_grouped_form = OPEN_PARENS, { CONTENT, [ COMMA ] }, CLOSE_PARENS node_cypher_form = OPEN_PARENS, LABEL, OPEN_BRACES, { IDENTIFIER, literal, [ COMMA ] }, CLOSE_BRACES literal = STRING | NUMBER edge = OPEN_BRACKETS, CONTENT, CLOSE_BRACKETS

# File lib/aspen/parser.rb, line 28
def parse
  Aspen::AST::Nodes::Narrative.new(parse_statements)
end
Also aliased as: parse_narrative
parse_comment() click to toggle source
# File lib/aspen/parser.rb, line 53
def parse_comment
  if comment = expect(:COMMENT)
    Aspen::AST::Nodes::Comment.new(comment.first.last)
  end
end
parse_custom_statement() click to toggle source
# File lib/aspen/parser.rb, line 59
def parse_custom_statement
  if content = expect(:CUSTOM_GRAMMAR_STATEMENT)
    # FIXME: Why does this need a #first and a #last?
    # Seems unnecessarily nested. Maybe this happened in the lexer.
    Aspen::AST::Nodes::CustomStatement.new(content.first.last)
  end
end
parse_edge() click to toggle source
# File lib/aspen/parser.rb, line 170
def parse_edge
  if (_, content, _ = expect(:OPEN_BRACKETS, :CONTENT, :CLOSE_BRACKETS))
    Aspen::AST::Nodes::Edge.new(content.last)
  end
end
parse_list_item() click to toggle source
# File lib/aspen/parser.rb, line 100
def parse_list_item
  node = nil
  if (_, content = expect(:BULLET, :CONTENT))
    node = Aspen::AST::Nodes::Node.new(attribute: content.last)
  end
  if (label = parse_list_item_label)
    node.label = label
  end
  return node
end
parse_list_item_label() click to toggle source
# File lib/aspen/parser.rb, line 111
def parse_list_item_label
  if (_, item_label, _  = expect(:OPEN_PARENS, :CONTENT, :CLOSE_PARENS))
    # If singularizing should be conditional, we need to introduce the env in the parser.
    return item_label.last
  end
end
parse_list_items() click to toggle source
# File lib/aspen/parser.rb, line 90
def parse_list_items
  if need(:START_LIST)
    results = []
    while target = parse_list_item
      results << target
    end
    results
  end
end
parse_list_label() click to toggle source
# File lib/aspen/parser.rb, line 83
def parse_list_label
  if (_, plural_label, _  = expect(:OPEN_PARENS, :CONTENT, :CLOSE_PARENS))
    # If singularizing should be conditional, we need to introduce the env in the parser.
    return plural_label.last.singularize
  end
end
parse_list_statement() click to toggle source
# File lib/aspen/parser.rb, line 67
def parse_list_statement
  if expect(:PREPARE_START_LIST)
    origin  = parse_node
    edge    = parse_edge
    label   = parse_list_label
    targets = parse_list_items
    expect(:END_LIST)
    targets.map do |target|
      # puts "TARGET #{target.attribute.content.inner_content} had label #{target.label.content.inner_content.inspect}"
      target.label = label if target.label.content.inner_content.nil?
      # puts "TARGET #{target.attribute.content.inner_content} has label #{target.label.content.inner_content.inspect}"
      Aspen::AST::Nodes::Statement.new(origin: origin, edge: edge, target: target)
    end
  end
end
parse_literal() click to toggle source
# File lib/aspen/parser.rb, line 166
def parse_literal
  raise NotImplementedError, "#parse_literal not yet implemented"
end
parse_narrative()
Alias for: parse
parse_node() click to toggle source
# File lib/aspen/parser.rb, line 135
def parse_node
  # parse_node_cypher_form ||
  parse_node_grouped_form || parse_node_short_form
end
parse_node_cypher_form() click to toggle source

This complicates things greatly. Can we skip this for now, by rewriting the tests to get rid of this case, and come back to it?

# File lib/aspen/parser.rb, line 160
def parse_node_cypher_form
  if (_, label, _, content, _ = expect(:OPEN_PARENS, :CONTENT, :SEPARATOR, :CONTENT, :CLOSE_PARENS))
    Aspen::AST::Nodes::Node.new(content: content.last, label: label.last)
  end
end
parse_node_grouped_form() click to toggle source
# File lib/aspen/parser.rb, line 140
def parse_node_grouped_form
  if (_, label, sep, content, _ = expect(:OPEN_PARENS, :LABEL, :SEPARATOR, :CONTENT, :CLOSE_PARENS))
    Aspen::AST::Nodes::Node.new(
      attribute: content.last,
      label: label.last
    )
  end
end
parse_node_labeled_form() click to toggle source
# File lib/aspen/parser.rb, line 119
def parse_node_labeled_form
  raise NotImplementedError, "#parse_node_labeled_form not yet implemented"
end
parse_node_short_form() click to toggle source
# File lib/aspen/parser.rb, line 149
def parse_node_short_form
  # Terminal instructions require a "need"
  _, content, _ = need(:OPEN_PARENS, :CONTENT, :CLOSE_PARENS)
  Aspen::AST::Nodes::Node.new(
    attribute: content.last,
    label: nil
  )
end
parse_statement() click to toggle source
# File lib/aspen/parser.rb, line 46
def parse_statement
  parse_comment           ||
  parse_custom_statement  ||
  parse_list_statement    ||
  parse_vanilla_statement
end
parse_statements() click to toggle source
# File lib/aspen/parser.rb, line 34
def parse_statements
  results = []

  # Make sure this returns on empty
  while result = parse_statement
    results.push(*result)
    break if tokens[position].nil?
  end

  results
end
parse_vanilla_statement() click to toggle source
# File lib/aspen/parser.rb, line 123
def parse_vanilla_statement
  # TODO: Might benefit from a condition when doing non-vanilla statements?
  origin = parse_node
  edge   = parse_edge
  target = parse_node

  # SMELL: Nil check
  advance if peek && peek.first == :END_STATEMENT

  Aspen::AST::Nodes::Statement.new(origin: origin, edge: edge, target: target)
end