package polyglot.parse;

import polyglot.ast.*;
import polyglot.parse.*;
import polyglot.types.*;
import polyglot.util.*;

/**
 * Represents an ambiguous, possibly qualified, identifier encountered while parsing.
 */
public class Name {
	public final Name prefix;
	public final String name;
	public final Position pos;
	public final NodeFactory nf;
	public final TypeSystem ts;

	public Name(BaseParser parser, Position pos, String name) {
		this(parser, pos, null, name);
	}

	public Name(BaseParser parser, Position pos, Name prefix, String name) {
		this.nf = parser.nf;
		this.ts = parser.ts;
		this.pos = pos;
		this.prefix = prefix;
		this.name = name;
	}

	// expr
	public Expr toExpr() {
		if (prefix == null) {
			return nf.AmbExpr(pos, name);
		}

		return nf.Field(pos, prefix.toReceiver(), name);
	}

	// expr or type
	public Receiver toReceiver() {
		if (prefix == null) {
			return nf.AmbReceiver(pos, name);
		}

		return nf.AmbReceiver(pos, prefix.toPrefix(), name);
	}

	// expr, type, or package
	public Prefix toPrefix() {
		if (prefix == null) {
			return nf.AmbPrefix(pos, name);
		}

		return nf.AmbPrefix(pos, prefix.toPrefix(), name);
	}

	// type or package
	public QualifierNode toQualifier() {
		if (prefix == null) {
			return nf.AmbQualifierNode(pos, name);
		}

		return nf.AmbQualifierNode(pos, prefix.toQualifier(), name);
	}

	// package
	public PackageNode toPackage() {
                if (prefix == null) {
                    return nf.PackageNode(pos, ts.createPackage(null, name));
                }
                else {
                    return nf.PackageNode(pos, ts.createPackage(prefix.toPackage().package_(), name));
                }
	}

	// type
	public TypeNode toType() {
		if (prefix == null) {
			return nf.AmbTypeNode(pos, name);
		}

		return nf.AmbTypeNode(pos, prefix.toQualifier(), name);
	}

	public String toString() {
		if (prefix == null) {
			return name;
		}

		return prefix.toString() + "." + name;
	}
}

@@ -614,32 +614,412 @@
 ;%0A%09%09
-this.prefix = prefix;%0A%09%09
+%0A%09%09if (! StringUtil.isNameShort(name)) %7B%0A%09%09    if (prefix == null) %7B%0A%09%09%09this.prefix = new Name(parser, pos, StringUtil.getPackageComponent(name));%0A%09%09%09this.name = StringUtil.getShortNameComponent(name);%0A%09%09    %7D%0A%09%09    else %7B%0A%09%09%09throw new InternalCompilerError(%22Can only construct a qualified Name with a short name string: %22 + name + %22 is not short.%22);%0A%09%09    %7D%0A%09%09%7D%0A%09%09else %7B%0A%09%09    this.prefix = null;%0A%09%09    
 this
@@ -1032,16 +1032,20 @@
 = name;%0A
+%09%09%7D%0A
 %09%7D%0A%0A%09// 

Allow qualified names to be passed into the constructor.