Module: Qcmd::Parser

Defined in:
lib/qcmd/parser.rb

Class Method Summary collapse

Class Method Details

.convert_tokens(token_array) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/qcmd/parser.rb', line 72

def convert_tokens( token_array )
  converted_tokens = []
  token_array.each do |t|
    converted_tokens << t.to_i and next if( is_integer_literal?(t) )
    converted_tokens << t.to_f and next if( is_float_literal?(t) )
    converted_tokens << t.to_s and next if( is_symbol?(t) )
    converted_tokens << eval(t) and next if( is_string_literal?(t) )
    # If we haven't recognized the token by now we need to raise
    # an exception as there are no more rules left to check against!
    raise Exception, "Unrecognized token: #{t}"
  end
  return converted_tokens
end

.extract_string_literals(string) ⇒ Object

adapted from gist.github.com/612311 by Aaron Gough



6
7
8
9
10
11
12
13
14
15
16
# File 'lib/qcmd/parser.rb', line 6

def extract_string_literals( string )
  string_literal_pattern = /"([^"\\]|\\.)*"/
  string_replacement_token = "___+++STRING_LITERAL+++___"
  # Find and extract all the string literals
  string_literals = []
  string.gsub(string_literal_pattern) {|x| string_literals << x}
  # Replace all the string literals with our special placeholder token
  string = string.gsub(string_literal_pattern, string_replacement_token)
  # Return the modified string and the array of string literals
  return [string, string_literals]
end

.is_float_literal?(string) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
63
# File 'lib/qcmd/parser.rb', line 60

def is_float_literal?( string )
  # Any number of numerals optionally preceded by a plus or minus sign
  return is_match?( string, /[\-\+]?[0-9]+(\.[0-9]*)?/ )
end

.is_integer_literal?(string) ⇒ Boolean

Detect an integer literal

Returns:

  • (Boolean)


55
56
57
58
# File 'lib/qcmd/parser.rb', line 55

def is_integer_literal?( string )
  # Any number of numerals optionally preceded by a plus or minus sign
  return is_match?( string, /[\-\+]?[0-9]+/ )
end

.is_match?(string, pattern) ⇒ Boolean

A helper method to take care of the repetitive stuff for us

Returns:

  • (Boolean)


41
42
43
44
45
46
# File 'lib/qcmd/parser.rb', line 41

def is_match?( string, pattern)
  match = string.match(pattern)
  return false unless match
  # Make sure that the matched pattern consumes the entire token
  match[0].length == string.length
end

.is_string_literal?(string) ⇒ Boolean

Detect a string literal

Returns:

  • (Boolean)


66
67
68
69
70
# File 'lib/qcmd/parser.rb', line 66

def is_string_literal?( string )
  # Any characters except double quotes
  # (except if preceded by a backslash), surrounded by quotes
  return is_match?( string, /"([^"\\]|\\.)*"/)
end

.is_symbol?(string) ⇒ Boolean

Detect a symbol

Returns:

  • (Boolean)


49
50
51
52
# File 'lib/qcmd/parser.rb', line 49

def is_symbol?( string )
  # Anything other than parentheses, single or double quote and commas
  return is_match?( string, /[^\"\'\,\(\)]+/ )
end

.parse(string) ⇒ Object



86
87
88
89
90
91
92
# File 'lib/qcmd/parser.rb', line 86

def parse( string )
  string, string_literals = extract_string_literals(string)
  token_array = tokenize_string(string)
  token_array = restore_string_literals(token_array, string_literals)
  token_array = convert_tokens(token_array)
  return token_array
end

.restore_string_literals(token_array, string_literals) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/qcmd/parser.rb', line 25

def restore_string_literals( token_array, string_literals )
  return token_array.map do |x|
    if(x == '___+++STRING_LITERAL+++___')
      # Since we've detected that a string literal needs to be
      # replaced we will grab the first available string from the
      # string_literals array
      string_literals.shift
    else
      # This is not a string literal so we need to just return the
      # token as it is
      x
    end
  end
end

.tokenize_string(string) ⇒ Object



18
19
20
21
22
23
# File 'lib/qcmd/parser.rb', line 18

def tokenize_string( string )
  string = string.gsub("(", " ( ")
  string = string.gsub(")", " ) ")
  token_array = string.split(" ")
  return token_array
end