示例#1
0
文件: Schemy.cs 项目: zer/schemy
        /// <summary>
        /// Reads an S-expression from the input source
        /// </summary>
        public static object Read(InPort port)
        {
            Func <object, object> readAhead = null;

            readAhead = token =>
            {
                Symbol quote;
                if (object.Equals(token, Symbol.EOF))
                {
                    throw new SyntaxError("unexpected EOF");
                }
                else if (token is string)
                {
                    string tokenStr = (string)token;
                    if (tokenStr == "(")
                    {
                        var L = new List <object>();
                        while (true)
                        {
                            token = port.NextToken();
                            if (token is string && (string)token == ")")
                            {
                                return(L);
                            }
                            else
                            {
                                L.Add(readAhead(token));
                            }
                        }
                    }
                    else if (tokenStr == ")")
                    {
                        throw new SyntaxError("unexpected )");
                    }
                    else if (Symbol.QuotesMap.TryGetValue(tokenStr, out quote))
                    {
                        object quoted = Read(port);
                        return(new List <object> {
                            quote, quoted
                        });
                    }
                    else
                    {
                        return(ParseAtom(tokenStr));
                    }
                }
                else
                {
                    throw new SyntaxError("unexpected token: " + token);
                }
            };

            var token1 = port.NextToken();

            return(Symbol.EOF.Equals(token1) ? Symbol.EOF : readAhead(token1));
        }