require 'pp'
module Type
+ Nil = Struct.new(:value)
Array = Struct.new(:type, :count)
Record = Struct.new(:fields)
Func = Struct.new(:args, :return)
Ptr = Struct.new(:type)
Int = Struct.new(:min, :max)
- Real = Struct.new(:bits)
+ Float = Struct.new(:bits)
end
module Ast
+ Nil = Struct.new(:value)
Val = Struct.new(:type, :value)
+ Apply = Struct.new(:type, :func, :args)
+ Return = Struct.new(:type, :val)
end
BuiltinSyms = {
+ "Nil" => {
+ :kind => :type,
+ :type => Type::Nil.new(0),
+ },
+# "nil" => {
+# :kind => :const,
+# :type => "Nil",
+# :value => Ast::Val.new("Nil", 0)
+# },
"Bool" => {
kind: :type,
type: Type::Int.new(0, 1)
},
- "true" => {
- kind: :const,
- type: "Bool",
- value: Ast::Val.new("Bool", 1)
- },
- "false" => {
- kind: :const,
- type: "Bool",
- value: Ast::Val.new("Bool", 0)
- },
+# "true" => {
+# kind: :const,
+# type: "Bool",
+# value: Ast::Val.new("Bool", 1)
+# },
+# "false" => {
+# kind: :const,
+# type: "Bool",
+# value: Ast::Val.new("Bool", 0)
+# },
"Char" => {
kind: :type,
type: Type::Int.new(0, 0x10FFFF)
kind: :type,
type: Type::Int.new(-2**63-1, 2**63-1)
},
- "Real" => {
+ "Float" => {
kind: :type,
- type: Type::Real.new(64)
+ type: Type::Float.new(64)
},
"Byte" => {
kind: :type,
type: Type::Int.new(0, 255)
},
+ "String" => {
+ kind: :type,
+ type: Type::Array.new("Byte", nil)
+ },
}
class Lexer
BRACES = /[\(\)\[\]\{\}]/
OPERATORS = /[*\/=+-:\$]/
INTEGER = /[0-9]+/
+ STRING = /"(\\"|[^"])*"/
ID_TYPES = {
"module" => :module,
"imports" => :imports,
- "is" => :is
+ "is" => :is,
+ "nil" => :nil,
+ "true" => :bool,
+ "false" => :bool,
+ "return" => :return,
}
def initialize(path)
type = get_id_type(@data.matched)
elsif @data.scan(INTEGER)
type = :int
+ elsif @data.scan(STRING)
+ type = :string
elsif @data.scan(BRACES)
type = @data.matched
elsif @data.scan(OPERATORS)
LVLNAMES = LEVELS.keys
RULES = {
- "(" => { prefix: :grouping, infix: :func_call, level: :call },
- "+" => { prefix: :unary, infix: :binary, level: :term },
- "-" => { prefix: :unary, infix: :binary, level: :term },
- "*" => { prefix: nil, infix: :binary, level: :factor },
- "/" => { prefix: nil, infix: :binary, level: :factor },
- :int => { prefix: :constant, infix: nil, level: :none },
+ "(" => { prefix: :grouping, infix: :func_call, level: :call },
+ "+" => { prefix: :unary, infix: :binary, level: :term },
+ "-" => { prefix: :unary, infix: :binary, level: :term },
+ "*" => { prefix: nil, infix: :binary, level: :factor },
+ "/" => { prefix: nil, infix: :binary, level: :factor },
+ :nil => { prefix: :constant, infix: nil, level: :none },
+ :bool => { prefix: :constant, infix: nil, level: :none },
+ :int => { prefix: :constant, infix: nil, level: :none },
+ :float => { prefix: :constant, infix: nil, level: :none },
+ :string => { prefix: :constant, infix: nil, level: :none },
+ :char => { prefix: :constant, infix: nil, level: :none },
+ :byte => { prefix: :constant, infix: nil, level: :none },
}
def initialize(path)
sym[:type] = Type::Func.new([], nil)
func_args(sym)
sym[:type].return = type_specifier() if accept(":")
- expect("{")
- expect("}")
+ block(sym)
end
def func_args(sym)
expect(")")
end
- def func_body(sym)
+ def block(sym)
+ sym[:value] = []
expect("{")
+ while !matches("}")
+ sym[:value] << statement()
+ end
expect("}")
end
+ #######################################
+ # Statement Parsing
+ #######################################
+ def statement()
+ puts "statement"
+ if matches(:return)
+ expect(:return)
+ expr = expression()
+ Ast::Return.new(expr[:type], expr)
+ elsif matches(:if)
+ elseif matches(:ident)
+ # declaration
+ # assignment
+ # procedure call
+ else
+ error("invalid statment")
+ end
+ end
+
#######################################
# Expression Parsing
#######################################
def expression()
- expect("{")
- expect("}")
+ parseLevel(:assign)
+ end
+
+ def getRule(tok)
+ RULES[tok.type] || {}
+ end
+
+ def keepGoing(level)
+ rule = getRule(peek())
+ (LEVELS[level] <= LEVELS[rule[:level]]) if rule.keys.length > 0
+ end
+
+ def parseLevel(level)
+ consume()
+ prefixRule = getRule(@prev)[:prefix]
+ error("error parsing expression") if not prefixRule
+ ast = send(prefixRule)
+ while keepGoing(level)
+ consume()
+ infixRule = getRule(@prev)[:infix]
+ ast = send(infixRule, ast)
+ end
+ ast
+ end
+
+ def constant()
+ if (@prev.type == :int || @prev.type == :byte)
+ val = @prev.text.to_i
+ if @prev.type == :byte
+ error("invalid byte value") if (val < 0 || val > 255)
+ end
+ Ast::Val.new(Type::Int, )
+ elsif (@prev.type == :string)
+ Ast::Val.new("String", @prev.text)
+ elsif (@prev.type == :nil)
+ Ast::Val.new("Nil", 0)
+ elsif (@prev.type == :bool)
+ Ast::Val.new("Bool", @prev.text == "true")
+ elsif (@prev.type == :float)
+ error("no float support yet")
+ elsif (@prev.type == :char)
+ error("no char support yet")
+ else
+ error("not a valid constant")
+ end
+ end
+
+ def grouping()
+ ast = expression()
+ expect(")")
+ ast
+ end
+
+ def func_call(ast)
+ expect(")")
+ Ast::Apply.new(nil, ast, [])
+ end
+
+ def unary()
+ type = @prev.type
+ Ast::Apply.new(nil, @prev.type, [parseLevel(:unary)])
+ end
+
+ def nextLevel(tok)
+ level = getRule(@prev)[:level]
+ index = LVLNAMES.find_index(level)
+ LVLNAMES[index + 1]
+ end
+
+ def binary(left)
+ type = @prev.type
+ nlvl = nextLevel(type)
+ right = parseLevel(nlvl)
+ Ast::Apply.new(nil, type, [left, right])
end
#######################################