]> git.mdlowis.com Git - proto/sclpl-rb.git/commitdiff
implemented statement parsing
authorMichael D. Lowis <mike@mdlowis.com>
Tue, 28 Jan 2020 03:22:09 +0000 (22:22 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Tue, 28 Jan 2020 03:22:09 +0000 (22:22 -0500)
compile.rb
example.src

index 5fb23e57a4343dd041c824d2945d345198ec1e56..9f3fdba44e2ac951b48c74fd6139b7a934792455 100755 (executable)
@@ -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
   #######################################
index 12e185741d51c347f7e13540ea290062d4350156..bed21b6c94490861b1a886754fc7f89499601cef 100644 (file)
@@ -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)
 }