Beispiel #1
0
Datei: let.cs Projekt: hww/VARP
        // (let () ...)
        public static AST Expand(Syntax stx, Environment env)
        {
            var list = stx.AsLinkedList <Value>();
            var argc = GetArgsCount(list);

            AssertArgsMinimum("let", "arity mismatch", 2, argc, list, stx);

            var keyword   = list[0].AsSyntax();   // let arguments
            var arguments = list[1].AsSyntax();   // let arguments

            if (!arguments.IsExpression)
            {
                throw SchemeError.SyntaxError("let", "bad syntax (missing name or binding pairs)", stx);
            }

            var localEnv = ArgumentsParser.ParseLet(stx, arguments.AsLinkedList <Value>(), env);

            AST lambda = new AstLambda(stx, keyword, localEnv, AstBuilder.ExpandListElements(list, 2, localEnv));

            var result = new LinkedList <Value>();

            result.AddLast(lambda.ToValue());
            foreach (var v in localEnv)
            {
                if (v is ArgumentBinding)
                {
                    var arg = v as ArgumentBinding;
                    if (arg.ArgType == ArgumentBinding.Type.Required)
                    {
                        result.AddLast(new Value(arg.Initializer));
                    }
                }
            }
            return(new AstApplication(stx, result));
        }
Beispiel #2
0
        private static Syntax ParseVector(Token thisToken, Tokenizer moreTokens)
        {
            var   listContents = new List <object>();
            Token dotToken     = null;

            var nextToken = moreTokens.ReadToken();

            while (nextToken != null && nextToken.Type != TokenType.CloseBracket)
            {
                // Parse this token
                listContents.Add(ParseToken(nextToken, moreTokens));

                // Fetch the next token
                nextToken = moreTokens.ReadToken();
                if (nextToken == null)
                {
                    throw SchemeError.SyntaxError("parser", "Improperly formed list.", dotToken);
                }

                //if (!improper && nextToken.Type == TokenType.Symbol && dotSymbol.Equals(nextToken.Value) && thisToken.Type == TokenType.OpenBracket)
                if (nextToken.Type == TokenType.Dot)
                {
                    throw SchemeError.SyntaxError("parser", "Improperly formed dotted list", nextToken);
                }
            }

            if (nextToken == null) // Missing ')'
            {
                throw SchemeError.SyntaxError("parser", "Missing close parenthesis", thisToken);
            }

            return(new Syntax(ValueList.FromList(listContents), thisToken));
        }
Beispiel #3
0
        // retrieve a quoted sugar token (' ` , ,@) and advance our position
        private Token QuoteSugar()
        {
            TokenType type;

            builder.Clear();

            switch (Character)
            {
            case '\'':
                type = TokenType.Quote;
                break;

            case '`':
                type = TokenType.QuasiQuote;
                break;

            case ',':
                type = TokenType.Unquote;
                break;

            default:
                throw SchemeError.SyntaxError("tokenizer", "unexpected character", lastToken);
            }

            builder.Append((char)Character);
            NextChar();
            if (Character == '@')
            {
                type = TokenType.UnquoteSplicing;
                NextChar();
                builder.Append((char)Character);
            }

            return(DefineToken(type, builder.ToString()));
        }
Beispiel #4
0
        /// <summary>
        /// Turns thisToken into an object, using moreTokens to get further tokens if required
        /// </summary>
        /// <returns></returns>
        protected static Syntax ParseToken(Token thisToken, Tokenizer moreTokens)
        {
            if (thisToken == null)
            {
                throw SchemeError.SyntaxError("parser", "unexpectedly reached the end of the input", moreTokens.LastToken);
            }

            switch (thisToken.Type)
            {
            //case TokenType.Dot:
            //    return thisToken; //TODO maybe exception or symbol .

            case TokenType.Character:
                return(new Syntax(new Value(thisToken.GetCharacter()), thisToken));

            case TokenType.Boolean:
                return(new Syntax(new Value(thisToken.GetBool()), thisToken));

            case TokenType.String:
                return(new Syntax(new Value(thisToken.GetString()), thisToken));

            case TokenType.Symbol:
                return(new Syntax(thisToken.GetSymbol(), thisToken));

            case TokenType.Heximal:
            case TokenType.Integer:
                return(new Syntax(new Value(thisToken.GetInteger()), thisToken));

            case TokenType.Floating:
                return(new Syntax(new Value(thisToken.GetFloat()), thisToken));

            case TokenType.OpenBracket:
                return(ParseList(thisToken, moreTokens));

            case TokenType.OpenVector:
                return(ParseVector(thisToken, moreTokens));

            case TokenType.Quote:
            case TokenType.Unquote:
            case TokenType.UnquoteSplicing:
            case TokenType.QuasiQuote:
                return(ParseQuoted(thisToken, moreTokens));

            case TokenType.BadNumber:
                throw SchemeError.SyntaxError("parser", "looks like it should be a number, but it contains a syntax error", thisToken);

            default:
                // Unknown token type
                throw SchemeError.SyntaxError("parser", "the element is being used in a context where it is not understood", thisToken);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Parses a scheme expression in the default manner
        /// </summary>
        /// <returns>A scheme object</returns>
        /// <remarks>It is an error to pass scheme to this method with 'extraneous' tokens, such as trailing closing brackets</remarks>
        public static Syntax Parse(string scheme, string filepath)
        {
            var reader = new Tokenizer(new System.IO.StringReader(scheme), filepath);

            var res   = Parse(reader);
            var token = reader.ReadToken();

            if (token != null)
            {
                throw SchemeError.SyntaxError("parser", "found extra tokens after the end of a scheme expression", token);
            }

            return(res);
        }
Beispiel #6
0
        /// <summary>
        /// Define new definition.
        /// </summary>
        /// <param name="name">identifier</param>
        /// <param name="binding">binding</param>
        public int Define(Symbol name, AstBinding binding)
        {
            var variable = LookupLocal(name);

            if (variable != null)
            {
                throw SchemeError.SyntaxError("define", "environment already have key", binding.Id);
            }

            binding.environment = this;
            binding.VarIdx      = Bindings.Count;
            Bindings[name]      = binding;
            return(binding.VarIdx);
        }
Beispiel #7
0
 public char GetCharacter()
 {
     Debug.Assert(Type == TokenType.Character);
     if (Value.Length == 3)
     {
         return(System.Convert.ToChar(Value[2]));
     }
     else
     {
         var c = (char)0;
         if (CharType.NameToCharacter(Value, out c))
         {
             return(c);
         }
         throw SchemeError.SyntaxError("get-character", "improperly formed char value", this);
     }
 }
Beispiel #8
0
        public bool GetBool()
        {
            Debug.Assert(Type == TokenType.Boolean);

            if (Value == "#t")
            {
                return(true);
            }
            else if (Value == "#f")
            {
                return(false);
            }
            else
            {
                throw SchemeError.SyntaxError("get-bool", "improperly formed bool value", this);
            }
        }
Beispiel #9
0
        public int GetInteger()
        {
            try
            {
                switch (Type)
                {
                case TokenType.Integer:
                    return(StringLibs.GetInteger(Value));

                case TokenType.Heximal:
                    return(StringLibs.GetHexadecimal(Value));

                default:
                    throw SchemeError.SyntaxError("get-integer", "wrong token type", this);
                }
            }
            catch (System.Exception ex)
            {
                throw SchemeError.SyntaxError("get-integer", "improperly formed int value", this);
            }
        }
Beispiel #10
0
        // retrieve a string literal token and advance our position
        private Token StringLiteral()
        {
            builder.Clear();
            NextChar();
            var type = TokenType.String;

            var matchingQuotes = false;

            while (Character >= 0)
            {
                // if we get an escape, increment the position some more and map the escaped character to what it should be
                if (Character == '\\')
                {
                    NextChar();
                    builder.Append(MapEscaped(Character));
                    NextChar();
                    continue;
                }

                // unescaped quote? We're done with this string.
                if (Character == '"')
                {
                    NextChar();
                    matchingQuotes = true;
                    break;
                }

                builder.Append((char)Character);
                NextChar();
            }

            // we didn't get opening and closing quotes :(
            if (!matchingQuotes)
            {
                throw SchemeError.SyntaxError("tokenizer", "unmatched quotes in string literal", lastToken);
            }

            return(DefineToken(type, builder.ToString()));
        }
Beispiel #11
0
 // Expand string @syntax to abstract syntax tree, in given @env environment
 public static Ast ExpandInternal(Syntax syntax, Environment env)
 {
     if (syntax == null)
     {
         return(null);
     }
     else if (syntax.IsLiteral)
     {
         return(ExpandLiteral(syntax, env));
     }
     else if (syntax.IsIdentifier)
     {
         return(ExpandIdentifier(syntax, env));
     }
     else if (syntax.IsExpression)
     {
         return(ExpandExpression(syntax, env));
     }
     else
     {
         throw SchemeError.SyntaxError("ast-builder-expand", "expected literal, identifier or list expression", syntax);
     }
 }
Beispiel #12
0
        // retrieve a number literal token (int or decimal) and advance our position
        private Token NumberLiteral()
        {
            var type = TokenType.Integer;

            builder.Clear();

            while (Character >= 0 && IsNumericalPart(Character))
            {
                // if we get a decimal we're no longer working with an integer
                if (Character == '.')
                {
                    if (type == TokenType.Floating)
                    {
                        throw SchemeError.SyntaxError("tokenizer", "error in numerical literal", lastToken);
                    }

                    type = TokenType.Floating;
                }
                builder.Append((char)Character);
                NextChar();
            }

            return(DefineToken(type, builder.ToString()));
        }
Beispiel #13
0
        private static Syntax ParseList(Token thisToken, Tokenizer moreTokens)
        {
            // Is a list/vector
            var   listContents = new List <Syntax>();
            Token dotToken     = null;

            var nextToken = moreTokens.ReadToken();

            while (nextToken != null && nextToken.Type != TokenType.CloseBracket)
            {
                // Parse this token
                listContents.Add(ParseToken(nextToken, moreTokens));

                // Fetch the next token
                nextToken = moreTokens.ReadToken();
                if (nextToken == null)
                {
                    throw SchemeError.SyntaxError("parser", "Improperly formed list.", dotToken);
                }

                if (nextToken.Type == TokenType.Dot)
                {
                    if (dotToken != null || thisToken.Type != TokenType.OpenBracket)
                    {
                        throw SchemeError.SyntaxError("parser", "Improperly formed dotted list", nextToken);
                    }
                    dotToken  = nextToken;
                    nextToken = moreTokens.ReadToken();
                    if (nextToken == null)
                    {
                        throw SchemeError.SyntaxError("parser", "Improperly formed dotted list", dotToken);
                    }
                    if (nextToken.Type == TokenType.CloseBracket)
                    {
                        throw SchemeError.SyntaxError("parser", "Improperly formed dotted list", dotToken);
                    }
                    listContents.Add(ParseToken(nextToken, moreTokens));
                    nextToken = moreTokens.ReadToken();
                    if (nextToken.Type != TokenType.CloseBracket)
                    {
                        throw SchemeError.SyntaxError("parser", "Improperly formed dotted list", dotToken);
                    }
                    break;
                }
            }

            if (nextToken == null)
            {
                // Missing ')'
                throw SchemeError.SyntaxError("parser", "missing close parenthesis", thisToken);
            }

            if (dotToken != null)
            {
                if (listContents.Count == 2)
                {
                    return(new Syntax(new ValuePair(listContents[0], listContents[1]), thisToken));
                }
                else
                {
                    throw SchemeError.SyntaxError("parser", "improper dot syntax", thisToken);
                }
            }
            else
            {
                if (listContents.Count == 0)
                {
                    return(new Syntax(Value.Nil, thisToken));
                }
                else
                {
                    return(new Syntax(ValueLinkedList.FromList <Syntax>(listContents), thisToken));
                }
            }
        }
Beispiel #14
0
Datei: Cond.cs Projekt: hww/VARP
        // (cond () ...)
        public static AST Expand(Syntax stx, Environment env)
        {
            var list = stx.AsLinkedList <Value>();    //< list of syntax objects
            var argc = GetArgsCount(list);

            var keyword = list[0].AsSyntax();
            LinkedList <Value> allcases = null;
            LinkedList <Value> elsecase = null;

            var curent = list.GetNodeAtIndex(1);

            while (curent != null)
            {
                var conditional_stx = curent.Value.AsSyntax();

                if (elsecase != null)
                {
                    throw SchemeError.SyntaxError("cond", "unexpected expression after condition's else clause", conditional_stx);
                }

                if (conditional_stx.IsExpression)
                {
                    // Get single conditional expression
                    var conditional_list = conditional_stx.AsLinkedList <Value>();

                    // Check arguments count, should be 2 for each condition
                    var size = conditional_list.Count;
                    if (size != 2)
                    {
                        throw SchemeError.ArityError("cond", "arity mismatch", 2, size, conditional_list, conditional_stx);
                    }

                    // Now get condition and it's expression
                    var var = conditional_list[0].AsSyntax();
                    var val = conditional_list[1].AsSyntax();

                    if (var.IsIdentifier && var.AsIdentifier() == Symbol.ELSE)
                    {
                        var ast = AstBuilder.ExpandInternal(val, env);
                        elsecase = ValueLinkedList.FromArguments(new Value(var), new Value(ast));
                    }
                    else
                    {
                        var cond_       = AstBuilder.ExpandInternal(var, env);
                        var then_       = AstBuilder.ExpandInternal(val, env);
                        var single_cond = ValueLinkedList.FromArguments(cond_, then_);
                        if (allcases == null)
                        {
                            allcases = new LinkedList <Value>();
                        }
                        allcases.AddLast(new Value(single_cond));
                    }
                }
                else
                {
                    throw SchemeError.SyntaxError("cond", "Expected condition's expression list", conditional_stx);
                }
                curent = curent.Next;
            }

            return(new AstCondition(stx, keyword, allcases, elsecase));
        }
Beispiel #15
0
        /// <summary>
        /// The result structure has lists of arguments where
        /// the variable names as syntaxes, but initializers as AST
        /// </summary>
        /// <param name="expression">expression where this aregumens located</param>
        /// <param name="arguments">the arguments list (syntax syntax syntax ...)</param>
        /// <param name="env">environment</param>
        /// <param name="args">destination arguments structure</param>
        public static Environment ParseLambda(Syntax expression, LinkedList <Value> arguments, Environment environment)
        {
            var newenv = new Environment(environment, Symbol.NULL);

            if (arguments == null)
            {
                return(newenv);
            }

            var arg_type = ArgumentBinding.Type.Required;

            /// ----------------------------------------------------------------------
            /// Waiting for the DSSSL keywords, when found change mode and return true
            /// ----------------------------------------------------------------------
            Func <Syntax, bool> SymbolToArgumentType = (Syntax stx) =>
            {
                if (!stx.IsSymbol)
                {
                    return(false);
                }

                var symbol = stx.GetDatum().AsSymbol();

                if (symbol == Symbol.OPTIONAL)
                {
                    arg_type = ArgumentBinding.Type.Optionals;
                }
                else if (symbol == Symbol.KEY)
                {
                    arg_type = ArgumentBinding.Type.Key;
                }
                else if (symbol == Symbol.REST)
                {
                    arg_type = ArgumentBinding.Type.Rest;
                }
                else if (symbol == Symbol.BODY)
                {
                    arg_type = ArgumentBinding.Type.Body;
                }
                else
                {
                    return(false);
                }
                return(true);
            };

            foreach (var arg in arguments)
            {
                var argstx = arg.AsSyntax();

                if (!SymbolToArgumentType(argstx))
                {
                    switch (arg_type)
                    {
                    case ArgumentBinding.Type.Required:
                        if (argstx.IsIdentifier)
                        {
                            ParseRequired("lambda", argstx, argstx, newenv, ArgumentBinding.Type.Required);
                        }
                        else
                        {
                            throw SchemeError.ArgumentError("lambda", "symbol?", argstx);
                        }
                        break;

                    case ArgumentBinding.Type.Optionals:
                        ParseOptional("lambda", argstx, argstx, newenv, ArgumentBinding.Type.Optionals);
                        break;

                    case ArgumentBinding.Type.Key:
                        ParseOptional("lambda", argstx, argstx, newenv, ArgumentBinding.Type.Key);
                        break;

                    case ArgumentBinding.Type.Rest:
                        ParseRequired("lambda", argstx, argstx, newenv, ArgumentBinding.Type.Rest);
                        arg_type = ArgumentBinding.Type.End;
                        break;

                    case ArgumentBinding.Type.Body:
                        ParseBody("lambda", argstx, argstx, newenv);
                        arg_type = ArgumentBinding.Type.End;
                        break;

                    case ArgumentBinding.Type.End:
                        throw SchemeError.SyntaxError("lambda", "unexpected extra argument", argstx);
                    }
                }
            }
            return(newenv);
        }
Beispiel #16
0
        // aka: x
        public static Ast ExpandIdentifier(Syntax syntax, Environment env)
        {
            if (!syntax.IsIdentifier)
            {
                throw SchemeError.SyntaxError("ast-builder-expand-identifier", "expected identifier", syntax);
            }

            var varname = (Name)syntax.GetDatum();

            // Check and expand some of literals
            if (varname == EName.None)
            {
                return(new AstLiteral(syntax));
            }

            // Find the variable in ast environment
            int envIdx  = 0;
            var binding = env.LookupAstRecursively(varname, ref envIdx);

            if (binding == null)
            {
                // If variable is not found designate it as global variable
                var localIdx = env.Define(varname, new GlobalBinding(syntax));
                return(new AstReference(syntax, AstReferenceType.Global, localIdx));
            }
            else
            {
                if (envIdx == 0)
                {
                    // local variable reference
                    return(new AstReference(syntax, AstReferenceType.Local, binding.VarIdx, 0, 0));
                }
                else
                {
                    // up-value reference
                    if (binding is GlobalBinding || !binding.environment.IsLexical)
                    {
                        // global variable
                        var localIdx = env.Define(varname, new GlobalBinding(syntax));
                        return(new AstReference(syntax, AstReferenceType.Global, localIdx));
                    }
                    else if (binding is LocalBinding || binding is ArgumentBinding)
                    {
                        // up value to local variable
                        var localIdx = env.Define(varname, new UpBinding(syntax, envIdx, binding.VarIdx));
                        return(new AstReference(syntax, AstReferenceType.UpValue, localIdx, envIdx, binding.VarIdx));
                    }
                    else if (binding is UpBinding)
                    {
                        // upValue to other upValue
                        var upBinding = binding as UpBinding;
                        var nEnvIdx   = upBinding.UpEnvIdx + envIdx;
                        var nVarIdx   = upBinding.UpVarIdx;
                        var localIdx  = env.Define(varname, new UpBinding(syntax, nEnvIdx, nVarIdx));
                        return(new AstReference(syntax, AstReferenceType.UpValue, localIdx, nEnvIdx, nVarIdx));
                    }
                    else
                    {
                        throw new SystemException();
                    }
                }
            }
        }
Beispiel #17
0
        // retrieve a vector literal marker, boolean token, or character literal token and advance our position
        private Token VectorOrBooleanOrChar()
        {
            builder.Clear();
            var boolLiterals = new List <char> {
                'F', 'f', 't', 'T'
            };
            var nextc = reader.Peek();

            if (boolLiterals.Contains((char)nextc))
            {
                // boolean literal!
                builder.Append((char)Character);
                NextChar(); // skip #
                if (Character >= 0)
                {
                    builder.Append((char)Character);
                    NextChar(); // skip F,f,t,T
                }
                return(DefineToken(TokenType.Boolean, builder.ToString()));
            }
            else if (nextc == '(')
            {
                // vector literal!
                NextChar(); // skip #
                NextChar(); // skip (
                return(DefineToken(TokenType.OpenVector, "("));
            }
            else if (nextc == '\\')
            {
                // char literal!
                while (Character >= 0 && !IsWhitespace(Character))
                {
                    if (builder.Size < 3)
                    {
                        builder.Append((char)Character);
                        NextChar();
                    }
                    else
                    {
                        if (!IsEOF(Character) && IsSymbolPart(Character))
                        {
                            builder.Append((char)Character);
                            NextChar();
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                return(DefineToken(TokenType.Character, builder.ToString()));
            }
            else if (nextc == 'x')
            {
                builder.Append((char)Character);
                NextChar(); // skip #
                builder.Append((char)Character);
                NextChar(); // skip x
                // char literal!
                while (Character >= 0 && IsHeximalPart(Character))
                {
                    builder.Append((char)Character);
                    NextChar();
                }
                return(DefineToken(TokenType.Heximal, builder.ToString()));
            }
            //else if (nextc == '!')
            //{
            //    builder.Append((char)Character);
            //    NextChar(); // skip #
            //    builder.Append((char)Character);
            //    NextChar(); // skip !
            //    // char literal!
            //    while (Character >= 0 && IsSymbolPart(Character))
            //    {
            //        builder.Append((char)Character);
            //        NextChar();
            //    }
            //    return DefineToken(TokenType.Symbol, builder.ToString());
            //}
            else
            {
                throw SchemeError.SyntaxError("tokenizer", "inside '#' but no matching characters to construct a token", lastToken);
            }
        }