/*
 * [The "BSD license"]
 *  Copyright (c) 2010 Terence Parr
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.antlr.tool;

import org.antlr.codegen.CodeGenerator;
import org.antlr.runtime.Token;

import java.util.*;

/** Track the attributes within a scope.  A named scoped has just its list
 *  of attributes.  Each rule has potentially 3 scopes: return values,
 *  parameters, and an implicitly-named scope (i.e., a scope defined in a rule).
 *  Implicitly-defined scopes are named after the rule; rules and scopes then
 *  must live in the same name space--no collisions allowed.
 */
public class AttributeScope {

	/** All token scopes (token labels) share the same fixed scope of
	 *  of predefined attributes.  I keep this out of the runtime.Token
	 *  object to avoid a runtime space burden.
	 */
	public static AttributeScope tokenScope = new AttributeScope("Token",null);
	static {
		tokenScope.addAttribute("text", null);
		tokenScope.addAttribute("type", null);
		tokenScope.addAttribute("line", null);
		tokenScope.addAttribute("index", null);
		tokenScope.addAttribute("pos", null);
		tokenScope.addAttribute("channel", null);
		tokenScope.addAttribute("tree", null);
		tokenScope.addAttribute("int", null);
	}

	/** This scope is associated with which input token (for error handling)? */
	public Token derivedFromToken;

	public Grammar grammar;

	/** The scope name */
	private String name;

	/** Not a rule scope, but visible to all rules "scope symbols { ...}" */
	public boolean isDynamicGlobalScope;

	/** Visible to all rules, but defined in rule "scope { int i; }" */
	public boolean isDynamicRuleScope;

	public boolean isParameterScope;

	public boolean isReturnScope;

	public boolean isPredefinedRuleScope;

	public boolean isPredefinedLexerRuleScope;

	/** The list of Attribute objects */
	protected LinkedHashMap<String,Attribute> attributes = new LinkedHashMap();

	/* Placeholder for compatibility with the CSharp3 target. */
	public LinkedHashMap<String, GrammarAST> actions = new LinkedHashMap();

	public AttributeScope(String name, Token derivedFromToken) {
		this(null,name,derivedFromToken);
	}

	public AttributeScope(Grammar grammar, String name, Token derivedFromToken) {
		this.grammar = grammar;
		this.name = name;
		this.derivedFromToken = derivedFromToken;
	}

	public String getName() {
		if ( isParameterScope ) {
			return name+"_parameter";
		}
		else if ( isReturnScope ) {
			return name+"_return";
		}
		return name;
	}

	/** From a chunk of text holding the definitions of the attributes,
	 *  pull them apart and create an Attribute for each one.  Add to
	 *  the list of attributes for this scope.  Pass in the character
	 *  that terminates a definition such as ',' or ';'.  For example,
	 *
	 *  scope symbols {
	 *  	int n;
	 *  	List names;
	 *  }
	 *
	 *  would pass in definitions equal to the text in between {...} and
	 *  separator=';'.  It results in two Attribute objects.
	 */
	public void addAttributes(String definitions, int separator) {
		List<String> attrs = new ArrayList<String>();
		CodeGenerator.getListOfArgumentsFromAction(definitions,0,-1,separator,attrs);
		for (String a : attrs) {
			Attribute attr = new Attribute(a);
			if ( !isReturnScope && attr.initValue!=null ) {
				ErrorManager.grammarError(ErrorManager.MSG_ARG_INIT_VALUES_ILLEGAL,
										  grammar,
										  derivedFromToken,
										  attr.name);
				attr.initValue=null; // wipe it out
			}
			attributes.put(attr.name, attr);
		}
	}

	public void addAttribute(String name, String decl) {
		attributes.put(name, new Attribute(name,decl));
	}

	/** Given @scope::name {action} define it for this attribute scope. Later,
	 *  the code generator will ask for the actions table.
	 */
	public final void defineNamedAction(GrammarAST nameAST, GrammarAST actionAST)
	{
		String actionName = nameAST.getText();
		GrammarAST a = actions.get(actionName);
		if (a != null) {
			ErrorManager.grammarError(ErrorManager.MSG_ACTION_REDEFINITION,
									  grammar,
									  nameAST.getToken(),
									  nameAST.getText());
		} else {
			actions.put(actionName, actionAST);
		}
	}

	public Attribute getAttribute(String name) {
		return (Attribute)attributes.get(name);
	}

	/** Used by templates to get all attributes */
	public List<Attribute> getAttributes() {
		List<Attribute> a = new ArrayList<Attribute>();
		a.addAll(attributes.values());
		return a;
	}

	/** Return the set of keys that collide from
	 *  this and other.
	 */
	public Set intersection(AttributeScope other) {
		if ( other==null || other.size()==0 || size()==0 ) {
			return null;
		}
		Set inter = new HashSet();
		Set thisKeys = attributes.keySet();
		for (Iterator it = thisKeys.iterator(); it.hasNext();) {
			String key = (String) it.next();
			if ( other.attributes.get(key)!=null ) {
				inter.add(key);
			}
		}
		if ( inter.size()==0 ) {
			return null;
		}
		return inter;
	}

	public int size() {
		return attributes==null?0:attributes.size();
	}

	public String toString() {
		return (isDynamicGlobalScope?"global ":"")+getName()+":"+attributes;
	}
}
