Class: TDRB::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/tdrb/parser.rb

Overview

Parser is the thing that does STUFF to a Token stream. What stuff? Well, that is defined by the handler lambdas.

Constant Summary collapse

IDLE =
lambda do |lexer|
  char = lexer.peek
  return if char == Token::EOF

  if whitespace?(char) || line_terminator?(char)
    lexer.next_char
    lexer.ignore

    return IDLE
  end

  case char
  when "@" then DATETIME
  when "#" then METAKEY
  when "*" then NOTE
  else
    VALUE
  end
end
DATETIME =
lambda do |lexer|
  lexer.take(["@", " "])
  lexer.ignore

  char = lexer.next_char

  while !line_terminator?(char) do
    char = lexer.next_char
  end

  lexer.rewind
  lexer.emit(Token::DATETIME)

  IDLE
end
METAKEY =
lambda do |lexer|
  lexer.take(["#", " "])
  lexer.ignore

  char = lexer.next_char

  while !colon_terminator?(char) do
    char = lexer.next_char
  end

  lexer.rewind
  lexer.emit(Token::METAKEY)

  METAVALUE
end
METAVALUE =
lambda do |lexer|
  lexer.take([":", " "])
  lexer.ignore

  char = lexer.next_char

  while !line_terminator?(char) do
    char = lexer.next_char
  end

  lexer.rewind
  lexer.emit(Token::METAVALUE)

  IDLE
end
MOVEMENT =

register_state :movement do end

lambda do |lexer|
  superset = false;

  char = lexer.next_char

  return if char == Token::EOF

  if char == "+"
    superset = true
    lexer.take([" "])
    lexer.ignore
    char = lexer.next_char
  end

  if char == "'"
    lexer.ignore
    char = lexer.next_char
  end

  while !colon_terminator?(char) do
    char = lexer.next_char
  end

  lexer.rewind

  if (superset)
    lexer.emit(Token::SUPERSET)
  else
    lexer.emit(Token::MOVEMENT)
  end

  lexer.take([":"])
  lexer.ignore

  IDLE
end
NOTE =
lambda do |lexer|
  lexer.take(["*", " "])
  lexer.ignore

  char = lexer.next_char

  while !line_terminator?(char) do
    char = lexer.next_char
  end

  lexer.rewind
  lexer.emit(Token::NOTE)

  IDLE
end
NUMBER =
lambda do |lexer|
  lexer.take(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."])

  # TODO: Configurable chars
  case lexer.peek
  when "f", "F" then lexer.emit(Token::FAIL)
  when "r", "R" then lexer.emit(Token::REP)
  when "s", "S" then lexer.emit(TokenType::SET)
  else
    lexer.emit(Token::LOAD)
  end

  lexer.take(["f", "F", "r", "R", "s", "S"])
  lexer.ignore

  IDLE
end
VALUE =
lambda do |lexer|
  char = lexer.next_char

  if char == "+" || char == "'"
    lexer.rewind
    return MOVEMENT
  end

  begin
    !!Integer(char)
    return NUMBER
  rescue ArgumentError, TypeError
    nil
  end

  if char != "b" && char != "B"
    lexer.rewind
    return MOVEMENT
  end

  peek = lexer.peek

  if peek != "w" && peek != "W"
    lexer.rewind
    MOVEMENT
  end

  while !whitespace?(char)
    char = lexer.next_char
  end

  lexer.rewind
  lexer.emit(Token::LOAD)

  IDLE
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(traindown:) ⇒ Parser

Returns a new instance of Parser.



9
10
11
12
# File 'lib/tdrb/parser.rb', line 9

def initialize(traindown:)
  @lexer     = Lexer.new(source: traindown, state: IDLE)
  @traindown = traindown
end

Instance Attribute Details

#lexerObject (readonly)

Returns the value of attribute lexer.



7
8
9
# File 'lib/tdrb/parser.rb', line 7

def lexer
  @lexer
end

#traindownObject (readonly)

Returns the value of attribute traindown.



7
8
9
# File 'lib/tdrb/parser.rb', line 7

def traindown
  @traindown
end

Class Method Details

.colon_terminator?(char) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/tdrb/parser.rb', line 20

def colon_terminator?(char)
  char == ":" || char == Token::EOF
end

.line_terminator?(char) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
27
28
29
30
31
32
33
34
# File 'lib/tdrb/parser.rb', line 24

def line_terminator?(char)
  return true if char == Token::EOF

  cp = char.codepoints;

  return true if cp.empty?
  return true if cp.count == 1 && [0, 10, 13, 59].include?(cp.first)
  return true if cp.count == 2 && cp.first == 13 and cp.last == 10

  false
end

.whitespace?(char) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/tdrb/parser.rb', line 36

def whitespace?(char)
  char.strip.empty?
end

Instance Method Details

#tokensObject



14
15
16
17
# File 'lib/tdrb/parser.rb', line 14

def tokens
  lexer.run
  lexer.tokens
end