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); }
/// <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); } }
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); }
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); }
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.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 }); }
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(); 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.INode ParseExpr(SeekableStringReader sr) { // expr = [ <whitespace> ] single | compound [ <whitespace> ] . sr.SkipWhitespace(); if (!sr.HasMore()) { throw new ParseException("unexpected end of line, missing expression or close/open character"); } char c = sr.Peek(); Ast.INode node; if (c == '{' || c == '[' || c == '(') { node = ParseCompound(sr); } else { node = ParseSingle(sr); } sr.SkipWhitespace(); return(node); }
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.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); }