Ast.SetNode ParseSet(SeekableStringReader sr) { // set = '{' expr_list '}' . sr.Read(); // { sr.SkipWhitespace(); Ast.SetNode setnode = new Ast.SetNode(); List <Ast.INode> elts = ParseExprList(sr); if (!sr.HasMore()) { throw new ParseException("missing '}'"); } char closechar = sr.Read(); if (closechar != '}') { throw new ParseException("expected '}'"); } // make sure it has set semantics (remove duplicate elements) HashSet <Ast.INode> h = new HashSet <Ast.INode>(elts); setnode.Elements = new List <Ast.INode>(h); return(setnode); }
Ast.ListNode ParseList(SeekableStringReader sr) { // list = list_empty | list_nonempty . // list_empty = '[]' . // list_nonempty = '[' expr_list ']' . sr.Read(); // [ sr.SkipWhitespace(); Ast.ListNode list = new Ast.ListNode(); if (sr.Peek() == ']') { sr.Read(); return(list); // empty list } list.Elements = ParseExprList(sr); if (!sr.HasMore()) { throw new ParseException("missing ']'"); } char closechar = sr.Read(); if (closechar != ']') { throw new ParseException("expected ']'"); } return(list); }
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.DictNode ParseDict(SeekableStringReader sr) { //dict = '{' keyvalue_list '}' . //keyvalue_list = keyvalue { ',' keyvalue } . //keyvalue = expr ':' expr . sr.Read(); // { sr.SkipWhitespace(); Ast.DictNode dict = new Ast.DictNode(); if (sr.Peek() == '}') { sr.Read(); return(dict); // empty dict } List <Ast.INode> elts = ParseKeyValueList(sr); if (!sr.HasMore()) { throw new ParseException("missing '}'"); } char closechar = sr.Read(); if (closechar != '}') { throw new ParseException("expected '}'"); } // make sure it has dict semantics (remove duplicate keys) Dictionary <Ast.INode, Ast.INode> fixedDict = new Dictionary <Ast.INode, Ast.INode>(elts.Count); foreach (Ast.KeyValueNode kv in elts) { fixedDict[kv.Key] = kv.Value; } foreach (var kv in fixedDict) { dict.Elements.Add(new Ast.KeyValueNode() { Key = kv.Key, Value = kv.Value }); } return(dict); }
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(); kvs.Add(ParseKeyValue(sr)); } 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(); exprList.Add(ParseExpr(sr)); } return(exprList); }
private Ast.SetNode ParseSet(SeekableStringReader sr) { // set = '{' expr_list trailing_comma '}' . // trailing_comma = '' | ',' . sr.Read(); // { sr.SkipWhitespace(); Ast.SetNode setnode = new Ast.SetNode(); var elts = ParseExprList(sr); // handle trailing comma if present sr.SkipWhitespace(); if (!sr.HasMore()) { throw new ParseException("missing '}'"); } if (sr.Peek() == ',') { sr.Read(); } if (!sr.HasMore()) { throw new ParseException("missing '}'"); } char closechar = sr.Read(); if (closechar != '}') { throw new ParseException("expected '}'"); } // make sure it has set semantics (remove duplicate elements) var h = new HashSet <Ast.INode>(elts); setnode.Elements = new List <Ast.INode>(h); return(setnode); }
private Ast.KeyValueNode ParseKeyValue(SeekableStringReader sr) { //keyvalue = expr ':' expr . Ast.INode key = ParseExpr(sr); if (!sr.HasMore() || sr.Peek() != ':') { throw new ParseException("expected ':'"); } sr.Read(); // : Ast.INode value = ParseExpr(sr); return(new Ast.KeyValueNode { Key = key, Value = value }); }
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); }
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); }
private Ast.PrimitiveNode <string> ParseString(SeekableStringReader sr) { char quotechar = sr.Read(); // ' or " StringBuilder sb = new StringBuilder(10); while (sr.HasMore()) { char c = sr.Read(); if (c == '\\') { // backslash unescape c = sr.Read(); switch (c) { case '\\': sb.Append('\\'); break; case '\'': sb.Append('\''); break; case '"': sb.Append('"'); break; case 'a': sb.Append('\a'); break; case 'b': sb.Append('\b'); break; case 'f': sb.Append('\f'); break; case 'n': sb.Append('\n'); break; case 'r': sb.Append('\r'); break; case 't': sb.Append('\t'); break; case 'v': sb.Append('\v'); break; case 'x': // "\x00" sb.Append((char)int.Parse(sr.Read(2), NumberStyles.HexNumber)); break; case 'u': // "\u0000" sb.Append((char)int.Parse(sr.Read(4), NumberStyles.HexNumber)); break; default: sb.Append(c); break; } } else if (c == quotechar) { // end of string return(new Ast.StringNode(sb.ToString())); } else { sb.Append(c); } } throw new ParseException("unclosed string"); }
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); }
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 }); }
private Ast.INode ParseDict(SeekableStringReader sr) { //dict = '{' keyvalue_list trailing_comma '}' . //keyvalue_list = keyvalue { ',' keyvalue } . //keyvalue = expr ':' expr . // trailing_comma = '' | ',' . sr.Read(); // { sr.SkipWhitespace(); Ast.DictNode dict = new Ast.DictNode(); if (sr.Peek() == '}') { sr.Read(); return(dict); // empty dict } var elts = ParseKeyValueList(sr); // handle trailing comma if present sr.SkipWhitespace(); if (!sr.HasMore()) { throw new ParseException("missing '}'"); } if (sr.Peek() == ',') { sr.Read(); } if (!sr.HasMore()) { throw new ParseException("missing '}'"); } char closechar = sr.Read(); if (closechar != '}') { throw new ParseException("expected '}'"); } // make sure it has dict semantics (remove duplicate keys) var fixedDict = new Dictionary <Ast.INode, Ast.INode>(elts.Count); foreach (var node in elts) { var kv = (Ast.KeyValueNode)node; fixedDict[kv.Key] = kv.Value; } foreach (var kv in fixedDict) { dict.Elements.Add(new Ast.KeyValueNode { Key = kv.Key, Value = kv.Value }); } // SPECIAL CASE: {'__class__':'float','value':'nan'} ---> Double.NaN if (dict.Elements.Count != 2) { return(dict); } if (!dict.Elements.Contains(new Ast.KeyValueNode(new Ast.StringNode("__class__"), new Ast.StringNode("float")))) { return(dict); } if (dict.Elements.Contains(new Ast.KeyValueNode(new Ast.StringNode("value"), new Ast.StringNode("nan")))) { return(new Ast.DoubleNode(double.NaN)); } return(dict); }