From 2c575b7740f67c58ebdf41db7caa488f907c8e79 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Sun, 3 Nov 2024 21:44:01 -0500 Subject: [PATCH] added qualified_identifier rule --- lib/parser.rb | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/parser.rb b/lib/parser.rb index a33731b..49f0532 100644 --- a/lib/parser.rb +++ b/lib/parser.rb @@ -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 -- 2.55.0