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 }); } }
Ast.TupleNode ParseTuple(SeekableStringReader sr) { //tuple = tuple_empty | tuple_one | tuple_more //tuple_empty = '()' . //tuple_one = '(' expr ',' <whitespace> ')' . //tuple_more = '(' expr_list ')' . sr.Read(); // ( sr.SkipWhitespace(); Ast.TupleNode tuple = new Ast.TupleNode(); if (sr.Peek() == ')') { sr.Read(); return(tuple); // empty tuple } Ast.INode firstelement = ParseExpr(sr); if (sr.Peek() == ',') { sr.Read(); sr.SkipWhitespace(); if (sr.Read() == ')') { // tuple with just a single element tuple.Elements.Add(firstelement); return(tuple); } sr.Rewind(1); // undo the thing that wasn't a ) } tuple.Elements = ParseExprList(sr); tuple.Elements.Insert(0, firstelement); if (!sr.HasMore()) { throw new ParseException("missing ')'"); } char closechar = sr.Read(); if (closechar == ',') { closechar = sr.Read(); } if (closechar != ')') { throw new ParseException("expected ')'"); } return(tuple); }
List <Ast.INode> ParseKeyValueList(SeekableStringReader sr) { //keyvalue_list = keyvalue { ',' keyvalue } . List <Ast.INode> kvs = new List <Ast.INode>(); kvs.Add(ParseKeyValue(sr)); while (sr.HasMore() && sr.Peek() == ',') { sr.Read(); try { kvs.Add(ParseKeyValue(sr)); } catch (ParseException) { sr.Rewind(1); break; } } return(kvs); }
List <Ast.INode> ParseExprList(SeekableStringReader sr) { //expr_list = expr { ',' expr } . List <Ast.INode> exprList = new List <Ast.INode>(); exprList.Add(ParseExpr(sr)); while (sr.HasMore() && sr.Peek() == ',') { sr.Read(); try { exprList.Add(ParseExpr(sr)); } catch (ParseException) { sr.Rewind(1); break; } } return(exprList); }
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 }); }