]> git.mdlowis.com Git - proto/sclpl-rb.git/commitdiff
fixed up array and assignment parsing
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 1 Feb 2020 19:32:37 +0000 (14:32 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 1 Feb 2020 19:32:37 +0000 (14:32 -0500)
compile.rb
example.src

index 1dec61fbed68700a5ce5014652070d970a35701c..a6eb88cd158a3f92202be107c9c75bc03d3fbf11 100755 (executable)
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'strscan'
-require 'pp'
 
 module Type
   Nil = Struct.new(:value)
@@ -15,13 +14,13 @@ module Type
 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 = {
@@ -141,6 +140,7 @@ class Parser
     "-"     => { 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   },
@@ -219,11 +219,12 @@ class Parser
       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
@@ -341,7 +342,7 @@ class Parser
   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("=")
@@ -350,11 +351,11 @@ class Parser
   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
 
@@ -374,8 +375,8 @@ class Parser
     (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)
@@ -386,13 +387,14 @@ class Parser
     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)
@@ -403,18 +405,18 @@ class Parser
 
   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()
index 9aa2bd48f492f432d9ccf314ec47d3a7b2dcb663..b1de7e72ff3ad93275aa81271fcce98b812a1c97 100644 (file)
@@ -5,22 +5,22 @@ cmd : ?[String] = true
 
 fetchsel(sel : String)
 {
-#    foo : String = 123
-#    if 1 { return 5 } else {}
-#    if 1 {} else if 1 {}
-    cmd[1] = sel
-#    1 + 1
-#    Posix.exec(cmd)
-#    return 0
+    foo : String = 123
+    foo = 3
+    Posix.exec(cmd)
+    if 1 { return 5 } else {}
+    if 1 {} else if 1 {}
+    cmd[1] = 1 + 2 * 5
+    return 0
 }
 
-#main(args : [String]) : Int
-#{
-##    x : X11.Config = 0
-##    X11.init(x)
-##    X11.mkwin(x, 1, 1, X11.PropertyChangeMask)
-##    XSel.init(x)
-##    X11.loop(x, nil)
-##    return 0
-#}
+$main(args : [String]) : Int
+{
+    x : X11.Config = 0
+    X11.init(x)
+    X11.mkwin(x, 1, 1, X11.PropertyChangeMask)
+    XSel.init(x)
+    X11.loop(x, nil)
+    return 0
+}