Permalink
Browse files

Support print statements

  • Loading branch information...
mattgreen committed Jun 3, 2014
0 parents commit 57db4000f7581ad8aba1d243a0869dfecea55571
Showing with 80 additions and 0 deletions.
  1. +74 −0 alpha/alpha.rb
  2. +6 −0 alpha/input.txt
@@ -0,0 +1,74 @@
+# Dirt-simple lexer that parses statements of the form:
+# print "<str>"
+class Lexer
+ def lex(code)
+ tokens = []
+
+ i = 0
+ line = 1
+
+ while i < code.length
+ chunk = code[i..code.length]
+
+ if print_statement = chunk[/\Aprint \"(.*)\"/]
+ tokens << [:PRINT, $1]
+ i += print_statement.length
+
+ elsif chunk[0] == "\n"
+ line += 1
+ i += 1
+
+ else
+ raise "Unexpected input on line #{line}: \"#{chunk[0..chunk.index("\n")-1]}\""
+
+ end
+ end
+
+ tokens
+ end
+end
+
+# An AST with only one node :)
+class PrintNode < Struct.new(:str)
+end
+
+# Converts token stream produced by lexer into AST nodes
+class Parser
+ def initialize
+ @nodes = []
+ end
+
+ def parse(tokens)
+ nodes = []
+
+ tokens.each do |token|
+ if token[0] == :PRINT
+ nodes << PrintNode.new(token[1])
+ else
+ raise "Unexpected token: #{token}"
+ end
+ end
+
+ nodes
+ end
+end
+
+# Walks the specified AST, executing it
+class Interpreter
+ def evaluate(nodes)
+ nodes.each do |node|
+ method = "evaluate" + node.class.name.gsub(/([A-Z])/) { "_#{$1.downcase}" }
+
+ __send__(method, node)
+ end
+ end
+
+ def evaluate_print_node(node)
+ print node.str + "\n"
+ end
+end
+
+tokens = Lexer.new.lex(File.read(ARGV[0]))
+nodes = Parser.new.parse(tokens)
+Interpreter.new.evaluate(nodes)
+
@@ -0,0 +1,6 @@
+print "Hello"
+
+print "Several words"
+print "Last line"
+print ""
+print "I am Matt"

0 comments on commit 57db400

Please sign in to comment.