#!/usr/bin/env ruby
require 'strscan'
-require 'pp'
module Type
Nil = Struct.new(:value)
end
module Ast
- Nil = Struct.new(:value)
+ Nil = Struct.new(:type, :value)
Val = Struct.new(:type, :value)
Apply = Struct.new(:type, :func, :args)
Return = Struct.new(:type, :val)
- Var = Struct.new(:name, :type, :value)
+ Var = Struct.new(:type, :name, :value)
IfStmt = Struct.new(:cond, :br1, :br2)
- Ident = Struct.new(:name)
+ Ident = Struct.new(:type, :name)
end
BuiltinSyms = {
"-" => { prefix: :unary, infix: :binary, level: :term },
"*" => { prefix: nil, infix: :binary, level: :factor },
"/" => { prefix: nil, infix: :binary, level: :factor },
+ "=" => { prefix: nil, infix: :assign, level: :assign },
:ident => { prefix: :variable, infix: nil, level: :none },
:nil => { prefix: :constant, infix: nil, level: :none },
:bool => { prefix: :constant, infix: nil, level: :none },
pointer_type()
elsif matches("?")
nilable_type()
-# elsif matches(:func)
-# func_type()
else
name = expect(:ident).text
- # TODO: check the type exists
+ name = [name] if matches(".")
+ while accept(".")
+ name << expect(:ident)
+ end
name
end
end
end
def declaration(name)
- var = Ast::Var.new(name.text, nil, nil)
+ var = Ast::Var.new(nil, name.text, nil)
expect(":")
var.type = type_specifier()
expect("=")
end
def decl_or_expr()
- ident = Ast::Ident.new(expect(:ident).text)
+ ident = Ast::Ident.new(nil, expect(:ident).text)
if matches(":")
declaration(@prev)
else
- parseNextLevel(ident, :none)
+ parseLevel(:assign, false)
end
end
(LEVELS[level] <= LEVELS[rule[:level]]) if rule.keys.length > 0
end
- def parseLevel(level)
- consume()
+ def parseLevel(level, take = true)
+ consume() if take
prefixRule = getRule(@prev)[:prefix]
error("error parsing expression") if not prefixRule
parseNextLevel(send(prefixRule), level)
while keepGoing(level)
consume()
infixRule = getRule(@prev)[:infix]
+# break if infixRule.nil? # Is this needed?
ast = send(infixRule, ast)
end
ast
end
def access(left)
- right = Ast::Ident.new(expect(:ident).text)
+ right = Ast::Ident.new(nil, expect(:ident).text)
access = Ast::Apply.new(nil, ".", [left, right])
if accept("(")
func_call(access)
def subscript(left)
right = expression()
-# p right
ast = Ast::Apply.new(nil, "[", [left, right])
-# p ast
expect("]")
- p peek()
ast = parseNextLevel(ast, :call)
-# p ast
ast
end
+ def assign(left)
+ Ast::Apply.new(left.type, "=", [left, expression()])
+ end
+
def variable()
- Ast::Ident.new(@prev.text)
+ Ast::Ident.new(nil, @prev.text)
end
def constant()