Пример #1
0
        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);
        }
Пример #2
0
        /// <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);
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
 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
     });
 }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        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");
        }
Пример #14
0
        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);
        }
Пример #15
0
        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);
        }