Ast.ComplexNumberNode ParseComplex(SeekableStringReader sr) { //complex = complextuple | imaginary . //imaginary = ['+' | '-' ] ( float | int ) 'j' . //complextuple = '(' ( float | int ) imaginary ')' . if (sr.Peek() == '(') { // complextuple sr.Read(); // ( string numberstr; if (sr.Peek() == '-' || sr.Peek() == '+') { // starts with a sign, read that first otherwise the readuntil will return immediately numberstr = sr.Read(1) + sr.ReadUntil(new char[] { '+', '-' }); } else { numberstr = sr.ReadUntil(new char[] { '+', '-' }); } double realpart; try { realpart = double.Parse(numberstr, CultureInfo.InvariantCulture); } catch (FormatException x) { throw new ParseException("invalid float format", x); } sr.Rewind(1); // rewind the +/- double imaginarypart = ParseImaginaryPart(sr); if (sr.Read() != ')') { throw new ParseException("expected ) to end a complex number"); } return(new Ast.ComplexNumberNode() { Real = realpart, Imaginary = imaginarypart }); } else { // imaginary double imag = ParseImaginaryPart(sr); return(new Ast.ComplexNumberNode() { Real = 0, Imaginary = imag }); } }
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); } }
private Ast.NoneNode ParseNone(SeekableStringReader sr) { // None string n = sr.ReadUntil('e'); if (n == "Non") { return(Ast.NoneNode.Instance); } throw new ParseException("expected None"); }
double ParseImaginaryPart(SeekableStringReader sr) { //imaginary = ['+' | '-' ] ( float | int ) 'j' . string numberstr = sr.ReadUntil('j'); try { return(double.Parse(numberstr, CultureInfo.InvariantCulture)); } catch (FormatException x) { throw new ParseException("invalid float format", x); } }
Ast.PrimitiveNode <bool> ParseBool(SeekableStringReader sr) { // True,False string b = sr.ReadUntil('e'); if (b == "Tru") { return(new Ast.BooleanNode(true)); } if (b == "Fals") { return(new Ast.BooleanNode(false)); } throw new ParseException("expected bool, True or False"); }
private Ast.PrimitiveNode <bool> ParseBool(SeekableStringReader sr) { // True,False string b = sr.ReadUntil('e'); switch (b) { case "Tru": return(new Ast.BooleanNode(true)); case "Fals": return(new Ast.BooleanNode(false)); } throw new ParseException("expected bool, True or False"); }
private Ast.ComplexNumberNode ParseComplex(SeekableStringReader sr) { //complex = complextuple | imaginary . //imaginary = ['+' | '-' ] ( float | int ) 'j' . //complextuple = '(' ( float | int ) imaginary ')' . if (sr.Peek() == '(') { // complextuple sr.Read(); // ( string numberstr; if (sr.Peek() == '-' || sr.Peek() == '+') { // starts with a sign, read that first otherwise the readuntil will return immediately numberstr = sr.Read(1) + sr.ReadUntil('+', '-'); } else { numberstr = sr.ReadUntil('+', '-'); } sr.Rewind(1); // rewind the +/- // because we're a bit more cautious here with reading chars than in the float parser, // it can be that the parser now stopped directly after the 'e' in a number like "3.14e+20". // ("3.14e20" is fine) So, check if the last char is 'e' and if so, continue reading 0..9. if (numberstr.EndsWith("e", StringComparison.InvariantCultureIgnoreCase)) { // if the next symbol is + or -, accept it, then read the exponent integer if (sr.Peek() == '-' || sr.Peek() == '+') { numberstr += sr.Read(1); } numberstr += sr.ReadWhile("0123456789"); } sr.SkipWhitespace(); double realpart; try { realpart = ParseDouble(numberstr); } catch (FormatException x) { throw new ParseException("invalid float format", x); } double imaginarypart = ParseImaginaryPart(sr); if (sr.Read() != ')') { throw new ParseException("expected ) to end a complex number"); } return(new Ast.ComplexNumberNode { Real = realpart, Imaginary = imaginarypart }); } // imaginary double imag = ParseImaginaryPart(sr); return(new Ast.ComplexNumberNode { Real = 0, Imaginary = imag }); }