Return = Struct.new(:type, :val)
Var = Struct.new(:name, :type, :value)
IfStmt = Struct.new(:cond, :br1, :br2)
+ Ident = Struct.new(:name)
end
BuiltinSyms = {
Tok = Struct.new(:text, :file, :pos, :type)
SPACE = /([ \t\v\n\r]+|#.*\n)/
IDENT = /[_a-zA-Z][_a-zA-Z0-9]*/
- BRACES = /[\(\)\[\]\{\}]/
+ BRACES = /[\(\)\[\]\{\}\.]/
OPERATORS = /[*\/=+-:\$]/
INTEGER = /[0-9]+/
STRING = /"(\\"|[^"])*"/
LVLNAMES = LEVELS.keys
RULES = {
+ "." => { prefix: nil, infix: :access, level: :call },
"(" => { 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 },
+ :ident => { prefix: :variable, infix: nil, level: :none },
:nil => { prefix: :constant, infix: nil, level: :none },
:bool => { prefix: :constant, infix: nil, level: :none },
:int => { prefix: :constant, infix: nil, level: :none },
return_statement()
elsif matches(:if)
if_statement()
- elsif matches(:ident)
- ident = expect(:ident)
- if matches(":")
- declaration(ident)
- else
- binary(ident)
- end
+# elsif matches(:ident)
+# ident = expect(:ident)
+# if matches(":")
+# declaration(ident)
+# else
+# binary(ident)
+# end
else
expression()
end
ast
end
+ def access(left)
+ right = Ast::Ident.new(expect(:ident).text)
+ access = Ast::Apply.new(nil, ".", [left, right])
+ if accept("(")
+ func_call(access)
+ else
+ access
+ end
+ end
+
+ def variable()
+ Ast::Ident.new(@prev.text)
+ 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, )
+ Ast::Val.new(Type::Int, nil)
elsif (@prev.type == :string)
Ast::Val.new("String", @prev.text)
elsif (@prev.type == :nil)
end
def func_call(ast)
+ call = Ast::Apply.new(nil, ast, [])
+ while !matches(")")
+ call[:args] << expression()
+ expect(",") if !matches(")")
+ end
expect(")")
- Ast::Apply.new(nil, ast, [])
+ call
end
def unary()
def nextLevel(tok)
level = getRule(@prev)[:level]
index = LVLNAMES.find_index(level)
+ error("unknown operator type '#{tok}'") if not index
LVLNAMES[index + 1]
end