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)
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()
type = Value::Type.new(:array, nil, base_type, 0)
expect("]")
else
- type = expect(:ident).text.to_sym
+ type = qualified_identifier()
end
type
end
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