]> git.mdlowis.com Git - proto/cerise-c.git/commitdiff
added qualified_identifier rule
authorMichael D. Lowis <mike@mdlowis.com>
Mon, 4 Nov 2024 02:44:01 +0000 (21:44 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Mon, 4 Nov 2024 02:44:01 +0000 (21:44 -0500)
lib/parser.rb

index a33731bb899b31a73492b0f632d45437fa696c03..49f053205ddd5317d03153e005f7d9777739eb0e 100644 (file)
@@ -218,7 +218,7 @@ class Parser
     if accept(:record)
       base_type = nil
       if accept("(")
-        base_type = identifier()
+        base_type = qualified_identifier()
         expect(")")
       end
       type = Value::Type.new(:record, {}, base_type, 0)
@@ -258,9 +258,30 @@ class Parser
     args
   end
 
+  def qualified_identifier()
+    tok = expect(:ident)
+    varname = IR::Var.new(tok.pos, nil, tok.text.to_sym, nil)
+    if matches(".")
+      mod = syms[varname.name]
+      if mod.nil?
+        error("no such module: '#{varname.name}'")
+      end
+      if mod.kind != :module
+        error("accessing field in object that is neither a record nor a module")
+      end
+      tok = consume()
+      sym = mod.type.exports[tok.text.to_sym]
+      if not sym
+        error("module or record has no such field '#{tok.text}'")
+      end
+      varname = IR::Var.new(tok.pos, sym[:type], tok.text.to_sym, varname.name)
+    end
+    varname
+  end
+
   def identifier()
-    name = expect(:ident)
-    IR::Var.new(name.pos, nil, name.text.to_sym)
+    tok = expect(:ident)
+    IR::Var.new(tok.pos, nil, tok.text.to_sym, nil)
   end
 
   def type_specifier()
@@ -269,7 +290,7 @@ class Parser
       type = Value::Type.new(:array, nil, base_type, 0)
       expect("]")
     else
-      type = expect(:ident).text.to_sym
+      type = qualified_identifier()
     end
     type
   end
@@ -485,20 +506,7 @@ class Parser
       elsif tok.type == :void
         IR::Const.new(tok.pos, :void, :void)
       elsif tok.type == :ident
-        varname = IR::Var.new(tok.pos, nil, tok.text.to_sym, nil)
-        if accept(".")
-          mod = syms[varname.name]
-          if mod.kind != :module
-            error("accessing field in object that is neither a record nor a module")
-          end
-          tok = consume()
-          sym = mod.type.exports[tok.text.to_sym]
-          if not sym
-            error("module or record has no such field '#{tok.text}'")
-          end
-          varname = IR::Var.new(tok.pos, sym[:type], tok.text.to_sym, varname.name)
-        end
-        varname
+        qualified_identifier()
       else
         error("invalid constant #{tok}")
       end