Class: Parser

Inherits:
Object show all
Includes:
Environment, ErrorMessages, Validator
Defined in:
lib/lisp/interpreter/parser.rb

Overview

Parser is used to validate the user input and parse it to the tokenizer

Constant Summary

Constants included from Environment

Environment::PROD, Environment::TEST

Instance Method Summary collapse

Methods included from Validator

#balanced_brackets?, #balanced_quotes?, #valid_function, #valid_var, #valid_var_name

Methods included from ErrorMessages

#arg_err_build, #no_procedure_build, #type_err, #unbalanced_brackets_error, #unbalanced_quotes_error, #unbound_symbol_err

Constructor Details

#initialize(env_type = Environment::TEST) ⇒ Parser

Returns a new instance of Parser.



15
16
17
18
# File 'lib/lisp/interpreter/parser.rb', line 15

def initialize(env_type = Environment::TEST)
  @env_type = env_type
  @tokenizer = Tokenizer.new
end

Instance Method Details

#display_result(result) ⇒ Object



119
120
121
122
# File 'lib/lisp/interpreter/parser.rb', line 119

def display_result(result)
  to_print = find_result_type result, @tokenizer.syntax_methods
  puts to_print
end

#finalize_result(result) ⇒ Object



100
101
102
103
104
# File 'lib/lisp/interpreter/parser.rb', line 100

def finalize_result(result)
  result = format_result result
  display_result result if @env_type == Environment::PROD
  result
end

#find_result_type(res, methods) ⇒ Object



112
113
114
115
116
117
# File 'lib/lisp/interpreter/parser.rb', line 112

def find_result_type(res, methods)
  return '#<Closure>' if res.is_a? Proc
  is_func = (methods.key? res.to_s)
  return '#<Function ' + res.to_s + '>' if is_func
  res.to_s
end

#format_result(result) ⇒ Object



106
107
108
109
110
# File 'lib/lisp/interpreter/parser.rb', line 106

def format_result(result)
  to_remove = result.to_s.list? || result.to_s.pair? || result.to_s.quote?
  result = result.delete('\'') if to_remove
  result
end

#parse(token) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/lisp/interpreter/parser.rb', line 80

def parse(token)
  return read_file token if (token.start_with? 'ghci ') && token.size > 4
  token_error = validate_token token
  result =
    if token_error.nil?
      @tokenizer.tokenize split_token token
    else
      token_error
    end
  finalize_result result unless result.to_s.empty?
end

#read_file(token) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/lisp/interpreter/parser.rb', line 72

def read_file(token)
  res = read_file_helper token
  return finalize_result res if res.is_a? String
  filename = token[5..-1]
  return read_file_executor filename if File.exist? filename
  finalize_result 'File with name "' + filename + '" does not exist!'
end

#read_file_execute_lines(f, expr) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/lisp/interpreter/parser.rb', line 54

def read_file_execute_lines(f, expr)
  last_value = ''
  f.each do |line|
    expr << line
    if (validate_token expr).nil? && expr != ''
      last_value = parse expr
      expr = ''
    end
  end
  last_value
end

#read_file_executor(file) ⇒ Object



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

def read_file_executor(file)
  f = File.open(file)
  expr = ''
  read_file_execute_lines f, expr
end

#read_file_helper(token) ⇒ Object



45
46
47
48
49
50
51
52
# File 'lib/lisp/interpreter/parser.rb', line 45

def read_file_helper(token)
  pattern = /^ghci .*\.[.ss|.scm]+$/
  result = (token =~ pattern)
  return unless result.nil?
  token = token[5..-1].nil? ? token[4..-1] : token[5..-1]
  msg = 'File with name "' + token + '" is not valid scheme file'
  msg
end

#runObject



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/lisp/interpreter/parser.rb', line 20

def run
  loop do
    print 'zakichan> ' if @env_type == Environment::PROD
    token = ''
    until (validate_token token).nil? && token != ''
      crr_input = STDIN.gets.chomp
      token << crr_input
      break if crr_input == ''
    end
    parse token
  end
end

#split_token(token) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/lisp/interpreter/parser.rb', line 33

def split_token(token)
  result = []
  token.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/).each do |t|
    if !t.string? && (t.include?('(') || t.include?(')'))
      t.to_s.split(/(\(|\))/).each { |p| result << p }
    else
      result << t
    end
  end
  result
end

#validate_token(token) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/lisp/interpreter/parser.rb', line 92

def validate_token(token)
  if !balanced_brackets? token
    unbalanced_brackets_error
  elsif !balanced_quotes? token
    unbalanced_quotes_error
  end
end