module Parser

Constants

BinaryOps
UnaryOps

Public Class Methods

parse(tokens) click to toggle source
# File lib/special-giggle/parser.rb, line 72
def self.parse(tokens)
  head = Token.new(:Program)
  statement = Array.new
  tokens.each do |token|
    if token.type == :SemiColon
      head.child << parse_statement(statement)
      statement = Array.new
    else
      statement << token
    end
  end
  head
end
parse_expression(tokens) click to toggle source
# File lib/special-giggle/parser.rb, line 30
def self.parse_expression(tokens)
  if tokens.length == 1 && tokens[0].type == :Variable
    Token.new(:Variable, tokens[0].string)
  elsif tokens.length == 1 && tokens[0].type == :Number
    Token.new(:Number, tokens[0].string.to_i)
  elsif tokens.length >= 3 && tokens[0].type == :LeftBracket && tokens[-1].type == :RightBracket
    Token.new(:Bracket, parse_expression(tokens[1...-1]))
  elsif tokens.length >= 2 && UnaryOps.include?(tokens[0].type)
    if tokens[0].type == :Minus
      Token.new(:Negative, parse_expression(tokens[1..-1]))
    else
      Token.new(tokens[0].type, parse_expression(tokens[1..-1]))
    end
  elsif tokens.length >= 3
    head, precedence = nil, 100
    (tokens.length-1).downto(0) do |index|
      token = tokens[index]
      next if index == 0 || index == tokens.length - 1 || !BinaryOps.include?(token.type)
      next unless precedence.nil? || precedence > BinaryOps[token.type]
      begin
        head = Token.new(token.type, parse_expression(tokens[0..index-1]), parse_expression(tokens[index+1..-1]))
        precedence = BinaryOps[token.type]
      rescue ParserError
      end
    end
    raise ParserError, "Syntax error in statement: #{tokens.map(&:string).join(' ')}" if head.nil?
    head
  else
    raise ParserError, "Syntax error in statement: #{tokens.map(&:string).join(' ')}"
  end
end
parse_statement(tokens) click to toggle source
# File lib/special-giggle/parser.rb, line 62
def self.parse_statement(tokens)
  if tokens.length >= 1 && tokens[0].type == :Print
    Token.new(:Print, parse_expression(tokens[1..-1]))
  elsif tokens.length >= 2 && tokens[0].type == :Variable && tokens[1].type == :Equal
    Token.new(:Move, Token.new(:Variable, tokens[0].string), parse_expression(tokens[2..-1]))
  else
    raise ParserError, "Syntax error in statement: #{tokens.map(&:string).join(' ')}"
  end
end