end
end
+class Codegen
+ def initialize()
+ @protos = StringIO.new
+ @funcs = {}
+ @func_stack = []
+ @func_id = 0
+ @temp_id = 0
+ end
+
+
+# def emit_line(str)
+# @func_stack.last.puts str
+# end
+#
+# def emit(str)
+# @func_stack.last.print str
+# end
+#
+# def emit_expr(expr)
+# v = get_tempvar()
+# emit_line " Value #{v} = #{expr};"
+# v
+# end
+#
+# def dump(file=$stdout)
+# file.puts @protos.string
+# @funcs.each {|f| file.puts f.string }
+# end
+#
+# def func_start()
+# io = StringIO.new
+# @syms.scope_start
+# @funcs.push(io)
+# @func_stack.push(io)
+# end
+#
+# def func_stop
+# @syms.scope_stop()
+# @func_stack.pop()
+# end
+
+ private
+
+ def mkfunc()
+ @func_id += 1
+ "__anonfunc#{@func_id}"
+ end
+
+ def mkvar()
+ @temp_id += 1
+ "__tmp#{@temp_id}"
+ end
+end
+
class Parser
LEVELS = {
none: 0,
@func_id = 0
end
- def toplevel()
- func_start()
- emit_line "Value toplevel(void) {"
- expr = emit_expr "NULL"
- while !matches(:eof)
- expr = expression()
- end
- emit_line " return #{expr};"
- emit_line "}"
- func_stop()
- end
-
- #######################################
- # Expression Parsing
- #######################################
- def expression()
- parseLevel(:assign)
- end
-
def getRule(tok)
RULES[tok.type] || {}
end
LVLNAMES[index + 1]
end
+ def error(str)
+ puts "#{@lex.file}:#{@lex.linenum(@next || @prev)}: #{str}"
+ exit 1
+ end
+
+ def peek()
+ @next = @lex.next if @next.nil?
+ @next
+ end
+
+ def matches(type)
+ (peek().type == type)
+ end
+
+ def accept(type)
+ if (matches(type))
+ @prev = @next
+ @next = nil
+ true
+ else
+ false
+ end
+ end
+
+ def expect(type)
+ tok = peek()
+ if not accept(type)
+ error("expected '#{type}', received '#{tok.type}'")
+ end
+ tok
+ end
+
+ def consume()
+ expect(peek().type)
+ end
+
+ def eof?
+ (peek().type == :eof)
+ end
+
+ def toplevel()
+ func_start()
+ emit_line "Value toplevel(void) {"
+ expr = emit_expr "NULL"
+ while !matches(:eof)
+ expr = expression()
+ end
+ emit_line " return #{expr};"
+ emit_line "}"
+ func_stop()
+ end
+
+ #######################################
+ # Expression Parsing
+ #######################################
+ def expression()
+ parseLevel(:assign)
+ end
+
def assign(left)
if (left.to_s.start_with? "__tmp")
error("invalid expression on left-hand side of assignment")
@syms.scope_stop()
@func_stack.pop()
end
-
- #######################################
- # Parsing Primitives
- #######################################
- def error(str)
- puts "#{@lex.file}:#{@lex.linenum(@next || @prev)}: #{str}"
- exit 1
- end
-
- def peek()
- @next = @lex.next if @next.nil?
- @next
- end
-
- def matches(type)
- (peek().type == type)
- end
-
- def accept(type)
- if (matches(type))
- @prev = @next
- @next = nil
- true
- else
- false
- end
- end
-
- def expect(type)
- tok = peek()
- if not accept(type)
- error("expected '#{type}', received '#{tok.type}'")
- end
- tok
- end
-
- def consume()
- expect(peek().type)
- end
-
- def eof?
- (peek().type == :eof)
- end
end
parse = Parser.new("dyn.src")