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; } } } }