private Ast.INode ParseCompound(SeekableStringReader sr) { // compound = tuple | dict | list | set . sr.SkipWhitespace(); switch (sr.Peek()) { case '[': return(ParseList(sr)); case '{': { int bm = sr.Bookmark(); try { return(ParseSet(sr)); } catch (ParseException) { sr.FlipBack(bm); return(ParseDict(sr)); } } case '(': // tricky case here, it can be a tuple but also a complex number: // if the last character before the closing parenthesis is a 'j', it is a complex number { int bm = sr.Bookmark(); string betweenparens = sr.ReadUntil(')', '\n').TrimEnd(); sr.FlipBack(bm); return(betweenparens.EndsWith("j") ? (Ast.INode)ParseComplex(sr) : ParseTuple(sr)); } default: throw new ParseException("invalid sequencetype char"); } }
/// <summary> /// Parse from a string with the Python literal expression /// </summary> public Ast Parse(string expression) { Ast ast = new Ast(); if (string.IsNullOrEmpty(expression)) { return(ast); } SeekableStringReader sr = new SeekableStringReader(expression); if (sr.Peek() == '#') { sr.ReadUntil('\n'); // skip comment line } try { ast.Root = ParseExpr(sr); sr.SkipWhitespace(); if (sr.HasMore()) { throw new ParseException("garbage at end of expression"); } return(ast); } catch (ParseException x) { string faultLocation = ExtractFaultLocation(sr); throw new ParseException(x.Message + " (at position " + sr.Bookmark() + "; '" + faultLocation + "')", x); } }
public Ast.INode ParseSingle(SeekableStringReader sr) { // single = int | float | complex | string | bool | none . sr.SkipWhitespace(); switch (sr.Peek()) { case 'N': return(ParseNone(sr)); case 'T': case 'F': return(ParseBool(sr)); case '\'': case '"': return(ParseString(sr)); } // int or float or complex. int bookmark = sr.Bookmark(); try { return(ParseComplex(sr)); } catch (ParseException) { sr.FlipBack(bookmark); try { return(ParseFloat(sr)); } catch (ParseException) { sr.FlipBack(bookmark); return(ParseInt(sr)); } } }
Ast.INode ParseCompound(SeekableStringReader sr) { // compound = tuple | dict | list | set . sr.SkipWhitespace(); switch (sr.Peek()) { case '[': return(ParseList(sr)); case '{': { int bm = sr.Bookmark(); try { return(ParseSet(sr)); } catch (ParseException) { sr.FlipBack(bm); return(ParseDict(sr)); } } case '(': // tricky case here, it can be a tuple but also a complex number. // try complex number first { int bm = sr.Bookmark(); try { return(ParseComplex(sr)); } catch (ParseException) { sr.FlipBack(bm); return(ParseTuple(sr)); } } default: throw new ParseException("invalid sequencetype char"); } }
private double ParseImaginaryPart(SeekableStringReader sr) { //imaginary = ['+' | '-' ] ( float | int ) 'j' . // string numberstr = sr.ReadUntil('j'); // try { // return this.ParseDouble(numberstr); // } catch(FormatException x) { // throw new ParseException("invalid float format", x); // } if (!sr.HasMore()) { throw new ParseException("unexpected end of input string"); } char signOrDigit = sr.Peek(); if (signOrDigit == '+') { sr.Read(); // skip the '+' } // now an int or float follows. double doubleValue; int bookmark = sr.Bookmark(); try { doubleValue = ParseFloat(sr).Value; } catch (ParseException) { sr.FlipBack(bookmark); var integerPart = ParseInt(sr); var integerNode = integerPart as Ast.IntegerNode; if (integerNode != null) { doubleValue = integerNode.Value; } else { var longNode = integerPart as Ast.LongNode; if (longNode != null) { doubleValue = longNode.Value; } else { var decimalNode = integerPart as Ast.DecimalNode; if (decimalNode != null) { doubleValue = Convert.ToDouble(decimalNode.Value); } else { throw new ParseException("not an integer for the imaginary part"); } } } } // now a 'j' must follow! sr.SkipWhitespace(); try { if (sr.Read() != 'j') { throw new ParseException("not an imaginary part"); } } catch (IndexOutOfRangeException) { throw new ParseException("not an imaginary part"); } return(doubleValue); }