Class: Baba

Inherits:
Object
  • Object
show all
Defined in:
lib/baba.rb,
lib/baba/run.rb,
lib/baba/expr.rb,
lib/baba/stmt.rb,
lib/baba/class.rb,
lib/baba/error.rb,
lib/baba/token.rb,
lib/baba/parser.rb,
lib/baba/tokens.rb,
lib/baba/scanner.rb,
lib/baba/version.rb,
lib/baba/callable.rb,
lib/baba/function.rb,
lib/baba/instance.rb,
lib/baba/resolver.rb,
lib/baba/environment.rb,
lib/baba/interpreter.rb,
lib/baba/ruby_object.rb,
lib/baba/runtime_error.rb

Defined Under Namespace

Modules: Expr, Stmt Classes: BabaClass, BabaRuntimeError, Break, Callable, Environment, Function, Instance, Interpreter, Parser, Resolver, Return, RubyClass, RubyFunction, RubyObject, Scanner, Token

Constant Summary collapse

LEFT_PAREN =

Single character tokens

0
RIGHT_PAREN =

(

1
COMMA =

)

2
MINUS =

,

3
PLUS =

-

4
SLASH =

+

5
STAR =

/

6
SEMICOLON =

*

7
COLON =

;

39
DOT =

: (colons are used when marking a new statement), can also function as {

44
NOT =

One-two character tokens

8
NOT_EQUAL =

! OR not

9
EQUAL =

!= OR not-equal

10
EQUAL_EQUAL =

is OR =

11
GREATER =

OR equals

12
LESS =

> OR greater

13
GREATER_EQUAL =

< OR less

14
LESS_EQUAL =

>= greater-equal

15
IDENTIFIER =

Literals

16
STRING =

??

17
NUMBER =

“”

18
THING =

Keywords

19
IF =

thing (class basically)

20
ELSE =

if

21
DOES =

else

22
FOR =

does (method definition)

23
BLANK =

for

24
OR =

blank (nil)

25
AND =

or OR ||

26
RETURN =

and OR &&

27
SUPER =

return

28
SELF =

super

29
VAR =

self

30
WHILE =

variable

31
FALSE =

while

32
TRUE =

false

33
KEND =

true

38
BREAK =

end, can also function as }

42
INCLUDE =

break

48
RBEVAL =

include

34
EOF =

RBFUNC = 35 # rb_func RBINSTANCECALL = 36 # rb_instance_call

37
KEYWORDS =

There are too many of these lol

{
  "thing" => THING,
  "if" => IF,
  "else" => ELSE,
  "does" => DOES,
  "for" => FOR,

  "blank" => BLANK,
  "nil" => BLANK,

  "or" => OR,
  "||" => OR,

  "and" => AND,
  "&&" => AND,

  "return" => RETURN,
  "super" => SUPER,
  "self" => SELF,
  "var" => VAR,
  "while" => WHILE,
  "false" => FALSE,
  "true" => TRUE,
  "end" => KEND, # It's KEND because ruby is dumb
  "break" => BREAK,

  "rb_eval" => RBEVAL,
  "include" => INCLUDE,
  # "rb_func" => RBFUNC,
  # "rb_instance_call" => RBINSTANCECALL,

  "not" => NOT,
  "not-equals" => NOT_EQUAL,
  "is" => EQUAL,
  "equals" => EQUAL_EQUAL,
  "greater" => GREATER,
  "less" => LESS,
  "greater-equal" => GREATER_EQUAL,
  "less-equal" => LESS_EQUAL,
}
VERSION =
"1.0.1"
@@had_error =
false

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeBaba

Returns a new instance of Baba.



10
11
12
# File 'lib/baba.rb', line 10

def initialize
  @interpreter = Interpreter.new
end

Class Method Details

.had_errorObject



46
47
48
# File 'lib/baba/error.rb', line 46

def self.had_error
  @@had_error
end

.parser_error(token, what) ⇒ Object



21
22
23
24
25
26
27
# File 'lib/baba/error.rb', line 21

def self.parser_error(token, what)
  if (token.type == EOF)
    report(token.line, "at_end #{what}")
  else
    report(token.line, "at '#{token.lexeme}', #{what}")
  end
end

.report(line, what, line_contents = nil, character = nil) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/baba/error.rb', line 37

def self.report(line, what, line_contents = nil, character = nil)
  warn "Error: #{what}\n"
  warn "#{line} | #{line_contents}" if line_contents
  warn "#{line} | " + ("~" * character) + "^ HERE" if character && line_contents
  warn "*" * 30

  @@had_error = true
end

.runtime_error(error) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/baba/error.rb', line 29

def self.runtime_error(error)
  if error.token.nil?
    report(0, error.message)
    return
  end
  report(error.token.line, error.message)
end

.scanner_error(line, what, contents = nil, character = nil) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/baba/error.rb', line 4

def self.scanner_error(line, what, contents = nil, character = nil)
  line_contents = nil
  line_character = nil
  unless contents.nil?
    begin
      line_contents = contents.split("\n")[line - 1]
      unless character.nil?
        line_character = character - contents.split("\n")[0..line].join.length
      end
    rescue ArgumentError => e
      warn e.message
    end
    line_character = nil if line_character.negative?
  end
  report(line, what, line_contents, line_character)
end

Instance Method Details

#mainObject



14
15
16
17
18
19
20
21
22
23
# File 'lib/baba.rb', line 14

def main
  case ARGV.length
  when 1
    run_file(ARGV[0])
  when 0
    run_interactive
  else
    puts "Usage: baba [file]"
  end
end

#run(source) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/baba/run.rb', line 7

def run(source)
  scanner = Scanner.new(source)
  tokens = scanner.scan_tokens
  parser = Parser.new(tokens)

  statements = parser.parse

  return if @@had_error

  resolver = Resolver.new(@interpreter)
  resolver.resolve(statements)

  return if @@had_error

  @interpreter.interpret(statements)
end

#run_file(path) ⇒ Object



25
26
27
28
29
30
31
32
# File 'lib/baba.rb', line 25

def run_file(path)
  f = File.open(path, "rb+")
  run(f.read)

  if @@had_error
    exit 1
  end
end

#run_interactiveObject



36
37
38
39
40
41
42
43
44
45
# File 'lib/baba.rb', line 36

def run_interactive
  prompt = "irbaba (#{VERSION}) > "
  use_history = true
  while buf = Readline.readline(prompt, use_history)
    break if buf == "exit"

    run(buf)
    @@had_error = false
  end
end