Class: Spitewaste::WhitespaceParser

Inherits:
Object
  • Object
show all
Defined in:
lib/spitewaste/parsers/whitespace.rb

Constant Summary collapse

SyntaxError =
Class.new Exception

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(program, **options) ⇒ WhitespaceParser

Returns a new instance of WhitespaceParser.



7
8
9
# File 'lib/spitewaste/parsers/whitespace.rb', line 7

def initialize program, **options
  @tokens = program.delete "^\s\t\n" # Remove comments.
end

Instance Attribute Details

#errorObject (readonly)

Returns the value of attribute error.



5
6
7
# File 'lib/spitewaste/parsers/whitespace.rb', line 5

def error
  @error
end

#instructionsObject (readonly)

Returns the value of attribute instructions.



5
6
7
# File 'lib/spitewaste/parsers/whitespace.rb', line 5

def instructions
  @instructions
end

Instance Method Details

#parseObject



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/spitewaste/parsers/whitespace.rb', line 11

def parse
  @instructions = []
  @line = @column = 1
  operator_buffer = ''
  mnemonics = OPERATORS_M2T.keys

  while token = @tokens.slice!(0)
    operator_buffer << token
    if @operator = OPERATORS_T2M[operator_buffer]
      argument = parse_number if mnemonics.index(@operator) < 8
      @instructions << [@operator, argument]
      operator_buffer.clear
      argument = nil
    end

    if OPERATORS_T2M.none? { |tokens,| tokens.start_with? operator_buffer }
      @error = [:illegal, operator_buffer, [@line, @column]]
      raise SyntaxError,
        "illegal token sequence: #{operator_buffer.inspect} " +
        "(line #@line, column #@column)"
    end

    if token == ?\n
      @line, @column = @line + 1, 1
    else
      @column += 1
    end
  end
end

#parse_numberObject

Raises:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/spitewaste/parsers/whitespace.rb', line 41

def parse_number
  unless end_of_number = @tokens.index(?\n)
    @column += @tokens.size
    @error = [:number, @operator, [@line, @column]]
    raise SyntaxError,
      "found EOF before end of number for #@operator operator " +
      "(line #@line, column #@column)"
  end

  digits = @tokens.slice! 0, end_of_number + 1

  raise SyntaxError,
    "too few digits in number for #@operator operator " +
    "(line #@line, column #@column)" if digits.size <3

  digits[0] = ?- if digits[0] == ?\t
  digits.tr("\s\t", '01').to_i 2
end