From c0748f06999f666cedfab0d27cba8b41569b51fe Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 27 Jan 2020 22:22:09 -0500 Subject: [PATCH] implemented statement parsing --- compile.rb | 94 +++++++++++++++++++++++++++++++---------------------- example.src | 5 +++ 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/compile.rb b/compile.rb index 5fb23e5..9f3fdba 100755 --- a/compile.rb +++ b/compile.rb @@ -18,6 +18,8 @@ module Ast Val = Struct.new(:type, :value) Apply = Struct.new(:type, :func, :args) Return = Struct.new(:type, :val) + Var = Struct.new(:name, :type, :value) + IfStmt = Struct.new(:cond, :br1, :br2) end BuiltinSyms = { @@ -25,25 +27,10 @@ BuiltinSyms = { :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) -# }, "Char" => { kind: :type, type: Type::Int.new(0, 0x10FFFF) @@ -82,6 +69,8 @@ class Lexer "true" => :bool, "false" => :bool, "return" => :return, + "if" => :if, + "else" => :else, } def initialize(path) @@ -153,6 +142,9 @@ class Parser @lex = Lexer.new(path) @prev = nil @next = nil + @name = nil + @imports = [] + @symbols = {} end ####################################### @@ -160,29 +152,28 @@ class Parser ####################################### def module() expect(:module) - expect(:ident).text + @name = expect(:ident).text + @name end def imports() expect(:imports) expect("(") - reqs = [] while (!matches(")")) - reqs << expect(:ident).text + @imports << expect(:ident).text expect(",") if !matches(")") end expect(")") - reqs + @imports end def definitions() - defs = {} while !matches(:eof) sym = { export: accept("$"), name: expect(:ident).text } - error("#{sym[:name]} multiply defined in module") if defs[sym[:name]] + error("#{sym[:name]} multiply defined in module") if @symbols[sym[:name]] if matches(:is) typedef(sym) elsif matches(":") @@ -192,9 +183,9 @@ class Parser else error("invalid symbol definition") end - defs[sym[:name]] = sym + @symbols[sym[:name]] = sym end - defs + @symbols end ####################################### @@ -268,7 +259,7 @@ class Parser sym[:type] = Type::Func.new([], nil) func_args(sym) sym[:type].return = type_specifier() if accept(":") - block(sym) + sym[:value] = block() end def func_args(sym) @@ -283,39 +274,66 @@ class Parser expect(")") end - def block(sym) - sym[:value] = [] + def block() + block = [] expect("{") while !matches("}") - sym[:value] << statement() + block << statement() end expect("}") + block end ####################################### # Statement Parsing ####################################### def statement() - puts "statement" if matches(:return) - expect(:return) - expr = expression() - Ast::Return.new(expr[:type], expr) + return_statement() elsif matches(:if) - elseif matches(:ident) - name = expect(:ident) + if_statement() + elsif matches(:ident) + ident = expect(:ident) if matches(":") -# declaration(name) - elsif matches("=") -# assignment + declaration(ident) else -# binary_expr(name) # procedure call / expression + binary(ident) end else - error("invalid statment") + expression() end end + def return_statement() + expect(:return) + expr = expression() + Ast::Return.new(expr[:type], expr) + end + + def if_statement() + stmt = Ast::IfStmt.new(nil, nil, nil) + expect(:if) + stmt.cond = expression() + stmt.br1 = block() + if accept(:else) + if matches(:if) + stmt.br2 = if_statement() + else + stmt.br2 = block() + end + end + stmt + end + + def declaration(name) + var = Ast::Var.new(name.text, nil, nil) + expect(":") + var.type = type_specifier() + expect("=") + var.value = expression() + var + end + ####################################### # Expression Parsing ####################################### diff --git a/example.src b/example.src index 12e1857..bed21b6 100644 --- a/example.src +++ b/example.src @@ -7,7 +7,12 @@ cmd : [String] = true fetchsel(sel : String) { + foo : String = 123 + 1 + 1 return 0 + if 1 { return 5 } else {} + if 1 {} else if 1 {} + ## cmd[1] = sel; ## Posix.exec(cmd) } -- 2.52.0