/// <summary> /// Interpret CatExpression /// </summary> /// <param name="expression">CatExpression to interpret</param> public override void Visit(CatExpression expression) { //Concatenate two expressions String tempExpressionText = ""; //Visit left expression.GetLeftExpression().AcceptVisitor(this); tempExpressionText += TextValue; //Visit right expression.GetRightExpression().AcceptVisitor(this); tempExpressionText += TextValue; TextValue = tempExpressionText; }
/// <summary> /// Parse an CatExpression /// </summary> /// <param name="expression">Expression which is already parsed</param> /// <returns></returns> public Expression ParseCatExpression(Expression expression) { CatExpression catExpression = new CatExpression(); //Left part of catenation expression catExpression.SetLeftExpression(expression); //Skip + token NextToken("+", "expression + expression", '+'); //Parse right part of token catExpression.SetRightExpression(ParseExpression()); return(catExpression); }
public void ParseCatExpressionTest() { //Create parser and parse tokens ExpressionParser expressionParser = new ExpressionParser(Init("expression+'symbol")); Expression expression = expressionParser.ParseExpression(); //Check type of expression Assert.AreEqual(typeof(CatExpression), expression.GetType()); CatExpression parsedCatExpression = (CatExpression)expression; //Check expressions in catexpression Assert.AreEqual(typeof(VarExpression), parsedCatExpression.GetLeftExpression().GetType()); Assert.AreEqual(typeof(SymExpression), parsedCatExpression.GetRightExpression().GetType()); VarExpression left = (VarExpression)parsedCatExpression.GetLeftExpression(); SymExpression right = (SymExpression)parsedCatExpression.GetRightExpression(); Assert.AreEqual("expression", left.GetVariableIdentifier()); Assert.AreEqual("symbol", right.GetSym()); }
public void Visit(CatExpression x) { }
public AbstractType Visit(CatExpression x) { return(OpExpressionType(x)); }
public ISymbolValue Visit(CatExpression x) { return E_MathOp(x); }
ISymbolValue EvalConcatenation(CatExpression x, ISymbolValue lValue) { // In the (not unusual) case that more than 2 arrays/strings shall be concat'ed - process them more efficiently var catQueue = new Queue<ISymbolValue>(); var catEx = (x as CatExpression); catQueue.Enqueue(lValue); catEx = catEx.RightOperand as CatExpression; ISymbolValue r; while(catEx != null) { r = TryGetValue(catEx.LeftOperand != null ? catEx.LeftOperand.Accept(this) : null); if(r == null || r is NullValue) { EvalError(catEx.LeftOperand, "Couldn't be evaluated."); return null; } catQueue.Enqueue(r); if(catEx.RightOperand is CatExpression) catEx = catEx.RightOperand as CatExpression; else break; } var rightOp = (catEx ?? x).RightOperand; r = TryGetValue(rightOp != null ? rightOp.Accept(this) : null); if(r == null) { EvalError((catEx ?? x).LeftOperand, "Couldn't be evaluated."); return null; } catQueue.Enqueue(r); // Notable: If one element is of the value type of the array, the element is added (either at the front or at the back) to the array // myString ~ 'a' will append an 'a' to the string // 'a' ~ myString inserts 'a' at index 0 // Determine whether we have to build up a string OR a normal list of atomic elements bool isString = true; ArrayType lastArrayType = null; foreach(var e in catQueue) { if(e is AssociativeArrayValue) { EvalError(x, "Can't concatenate associative arrays", e); return null; } else if(e is ArrayValue) { if(lastArrayType != null && !ResultComparer.IsEqual(lastArrayType, e.RepresentedType)) { EvalError(x, "Both arrays must be of same type", new[]{lastArrayType, e.RepresentedType}); return null; } lastArrayType = e.RepresentedType as ArrayType; if((e as ArrayValue).IsString) continue; } else if(e is PrimitiveValue) { var btt = (e as PrimitiveValue).BaseTypeToken; if(btt == DTokens.Char || btt == DTokens.Dchar || btt == DTokens.Wchar) continue; } isString = false; } if(lastArrayType == null) { EvalError(x, "At least one operand must be an (non-associative) array. If so, the other operand must be of the array's element type.", catQueue.ToArray()); return null; } if(isString) { var sb = new StringBuilder(); while(catQueue.Count != 0) { var e = catQueue.Dequeue(); if(e is ArrayValue) sb.Append((e as ArrayValue).StringValue); else if(e is PrimitiveValue) sb.Append((char)((e as PrimitiveValue).Value)); } return new ArrayValue(GetStringType(LiteralSubformat.Utf8), sb.ToString()); } var elements = new List<ISymbolValue>(); while(catQueue.Count != 0) { var e = catQueue.Dequeue(); var av = e as ArrayValue; if(av != null) { if(av.IsString) elements.Add(av); else if(av.Elements != null) elements.AddRange(av.Elements); continue; } if(!ResultComparer.IsImplicitlyConvertible(e.RepresentedType, lastArrayType.ValueType, ctxt)) { EvalError(x, "Element with type " + (e.RepresentedType != null ? e.RepresentedType.ToCode() : "") + " doesn't fit into array with type "+lastArrayType.ToCode(), catQueue.ToArray()); return null; } elements.Add(e); } return new ArrayValue(lastArrayType, elements.ToArray()); }
/// <summary> /// Note: Add, Multiply as well as Cat Expressions are parsed in this method. /// </summary> IExpression AddExpression(IBlockNode Scope = null) { var left = UnaryExpression(Scope); OperatorBasedExpression ae = null; switch (laKind) { case Plus: case Minus: ae = new AddExpression(laKind == Minus); break; case Tilde: ae = new CatExpression(); break; case Times: case Div: case Mod: ae = new MulExpression(laKind); break; default: return left; } Step(); ae.LeftOperand = left; ae.RightOperand = AddExpression(Scope); return ae; }
ISymbolValue EvalConcatenation(CatExpression x, ISymbolValue lValue) { // In the (not unusual) case that more than 2 arrays/strings shall be concat'ed - process them more efficiently var catQueue = new Queue <ISymbolValue>(); var catEx = (x as CatExpression); catQueue.Enqueue(lValue); catEx = catEx.RightOperand as CatExpression; ISymbolValue r; while (catEx != null) { r = TryGetValue(E(catEx.LeftOperand)); if (r == null) { EvalError(catEx.LeftOperand, "Couldn't be evaluated."); return(null); } catQueue.Enqueue(r); if (catEx.RightOperand is CatExpression) { catEx = catEx.RightOperand as CatExpression; } else { break; } } r = TryGetValue(E((catEx ?? x).RightOperand)); if (r == null) { EvalError(catEx.LeftOperand, "Couldn't be evaluated."); return(null); } catQueue.Enqueue(r); // Notable: If one element is of the value type of the array, the element is added (either at the front or at the back) to the array // myString ~ 'a' will append an 'a' to the string // 'a' ~ myString inserts 'a' at index 0 // Determine whether we have to build up a string OR a normal list of atomic elements bool isString = true; ArrayType lastArrayType = null; foreach (var e in catQueue) { if (e is AssociativeArrayValue) { EvalError(x, "Can't concatenate associative arrays", e); return(null); } else if (e is ArrayValue) { if (lastArrayType != null && !ResultComparer.IsEqual(lastArrayType, e.RepresentedType)) { EvalError(x, "Both arrays must be of same type", new[] { lastArrayType, e.RepresentedType }); return(null); } lastArrayType = e.RepresentedType as ArrayType; if ((e as ArrayValue).IsString) { continue; } } else if (e is PrimitiveValue) { var btt = (e as PrimitiveValue).BaseTypeToken; if (btt == DTokens.Char || btt == DTokens.Dchar || btt == DTokens.Wchar) { continue; } } isString = false; } if (lastArrayType == null) { EvalError(x, "At least one operand must be an (non-associative) array. If so, the other operand must be of the array's element type.", catQueue.ToArray()); return(null); } if (isString) { var sb = new StringBuilder(); while (catQueue.Count != 0) { var e = catQueue.Dequeue(); if (e is ArrayValue) { sb.Append((e as ArrayValue).StringValue); } else if (e is PrimitiveValue) { sb.Append((char)((e as PrimitiveValue).Value)); } } return(new ArrayValue(GetStringType(LiteralSubformat.Utf8), sb.ToString())); } var elements = new List <ISymbolValue>(); while (catQueue.Count != 0) { var e = catQueue.Dequeue(); var av = e as ArrayValue; if (av != null) { if (av.IsString) { elements.Add(av); } else if (av.Elements != null) { elements.AddRange(av.Elements); } continue; } if (!ResultComparer.IsImplicitlyConvertible(e.RepresentedType, lastArrayType.ValueType, ctxt)) { EvalError(x, "Element with type " + e.RepresentedType.ToCode() + " doesn't fit into array with type " + lastArrayType.ToCode(), catQueue.ToArray()); return(null); } elements.Add(e); } return(new ArrayValue(lastArrayType, elements.ToArray())); }
public virtual void Visit(CatExpression expression) { VisitSubNodes(expression); }
public ISymbolValue Visit(CatExpression x) { return(E_MathOp(x)); }