using System;
using System.Collections.Generic;
using System.Text;
using Iesi.Collections;
using System.Collections;
using CLab.Exceptions;
using CLab.Auxiliary;
namespace CLab
{
public class Symbols
{
private CP cp;
//Type variables
private Set allTypes;
private Set enumerationTypes;
private Hashtable enumerationItems; //enumTypeElems
private Set allEnumerationItems; //allEnums
private Set rangeTypes; //rngTypes
//Variable variables
private Set allVariables;
private Set enumerationVariables;//enumVars
private Hashtable enumerationVariableType;
private Set rangeVariables;
private Set boolVariables;
//Other
private StringComparer stringComparer;
public Symbols(CP cp)
{
stringComparer = StringComparer.Create(System.Globalization.CultureInfo.CurrentCulture, true);
this.cp = cp;
//Type variables
allTypes = new HybridSet();
enumerationTypes = new HybridSet();
enumerationItems = new Hashtable(stringComparer);
allEnumerationItems = new HybridSet();
rangeTypes = new HybridSet();
//Variable variables
allVariables = new HybridSet();
enumerationVariables = new HybridSet();
enumerationVariableType = new Hashtable(stringComparer);
rangeVariables = new HybridSet();
boolVariables = new HybridSet();
FillAndCheckType();
FillAndCheckVar();
}
public void FillAndCheckType()
{
for (int i = 0; i < cp.Types.Count; i++)
{
if (allTypes.Contains(cp.Types[i].TypeName.ToLower()))
{
// throw new DuplicateTypeException(((Type)cp.Types[i]).TypeName);
}
else allTypes.Add(cp.Types[i].TypeName.ToLower());
switch (cp.Types[i].GetType().ToString())
{
case "CLab.TypeEnumeration":
{
TypeEnumeration tvl = (TypeEnumeration)cp.Types[i];
if (tvl.EnumeratorsList.Count < 2)
{
//throw new singleItemInListException(cp.Types[i].GetType().ToString());
}
else enumerationTypes.Add(cp.Types[i].TypeName.ToLower());
Set valueSet = new HybridSet();
foreach (String value in tvl.EnumeratorsList)
{
if (allTypes.Contains(value.ToLower()))
{
//throw new valueAllreadyInListEzxception;
}
else valueSet.Add(value.ToLower());
}
allEnumerationItems = (Set) allEnumerationItems.Union(valueSet);
enumerationItems[cp.Types[i].TypeName] = SetOf(((TypeEnumeration)cp.Types[i]).EnumeratorsList);
}
break;
case "CLab.TypeRange":
{
TypeRange tr = (TypeRange)cp.Types[i];
if (tr.EndOfRange - tr.StartOfRange + 1 < 2)
{
//trow new rangeTooSmallException;
}
else rangeTypes.Add(cp.Types[i].TypeName.ToLower());
}
break;
default: //throw new switchCaseNotCoveredException;
break;
}
}
}
public void FillAndCheckVar()
{
for (int i = 0; i < cp.Variables.Count; i++)
{
Variable var = cp.Variables[i];
if (allVariables.Contains(var.VariableName.ToLower()))
{
throw new Exception("Symbols");
//variabel allerede deklarert
}
if (allEnumerationItems.Contains(var.VariableName.ToLower()))
{
throw new Exception("Symbols");
//krasj med domenenavnverdi
}
allVariables.Add(var.VariableName.ToLower());
//if (cp.Variables[i].TypeName.Equals("bool"))
if (string.Compare(cp.Variables[i].TypeName, "bool", true) == 0)
boolVariables.Add(var.VariableName.ToLower());
else
{
if (!allTypes.Contains(var.TypeName.ToLower()))
{
throw new Exception("symbols");
//Exception: Variabeltype er ikke deklarert og ikke bool
}
//Variable of valuelist type
if (enumerationTypes.Contains(var.TypeName.ToLower()))
{
enumerationVariables.Add(var.VariableName.ToLower());
Console.WriteLine("test " +var.VariableName);
enumerationVariableType[var.VariableName] = var.TypeName;
}
//Variable of range type
else
rangeVariables.Add(var.VariableName.ToLower());
}
}
}
public void TypeCheck(Expression expression)
{
switch (expression.Type)
{
case Common.ExprType.et_id:
IdExpression idExpression = (IdExpression)expression;
if (!allVariables.Contains(idExpression.Id.ToLower()) & !allEnumerationItems.Contains(idExpression.Id.ToLower()))
throw new ClabTypeCheckException(String.Format("Variable or enumeration constant {0} is not declared", idExpression.Id));
if (enumerationVariables.Contains(idExpression.Id.ToLower()))
throw new ClabTypeCheckException(String.Format("Illegal enumeration expression for enumeration variable {0}", idExpression.Id));
if (allEnumerationItems.Contains(idExpression.Id.ToLower()))
throw new ClabTypeCheckException(String.Format("Illegal enumeration expression for enumeration constant {0}", idExpression.Id));
break;
case Common.ExprType.et_eq:
case Common.ExprType.et_ne:
BinaryExpression binExpression = (BinaryExpression)expression;
bool enumerationVariablesLeft = false;
bool enumerationVariablesRight = false;
bool allEnumerationItemsLeft = false;
bool allEnumerationItemsRight = false;
String var = "";
String item = "";
//Checking left side
if (binExpression.Left.Type.Equals(Common.ExprType.et_id))
{
IdExpression leftIdExpression = (IdExpression)binExpression.Left;
if (!allVariables.Contains(leftIdExpression.Id.ToLower()) & !allEnumerationItems.Contains(leftIdExpression.Id.ToLower()))
throw new ClabTypeCheckException(String.Format("Left argument {0} of ==/!= expression {1} is not a declared variable or enumeration constant", leftIdExpression.Id, expression));
else if (enumerationVariables.Contains(leftIdExpression.Id.ToLower()))
{
enumerationVariablesLeft = true;
var = leftIdExpression.Id;
}
else if (allEnumerationItems.Contains(leftIdExpression.Id.ToLower()))
{
allEnumerationItemsLeft = true;
item = leftIdExpression.Id;
}
}
//Checking right side
if (binExpression.Right.Type.Equals(Common.ExprType.et_id))
{
IdExpression rightIdExpression = (IdExpression)binExpression.Right;
if (!allVariables.Contains(rightIdExpression.Id.ToLower()) & !allEnumerationItems.Contains(rightIdExpression.Id.ToLower()))
{
if (!allVariables.Contains(rightIdExpression.Id.ToLower()))
Console.WriteLine("!allVariables. Count = " + allVariables.Count);
if (!allEnumerationItems.Contains(rightIdExpression.Id.ToLower()))
Console.WriteLine("!allEnumerationItems. Count = " + allEnumerationItems.Count);
throw new ClabTypeCheckException(String.Format("Right argument {0} of ==/!= expression {1} is not a declared variable or enumeration constant", rightIdExpression.Id, expression));
}
else if (enumerationVariables.Contains(rightIdExpression.Id.ToLower()))
{
enumerationVariablesRight = true;
var = rightIdExpression.Id;
}
else if (allEnumerationItems.Contains(rightIdExpression.Id.ToLower()))
{
allEnumerationItemsRight = true;
item = rightIdExpression.Id;
}
}
//If either an enum variable or const on left or right side we can check without a recursive call
if (enumerationVariablesLeft | enumerationVariablesRight | allEnumerationItemsLeft | allEnumerationItemsRight)
{
if (enumerationVariablesLeft & allEnumerationItemsRight | enumerationVariablesRight & allEnumerationItemsLeft)
{
if (!((Set)enumerationItems[enumerationVariableType[var]]).Contains(item.ToLower()))
throw new ClabTypeCheckException(String.Format("In some == or != expression: the enumeration constant {0} is not a member of {1}'s enumeration type {2} ={3}", item, var, enumerationVariableType[var], ((TypeEnumeration)enumerationItems[enumerationVariableType[var]]).GetDomain));
}
else
//Illegal enum expression
{
String error = "Error in some ==/!= expression involving\n";
if (!var.Equals("")) error += "\tEnumeration variable: " + var + "\n";
if (!item.Equals("")) error += "\tEnumeration constant: " + item + "\n";
throw new ClabTypeCheckException(error);
}
}
else
{
//Not an enum expression - Make recursive check
TypeCheck(binExpression.Left);
TypeCheck(binExpression.Right);
}
break;
case Common.ExprType.et_val:
//Leaf case always ok
break;
case Common.ExprType.et_neg:
case Common.ExprType.et_not:
NotNegExpression nnExpression = (NotNegExpression)expression;
TypeCheck(nnExpression.Left);
break;
case Common.ExprType.et_impl:
case Common.ExprType.et_or:
case Common.ExprType.et_and:
case Common.ExprType.et_lte:
case Common.ExprType.et_gte:
case Common.ExprType.et_lt:
case Common.ExprType.et_gt:
case Common.ExprType.et_minus:
case Common.ExprType.et_plus:
case Common.ExprType.et_mod:
case Common.ExprType.et_div:
case Common.ExprType.et_times:
binExpression = (BinaryExpression)expression;
//Not an enum expression - Make recursive check
TypeCheck(binExpression.Left);
TypeCheck(binExpression.Right);
break;
default:
throw new ClabTypeCheckException("Symbols.cs: Typecheck(Expression) : switch case not covered");
}
}
///
/// Makes a Set out of a List of Strings
///
///
///
public Set SetOf(List list)
{
Set res = new HybridSet();
foreach (String s in list)
{
res.Add(s.ToLower());
}
return res;
}
/*
* added by yngve 24.02.2006
*/
public Set EnumerationVariables
{
get { return this.enumerationVariables; }
set { this.enumerationVariables = value; }
}
public Set AllVariables
{
get { return allVariables; }
}
public Set RangeVariables
{
get { return rangeVariables; }
set { rangeVariables = value; }
}
public Set BoolVariables
{
get { return boolVariables; }
set { boolVariables = value; }
}
}
}