/// <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); }
/// <summary> /// Ported from void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags) /// </summary> public void Next(InputTextStream inStream, AmountParseFlagsEnum pflags) { if (inStream.Eof) { Kind = ExprTokenKind.TOK_EOF; return; } char c = inStream.PeekNextNonWS(); if (inStream.Eof) { Kind = ExprTokenKind.TOK_EOF; return; } Symbol = new string(c, 1); Length = 1; switch (c) { case '&': inStream.Get(); c = inStream.Peek; if (c == '&') { c = inStream.Get(); Length = 2; } Kind = ExprTokenKind.KW_AND; break; case '|': inStream.Get(); c = inStream.Peek; if (c == '|') { c = inStream.Get(); Length = 2; } Kind = ExprTokenKind.KW_OR; break; case '(': c = inStream.Get(); Kind = ExprTokenKind.LPAREN; break; case ')': c = inStream.Get(); Kind = ExprTokenKind.RPAREN; break; case '[': { c = inStream.Get(); string buf; Length += inStream.ReadInto(out buf, out c, ch => ch != ']'); if (c != ']') { Expected(']', c); } c = inStream.Get(); Length++; DateInterval timespan = new DateInterval(buf); Date? begin = timespan.Begin; if (!begin.HasValue) { throw new ParseError(ParseError.ParseError_DateSpecifierDoesNotReferToAStartingDate); } Kind = ExprTokenKind.VALUE; Value = Value.Get(begin.Value); break; } case '\'': case '"': { char delim = inStream.Get(); string buf; Length += inStream.ReadInto(out buf, out c, ch => ch != delim); if (c != delim) { Expected(delim, c); } c = inStream.Get(); Length++; Kind = ExprTokenKind.VALUE; Value = Value.Get(buf, true); // [DM] It equals to 'value.set_string(buf);' break; } case '{': { c = inStream.Get(); Amount temp = new Amount(); temp.Parse(inStream, AmountParseFlagsEnum.PARSE_NO_MIGRATE); c = inStream.Get(); if (c != '}') { Expected('}', c); } Length++; Kind = ExprTokenKind.VALUE; Value = Value.Get(temp); break; } case '!': inStream.Get(); c = inStream.Peek; if (c == '=') { c = inStream.Get(); Symbol = "!="; Kind = ExprTokenKind.NEQUAL; Length = 2; break; } else if (c == '~') { c = inStream.Get(); Symbol = "!~"; Kind = ExprTokenKind.NMATCH; Length = 2; break; } Kind = ExprTokenKind.EXCLAM; break; case '-': inStream.Get(); c = inStream.Peek; if (c == '>') { c = inStream.Get(); Symbol = "->"; Kind = ExprTokenKind.ARROW; Length = 2; break; } Kind = ExprTokenKind.MINUS; break; case '+': c = inStream.Get(); Kind = ExprTokenKind.PLUS; break; case '*': c = inStream.Get(); Kind = ExprTokenKind.STAR; break; case '?': c = inStream.Get(); Kind = ExprTokenKind.QUERY; break; case ':': inStream.Get(); c = inStream.Peek; Kind = ExprTokenKind.COLON; break; case '/': { c = inStream.Get(); if (pflags.HasFlag(AmountParseFlagsEnum.PARSE_OP_CONTEXT)) { // operator context Kind = ExprTokenKind.SLASH; } else { // terminal context // Read in the regexp string buf; Length += inStream.ReadInto(out buf, out c, ch => ch != '/'); if (c != '/') { Expected('/', c); } c = inStream.Get(); Length++; Kind = ExprTokenKind.VALUE; Value = Value.Get(new Mask(buf)); } break; } case '=': { inStream.Get(); c = inStream.Peek; if (c == '~') { c = inStream.Get(); Symbol = "=~"; Kind = ExprTokenKind.MATCH; Length = 2; break; } if (c == '=') { c = inStream.Get(); Symbol = "=="; Kind = ExprTokenKind.EQUAL; Length = 2; break; } Kind = ExprTokenKind.ASSIGN; break; } case '<': c = inStream.Get(); if (inStream.Peek == '=') { c = inStream.Get(); Symbol = "<="; Kind = ExprTokenKind.LESSEQ; Length = 2; break; } Kind = ExprTokenKind.LESS; break; case '>': c = inStream.Get(); if (inStream.Peek == '=') { c = inStream.Get(); Symbol = ">="; Kind = ExprTokenKind.GREATEREQ; Length = 2; break; } Kind = ExprTokenKind.GREATER; break; case '.': c = inStream.Get(); Kind = ExprTokenKind.DOT; break; case ',': c = inStream.Get(); Kind = ExprTokenKind.COMMA; break; case ';': c = inStream.Get(); Kind = ExprTokenKind.SEMI; break; default: { int pos = inStream.Pos; // First, check to see if it's a reserved word, such as: and or not int result = ParseReservedWord(inStream); if (char.IsLetter(c) && result == 1) { break; } // If not, rewind back to the beginning of the word to scan it // again. If the result was -1, it means no identifier was scanned // so we don't have to rewind. if (result == 0 || inStream.Eof) { inStream.Pos = pos; } if (inStream.Eof) { throw new InvalidOperationException("eof"); } // When in relaxed parsing mode, we want to migrate commodity flags // so that any precision specified by the user updates the current // maximum displayed precision. AmountParseFlagsEnum parseFlags = AmountParseFlagsEnum.PARSE_NO_ANNOT; if (pflags.HasFlag(AmountParseFlagsEnum.PARSE_NO_MIGRATE)) { parseFlags |= AmountParseFlagsEnum.PARSE_NO_MIGRATE; } if (pflags.HasFlag(AmountParseFlagsEnum.PARSE_NO_REDUCE)) { parseFlags |= AmountParseFlagsEnum.PARSE_NO_REDUCE; } try { Amount temp = new Amount(); if (!temp.Parse(inStream, parseFlags | AmountParseFlagsEnum.PARSE_SOFT_FAIL)) { inStream.Pos = pos; c = inStream.Peek; if (c != InputTextStream.EndOfFileChar) { if (!char.IsLetter(c) && c != '_') { Expected(default(char), c); } ParseIdent(inStream); } else { throw new ParseError(ParseError.ParseError_UnexpectedEOF); } if (Value.Type != ValueTypeEnum.String || Value.IsZero) { Kind = ExprTokenKind.ERROR; Symbol = new string(c, 1); throw new ParseError(ParseError.ParseError_FailedToParseIdentifier); } } else { Kind = ExprTokenKind.VALUE; Value = Value.Get(temp); Length = inStream.Pos - pos; } } catch { Kind = ExprTokenKind.ERROR; Length = inStream.Pos - pos; throw; } break; } } }
protected string ReadField(ref string line) { StringBuilder field = new StringBuilder(); InputTextStream inStream = new InputTextStream(line); char c; if (inStream.Peek == '"' || inStream.Peek == '|') { c = inStream.Get(); char x; while (!inStream.Eof) { x = inStream.Get(); if (x == '\\') { x = inStream.Get(); } else if (x == '"' && inStream.Peek == '"') { x = inStream.Get(); } else if (x == c) { if (x == '|') { inStream.Unget(); } else if (inStream.Peek == ',') { c = inStream.Get(); } break; } if (x != default(char)) { field.Append(x); } } } else { while (!inStream.Eof) { c = inStream.Get(); if (c == ',') { break; } if (c != default(char)) { field.Append(c); } } } line = inStream.RemainSource; return(field.ToString().Trim()); }