class JGrep::Parser
Attributes
execution_stack[R]
scanner[R]
Public Class Methods
new(args)
click to toggle source
# File lib/parser/parser.rb, line 5 def initialize(args) @scanner = Scanner.new(args) @execution_stack = [] parse end
Public Instance Methods
parse(substatement = nil, token_index = 0)
click to toggle source
Parse the input string, one token at a time a contruct the call stack
# File lib/parser/parser.rb, line 13 def parse(substatement = nil, token_index = 0) p_token = nil if substatement c_token, c_token_value = substatement[token_index] else c_token, c_token_value = @scanner.get_token end parenth = 0 until c_token.nil? if substatement token_index += 1 n_token, n_token_value = substatement[token_index] else @scanner.token_index += 1 n_token, n_token_value = @scanner.get_token end next if n_token == " " case c_token when "and" unless (n_token =~ /not|statement|\(|\+|-/) || (scanner.token_index == scanner.arguments.size) raise "Error at column #{scanner.token_index}. \nExpected 'not', 'statement' or '('. Found '#{n_token_value}'" end raise "Error at column #{scanner.token_index}. \n Expression cannot start with 'and'" if p_token.nil? raise "Error at column #{scanner.token_index}. \n #{p_token} cannot be followed by 'and'" if %w[and or].include?(p_token) when "or" unless (n_token =~ /not|statement|\(|\+|-/) || (scanner.token_index == scanner.arguments.size) raise "Error at column #{scanner.token_index}. \nExpected 'not', 'statement', '('. Found '#{n_token_value}'" end raise "Error at column #{scanner.token_index}. \n Expression cannot start with 'or'" if p_token.nil? raise "Error at column #{scanner.token_index}. \n #{p_token} cannot be followed by 'or'" if %w[and or].include?(p_token) when "not" unless n_token =~ /statement|\(|not|\+|-/ raise "Error at column #{scanner.token_index}. \nExpected 'statement' or '('. Found '#{n_token_value}'" end when "statement" if c_token_value.is_a? Array raise "Error at column #{scanner.token_index}\nError, cannot define '[' in a '[...]' block." if substatement parse(c_token_value, 0) end if c_token_value =~ /!=/ c_token_value = c_token_value.gsub("!=", "=") @execution_stack << {"not" => "not"} end if !n_token.nil? && !n_token.match(/and|or|\)/) raise "Error at column #{scanner.token_index}. \nExpected 'and', 'or', ')'. Found '#{n_token_value}'" end when "+" if !n_token.nil? && !n_token.match(/and|or|\)/) raise "Error at column #{scanner.token_index}. \nExpected 'and', 'or', ')'. Found '#{n_token_value}'" end when "-" if !n_token.nil? && !n_token.match(/and|or|\)/) raise "Error at column #{scanner.token_index}. \nExpected 'and', 'or', ')'. Found '#{n_token_value}'" end when ")" if !n_token.nil? && !n_token =~ /|and|or|not|\(/ raise "Error at column #{scanner.token_index}. \nExpected 'and', 'or', 'not' or '('. Found '#{n_token_value}'" end parenth += 1 when "(" unless n_token =~ /statement|not|\(|\+|-/ raise "Error at column #{scanner.token_index}. \nExpected 'statement', '(', not. Found '#{n_token_value}'" end parenth -= 1 else raise "Unexpected token found at column #{scanner.token_index}. '#{c_token_value}'" end unless n_token == " " || substatement @execution_stack << {c_token => c_token_value} end p_token = c_token c_token = n_token c_token_value = n_token_value end return if substatement raise "Error. Missing parentheses ')'." if parenth < 0 raise "Error. Missing parentheses '('." if parenth > 0 end