Class: Q_Parser

Inherits:
Racc::Parser
  • Object
show all
Defined in:
lib/q-language/parser.rb

Constant Summary collapse

Racc_debug_parser =
false
Racc_arg =
[
[2,9,6,7,2,10,6,7,2,3,12,13], [2,3,2,2,4,4,4,4,0,1,6,7],
[-9,-9,-8,-9,-9,-2,-9,-5,-6,14,-1,-7,-3,-4],
[6,9,-2,1,2,nil,5,5,nil,nil,nil,nil,nil,nil],
[8,4,11,1], [3,2,3,1], [nil,5,nil,nil], [nil,3,-1,-2], 7,
[0,0,:racc_error, 3,8,:new_block, 1,10,:block,
  2,10,:new_variable, 2,10,:new_literal, 1,10,:new_method,
  1,9,:new_node_array, 2,9,:append_node, 0,9,:new_empty_array],
{ false=>0, error: 1, "{"=>2, "}"=>3, ":"=>4, ID: 5, STRING: 6 },
14, 9, true]

Instance Method Summary collapse

Constructor Details

#initialize(script) ⇒ Q_Parser

Returns a new instance of Q_Parser.



10
11
12
# File 'lib/q-language/parser.rb', line 10

def initialize (script)
  @ss = StringScanner.new(script)
end

Instance Method Details

#next_tokenObject

Removes and returns one item from the Array of script tokens. Required by racc.



17
18
19
# File 'lib/q-language/parser.rb', line 17

def next_token
  @tokens.shift
end

#on_errorObject

Raises a SyntaxError. Required by racc.

Raises:

  • (SyntaxError)


24
25
26
# File 'lib/q-language/parser.rb', line 24

def on_error (*)
  raise SyntaxError, "tokens do not form valid script"
end

#parseObject

Parses the Q script, then returns an Array containing the outermost Node, an Array of every block Node, an Array of every literal Node, an Array of every method Node, and an Array of every variable Node. If any invalid tokens are encountered in the script or if the tokens do not form a valid Q script, raises a SyntaxError.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/q-language/parser.rb', line 34

def parse
  @tokens = []
  @ss.reset
  
  until @ss.eos?
    @tokens << case c = @ss.getch
      when /\s/ then next
      when /[\p{alpha}_]/
        @ss.unscan.scan /[\p{alnum}_]+[?!]?/
        [:ID, @ss.matched.intern]
      when /[}:{]/ then [c, 0]
      when /\(/ then [:STRING, scan_literal]
      else raise SyntaxError, "script contains invalid token `#{c}'"
    end
  end
  
  @tokens << [false, false]
  
  @blocks = []
  @literals = []
  @methods = []
  @variables = []
  
  return do_parse, @blocks, @literals, @methods, @variables
end

#scan_literalObject

Returns the string enclosed by the set of parentheses beginning at the ‘(’ exactly one character before the StringScanner’s current pointer location and ending at the ‘)’ character after all sets of parentheses have been balanced. Parenthesis characters escaped by a preceding ‘' are not considered in the balance count. If the end of the string is reached before the closing ’)‘ character, raises a SyntaxError.

Raises:

  • (SyntaxError)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/q-language/parser.rb', line 67

def scan_literal
  strings = []
  p_count = 0
  
  while s = @ss.scan_until(/(?=[()\\])/)
    case (c = @ss.getch).ord
      when 41 then (p_count == 0) ? (return (strings << s).join) : (p_count -= 1) # )
      when 40 then p_count += 1 # (
      when 92 then %w[) (].include?(@ss.peek(1)) ? (strings << s << c << @ss.getch) : (next) # \
    end
    
    strings << s << c
  end
  
  raise SyntaxError, "unterminated literal meets end of script"
end