public override string Dump() { StringBuilder sb = new StringBuilder(); for (FormatElement elem = Elements; elem != null; elem = elem.Next) { sb.Append(elem.Dump()); } return(sb.ToString()); }
public override void MarkUncomplited() { for (FormatElement elem = Elements; elem != null; elem = elem.Next) { if (elem.Type == FormatElementEnum.EXPR) { Expr expr = elem.Data.GetValue <Expr>(); expr.MarkUncomplited(); } } }
// Replacement for: element_t& operator=(const element_t& elem) public FormatElement Assign(FormatElement element) { if (element != this) { IsElementAlignLeft = element.IsElementAlignLeft; Type = element.Type; MinWidth = element.MinWidth; MaxWidth = element.MaxWidth; Data.SetValue(element.Data); } return(this); }
/// <summary> /// Ported from format_t::element_t * format_t::parse_elements /// </summary> private FormatElement ParseElements(string fmt, Format tmpl = null) { FormatElement result = null; FormatElement current = null; string q = string.Empty; InputTextStream inStream = new InputTextStream(fmt); for (char p = inStream.Peek; !inStream.Eof; inStream.Get(), p = inStream.Peek) { if (p != '%' && p != '\\') { q += p; continue; } if (result == null) { result = new FormatElement(); current = result; } else { current.Next = new FormatElement(); current = current.Next; } if (!String.IsNullOrEmpty(q)) { current.Type = FormatElementEnum.STRING; current.Data.SetValue(q); q = string.Empty; current.Next = new FormatElement(); current = current.Next; } if (p == '\\') { inStream.Get(); p = inStream.Peek; current.Type = FormatElementEnum.STRING; switch (p) { case 'b': current.Data.SetValue("\b"); break; case 'f': current.Data.SetValue("\f"); break; case 'n': current.Data.SetValue("\n"); break; case 'r': current.Data.SetValue("\r"); break; case 't': current.Data.SetValue("\t"); break; case 'v': current.Data.SetValue("\v"); break; case '\\': current.Data.SetValue("\\"); break; default: current.Data.SetValue(new string(p, 1)); break; } continue; } inStream.Get(); p = inStream.Peek; // cut '%' or '\\' while (p == '-') { current.IsElementAlignLeft = true; inStream.Get(); p = inStream.Peek; } current.MinWidth = inStream.ReadInt(0, out p); if (p == '.') { current.MaxWidth = inStream.ReadInt(0, out p); p = inStream.Peek; if (current.MinWidth == 0) { current.MinWidth = current.MaxWidth; } } if (Char.IsLetter(p)) { string sExpr; if (SingleLetterMapping.TryGetValue(p, out sExpr)) { if (sExpr.Contains('$')) { sExpr = sExpr.Replace("$min", current.MinWidth > 0 ? current.MinWidth.ToString() : "-1"). Replace("$max", current.MaxWidth > 0 ? current.MaxWidth.ToString() : "-1"). Replace("$left", current.IsElementAlignLeft ? "false" : "true"); if (sExpr.Contains('$')) { throw new InvalidOperationException("Unrecognized format substitution keyword"); } } current.Type = FormatElementEnum.EXPR; current.Data.SetValue(new Expr(sExpr)); } else { throw new FormatError(String.Format(FormatError.ErrorMessageUnrecognizedFormattingCharacterSmth, p)); } } else { switch (p) { case '%': current.Type = FormatElementEnum.STRING; current.Data.SetValue("%"); break; case '$': { if (tmpl == null) { throw new FormatError(FormatError.ErrorMessagePriorFieldReferenceButNoTemplate); } inStream.Get(); p = inStream.Peek; if (p == '0' || (!Char.IsDigit(p) && p != 'A' && p != 'B' && p != 'C' && p != 'D' && p != 'E' && p != 'F')) { throw new FormatError(FormatError.ErrorMessageFieldReferenceMustBeADigitFrom1To9); } int index = char.IsDigit(p) ? p - '0' : (p - 'A' + 10); FormatElement tmplElem = tmpl.Elements; for (int i = 1; i < index && tmplElem != null; i++) { tmplElem = tmplElem.Next; while (tmplElem != null && tmplElem.Type != FormatElementEnum.EXPR) { tmplElem = tmplElem.Next; } } if (tmplElem == null) { throw new FormatError(FormatError.ErrorMessageReferenceToANonExistentPriorField); } current.Assign(tmplElem); break; } case '(': case '{': { bool formatAmount = p == '{'; current.Type = FormatElementEnum.EXPR; current.Data.SetValue(ParseSingleExpression(inStream)); // Wrap the subexpression in calls to justify and scrub if (!formatAmount) { break; } ExprOp op = current.Data.GetValue <Expr>().Op; #region Create Expressions ExprOp call2Node = new ExprOp(OpKindEnum.O_CALL); call2Node.Left = IdentNode("justify"); ExprOp args3Node = new ExprOp(OpKindEnum.O_CONS); ExprOp call1Node = new ExprOp(OpKindEnum.O_CALL); call1Node.Left = IdentNode("scrub"); call1Node.Right = op.Kind == OpKindEnum.O_CONS ? op.Left : op; args3Node.Left = call1Node; ExprOp args2Node = new ExprOp(OpKindEnum.O_CONS); ExprOp arg1Node = new ExprOp(OpKindEnum.VALUE); arg1Node.AsValue = Value.Get(current.MinWidth > 0 ? current.MinWidth : -1); args2Node.Left = arg1Node; ExprOp args1Node = new ExprOp(OpKindEnum.O_CONS); ExprOp arg2Node = new ExprOp(OpKindEnum.VALUE); arg2Node.AsValue = Value.Get(current.MaxWidth > 0 ? current.MaxWidth : -1); args1Node.Left = arg2Node; ExprOp arg3Node = new ExprOp(OpKindEnum.VALUE); arg3Node.AsValue = Value.Get(!current.IsElementAlignLeft); args1Node.Right = arg3Node; args2Node.Right = args1Node; args3Node.Right = args2Node; call2Node.Right = args3Node; #endregion current.MinWidth = 0; current.MaxWidth = 0; string prevExpr = current.Data.GetValue <Expr>().Text; ExprOp colorizeOp = null; if (op.Kind == OpKindEnum.O_CONS && op.HasRight) { colorizeOp = op.Right; } if (colorizeOp != null) { ExprOp call3Node = new ExprOp(OpKindEnum.O_CALL); call3Node.Left = IdentNode("ansify_if"); ExprOp args4Node = new ExprOp(OpKindEnum.O_CONS); args4Node.Left = call2Node; // from above args4Node.Right = colorizeOp; call3Node.Right = args4Node; current.Data.SetValue(new Expr(call3Node)); } else { current.Data.SetValue(new Expr(call2Node)); } current.Data.GetValue <Expr>().Text = prevExpr; break; } default: throw new FormatError(String.Format(FormatError.ErrorMessageUnrecognizedFormattingCharacterSmth, p)); } } } if (!string.IsNullOrEmpty(q)) { if (result == null) { result = new FormatElement(); current = result; } else { current.Next = new FormatElement(); current = current.Next; } current.Type = FormatElementEnum.STRING; current.Data.SetValue(q); } return(result); }
protected override string RealCalc(Scope scope) { StringBuilder outStr = new StringBuilder(); for (FormatElement elem = Elements; elem != null; elem = elem.Next) { string s; switch (elem.Type) { case FormatElementEnum.STRING: string stringFormat = StringExtensions.GetWidthAlignFormatString(elem.MinWidth, !elem.IsElementAlignLeft); s = String.Format(stringFormat, elem.Data.GetValue <string>()); break; case FormatElementEnum.EXPR: Expr expr = new Expr(elem.Data.GetValue <Expr>()); try { expr.Compile(scope); Value value; if (expr.IsFunction) { CallScope args = new CallScope(scope); args.PushBack(Value.Get(elem.MaxWidth)); value = expr.GetFunction()(args); } else { value = expr.Calc(scope); } Logger.Current.Debug("format.expr", () => String.Format("value = ({0})", value)); if (elem.MinWidth > 0) { s = value.Print(elem.MinWidth, -1, elem.IsElementAlignLeft ? AmountPrintEnum.AMOUNT_PRINT_NO_FLAGS : AmountPrintEnum.AMOUNT_PRINT_RIGHT_JUSTIFY); } else { s = value.ToString(); } } catch { string currentContext = ErrorContext.Current.GetContext(); ErrorContext.Current.AddErrorContext("While calculating format expression:"); ErrorContext.Current.AddErrorContext(expr.ContextToStr()); if (!String.IsNullOrEmpty(currentContext)) { ErrorContext.Current.AddErrorContext(currentContext); } throw; } break; default: throw new InvalidOperationException("Unknown enum item"); } if (elem.MaxWidth > 0 || elem.MinWidth > 0) { string result; if (elem.MaxWidth > 0 && elem.MaxWidth < s.Length) { result = Truncate(s, elem.MaxWidth); } else { result = s; if (elem.MinWidth > s.Length) { result = result + new String(' ', s.Length - elem.MinWidth); } } outStr.Append(result); } else { outStr.Append(s); } } return(outStr.ToString()); }