/// <summary>
 /// 再帰的に連続させられる一次式の処理
 /// </summary>
 /// <param name="tokens"></param>
 /// <param name="parent"></param>
 /// <returns></returns>
 private KecaknoahPrimaryExpressionAstNode ParsePrimaryRecursiveExpression(Queue<KecaknoahToken> tokens, KecaknoahPrimaryExpressionAstNode parent)
 {
     var result = parent;
     if (!tokens.CheckToken(KecaknoahTokenType.Period, KecaknoahTokenType.ParenStart, KecaknoahTokenType.BracketStart)) return result;
     while (true)
     {
         if (tokens.CheckSkipToken(KecaknoahTokenType.Period))
         {
             result = ParsePrimaryMemberAccessExpression(tokens, result);
         }
         else if (tokens.CheckSkipToken(KecaknoahTokenType.ParenStart))
         {
             result = ParsePrimaryFunctionCallExpression(tokens, result);
         }
         else if (tokens.CheckSkipToken(KecaknoahTokenType.BracketStart))
         {
             result = ParsePrimaryIndexerAccessExpression(tokens, result);
         }
         else
         {
             break;
         }
     }
     return result;
 }
 /// <summary>
 /// インデクサの引数リスト処理
 /// </summary>
 /// <param name="tokens"></param>
 /// <param name="parent"></param>
 /// <returns></returns>
 private KecaknoahArgumentCallExpressionAstNode ParsePrimaryIndexerAccessExpression(Queue<KecaknoahToken> tokens, KecaknoahPrimaryExpressionAstNode parent)
 {
     var r = new KecaknoahArgumentCallExpressionAstNode();
     r.Target = parent;
     r.ExpressionType = KecaknoahOperatorType.IndexerAccess;
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     if (tokens.CheckSkipToken(KecaknoahTokenType.BracketEnd)) return r;
     while (true)
     {
         r.Arguments.Add(ParseExpression(tokens));
         if (tokens.CheckSkipToken(KecaknoahTokenType.Comma)) continue;
         tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
         if (tokens.CheckSkipToken(KecaknoahTokenType.BracketEnd)) break;
         throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("メソッド呼び出しの引数リストが無効です。"));
     }
     return r;
 }
 private KecaknoahLoopAstNode ParseForeach(Queue<KecaknoahToken> tokens, bool single)
 {
     var result = new KecaknoahForeachAstNode();
     var t = tokens.Peek();
     if (t.Type == KecaknoahTokenType.Identifer)
     {
         tokens.Dequeue();
         result.Name = t.TokenString;
     }
     else
     {
         result.Name = Guid.NewGuid().ToString().Substring(0, 8);
     }
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("whileの条件式はカッコでくくってください。"));
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     var nt = tokens.Dequeue();
     if (nt.Type != KecaknoahTokenType.Identifer) throw new KecaknoahParseException(nt.CreateErrorAt("foreachのループ変数には識別子を指定してください。"));
     result.ElementVariableName = nt.TokenString;
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     nt = tokens.Dequeue();
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     if (nt.Type == KecaknoahTokenType.InKeyword)
     {
         result.Source = ParseExpression(tokens);
     }
     else if (nt.Type == KecaknoahTokenType.OfKeyword)
     {
         result.IsCoroutineSource = true;
         result.Source = ParseExpression(tokens);
         if (tokens.CheckSkipToken(KecaknoahTokenType.Colon))
         {
             if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(nt.CreateErrorAt("コルーチンの引数リストが不正です。"));
             tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
             while (true)
             {
                 result.CoroutineArguments.Add(ParseExpression(tokens));
                 tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                 if (tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) break;
                 if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) throw new KecaknoahParseException(nt.CreateErrorAt("コルーチンの引数リストが閉じていません。"));
                 tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
             }
         }
     }
     else
     {
         throw new KecaknoahParseException(nt.CreateErrorAt("foreachにはinかofを指定してください。"));
     }
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("foreachの条件式はカッコでくくってください。"));
     if (single || !tokens.SkipLogicalLineBreak())
     {
         if (tokens.SkipLogicalLineBreak()) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("単行foreach文のみ記述できます。"));
         foreach (var i in ParseSingleLineStatement(tokens)) result.AddNode(i);
     }
     else
     {
         foreach (var i in ParseBlock(tokens)) result.AddNode(i);
         if (!tokens.CheckSkipToken(KecaknoahTokenType.NextKeyword)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("nextで終わっていません。"));
     }
     return result;
 }
 /// <summary>
 /// 一次式の処理
 /// </summary>
 /// <param name="tokens"></param>
 /// <returns></returns>
 private KecaknoahPrimaryExpressionAstNode ParsePrimaryExpression(Queue<KecaknoahToken> tokens)
 {
     var factor = ParseFactorExpression(tokens);
     //tokens.SkipLogicalLineBreak();
     var re = ParsePrimaryRecursiveExpression(tokens, factor);
     if (re != factor) return re;
     if (!tokens.CheckToken(KecaknoahTokenType.Increment, KecaknoahTokenType.Decrement)) return factor;
     re = new KecaknoahPrimaryExpressionAstNode();
     re.Target = factor;
     if (tokens.CheckSkipToken(KecaknoahTokenType.Increment)) re.ExpressionType = KecaknoahOperatorType.Increment;
     if (tokens.CheckSkipToken(KecaknoahTokenType.Decrement)) re.ExpressionType = KecaknoahOperatorType.Decrement;
     return re;
 }
 private KecaknoahForAstNode ParseFor(Queue<KecaknoahToken> tokens, bool single)
 {
     var result = new KecaknoahForAstNode();
     var t = tokens.Peek();
     if (t.Type == KecaknoahTokenType.Identifer)
     {
         tokens.Dequeue();
         result.Name = t.TokenString;
     }
     else
     {
         result.Name = Guid.NewGuid().ToString().Substring(0, 8);
     }
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("forの各式は全体をカッコでくくってください。"));
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     while (true)
     {
         var exp = ParseExpression(tokens);
         result.InitializeExpressions.Add(exp);
         if (tokens.CheckSkipToken(KecaknoahTokenType.Semicolon)) break;
         if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("初期化式はコンマで区切ってください。"));
         tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     }
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     result.Condition = ParseExpression(tokens);
     if (!tokens.CheckSkipToken(KecaknoahTokenType.Semicolon)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("セミコロンで区切ってください。"));
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     while (true)
     {
         var exp = ParseExpression(tokens);
         result.CounterExpressions.Add(exp);
         tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
         if (tokens.CheckToken(KecaknoahTokenType.ParenEnd)) break;
         if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("初期化式はコンマで区切ってください。"));
         tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     }
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("forの各式は全体をカッコでくくってください。"));
     if (single || !tokens.SkipLogicalLineBreak())
     {
         if (tokens.SkipLogicalLineBreak()) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("単行for文のみ記述できます。"));
         foreach (var i in ParseSingleLineStatement(tokens)) result.AddNode(i);
     }
     else
     {
         foreach (var i in ParseBlock(tokens)) result.AddNode(i);
         if (!tokens.CheckSkipToken(KecaknoahTokenType.NextKeyword)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("nextで終わっていません。"));
     }
     return result;
 }
 private KecaknoahLoopAstNode ParseWhile(Queue<KecaknoahToken> tokens, bool single)
 {
     var result = new KecaknoahLoopAstNode();
     var t = tokens.Peek();
     if (t.Type == KecaknoahTokenType.Identifer)
     {
         tokens.Dequeue();
         result.Name = t.TokenString;
     }
     else
     {
         result.Name = Guid.NewGuid().ToString().Substring(0, 8);
     }
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("whileの条件式はカッコでくくってください。"));
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     result.Condition = ParseExpression(tokens);
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("whileの条件式はカッコでくくってください。"));
     if (single || !tokens.SkipLogicalLineBreak())
     {
         if (tokens.SkipLogicalLineBreak()) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("単行while文のみ記述できます。"));
         foreach (var i in ParseSingleLineStatement(tokens)) result.AddNode(i);
     }
     else
     {
         foreach (var i in ParseBlock(tokens)) result.AddNode(i);
         if (!tokens.CheckSkipToken(KecaknoahTokenType.NextKeyword)) throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("nextで終わっていません。"));
     }
     return result;
 }
 private KecaknoahIfAstNode ParseIf(Queue<KecaknoahToken> tokens, bool single)
 {
     var result = new KecaknoahIfAstNode();
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("if文の条件式はカッコでくくってください。"));
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     var cnd = ParseExpression(tokens);
     tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
     var ifb = new KecaknoahIfBlockAstNode();
     ifb.Condition = cnd;
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("if文の条件式が閉じていません。"));
     if (!tokens.CheckSkipToken(KecaknoahTokenType.ThenKeyword)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("thenキーワードをおいてください。"));
     if (!single && tokens.SkipLogicalLineBreak())
     {
         //ブロックif
         var b = ParseBlock(tokens);
         foreach (var i in b) ifb.AddNode(i);
         result.IfBlock = ifb;
         while (true)
         {
             var nt = tokens.Dequeue();
             if (nt.Type == KecaknoahTokenType.EndifKeyword)
             {
                 break;
             }
             else if (nt.Type == KecaknoahTokenType.ElifKeyword)
             {
                 if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("elif文の条件式はカッコでくくってください。"));
                 tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                 cnd = ParseExpression(tokens);
                 var elb = new KecaknoahIfBlockAstNode();
                 tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                 elb.Condition = cnd;
                 if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("elif文の条件式が閉じていません。"));
                 if (!tokens.CheckSkipToken(KecaknoahTokenType.ThenKeyword)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("thenキーワードをおいてください。"));
                 tokens.SkipLogicalLineBreak();
                 b = ParseBlock(tokens);
                 foreach (var i in b) elb.AddNode(i);
                 result.ElifBlocks.Add(elb);
             }
             else if (nt.Type == KecaknoahTokenType.ElseKeyword)
             {
                 tokens.SkipLogicalLineBreak();
                 var esb = new KecaknoahIfBlockAstNode();
                 b = ParseBlock(tokens);
                 foreach (var i in b) esb.AddNode(i);
                 result.ElseBlock = esb;
             }
             else
             {
                 throw new KecaknoahParseException(nt.CreateErrorAt("不正なif文です。"));
             }
         }
     }
     else
     {
         //単行if
         ifb.AddNode(ParseSingleLineStatement(tokens));
         result.IfBlock = ifb;
         if (tokens.CheckSkipToken(KecaknoahTokenType.ElseKeyword))
         {
             var esb = new KecaknoahIfBlockAstNode();
             esb.AddNode(ParseSingleLineStatement(tokens));
             result.ElseBlock = esb;
         }
     }
     return result;
 }
        private KecaknoahIfAstNode ParseCase(Queue<KecaknoahToken> tokens)
        {
            var result = new KecaknoahIfAstNode();
            var ifb = new KecaknoahIfBlockAstNode();
            ifb.Condition = new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.BooleanValue, BooleanValue = false };
            result.IfBlock = ifb;
            if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("case文の判定式はカッコでくくってください。"));
            tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
            var target = ParseExpression(tokens);
            tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
            if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("case文の判定式はカッコでくくってください。"));
            if (!tokens.SkipLogicalLineBreak()) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("case文の判定式の後は改行してください。"));
            var wls = new List<KecaknoahExpressionAstNode>();
            var df = false;
            while (true)
            {
                var nt = tokens.Peek();
                if (nt.Type == KecaknoahTokenType.EndCaseKeyword)
                {
                    tokens.Dequeue();
                    break;
                }
                else if (nt.Type == KecaknoahTokenType.WhenKeyword)
                {
                    tokens.Dequeue();
                    var t2 = ParseExpression(tokens);
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.Colon)) throw new KecaknoahParseException(nt.CreateErrorAt("whenの式の後ろはコロンを付けてください。"));
                    wls.Add(t2);
                    tokens.SkipLogicalLineBreak();
                    continue;
                }
                else if (nt.Type == KecaknoahTokenType.DefaultKeyword)
                {
                    tokens.Dequeue();
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.Colon)) throw new KecaknoahParseException(nt.CreateErrorAt("defaultの後ろはコロンを付けてください。"));
                    df = true;
                    continue;
                }
                else
                {
                    var bl = ParseBlock(tokens);
                    if (wls.Count == 0)
                    {
                        if (!df) throw new KecaknoahParseException(nt.CreateErrorAt("case文内でブロックが浮いています。"));
                        var en = new KecaknoahIfBlockAstNode();
                        foreach (var j in bl) en.AddNode(j);
                        result.ElseBlock = en;
                        df = false;
                    }
                    else
                    {
                        var tn = new KecaknoahBinaryExpressionAstNode();
                        tn.ExpressionType = KecaknoahOperatorType.OrElse;
                        tn.FirstNode = new KecaknoahBinaryExpressionAstNode { ExpressionType = KecaknoahOperatorType.Equal, FirstNode = target, SecondNode = wls[0] };
                        var eln = new KecaknoahIfBlockAstNode();
                        foreach (var i in wls.Skip(1))
                        {
                            var nc = new KecaknoahBinaryExpressionAstNode { ExpressionType = KecaknoahOperatorType.Equal, FirstNode = target, SecondNode = i };
                            tn.SecondNode = nc;
                            var ntn = new KecaknoahBinaryExpressionAstNode();
                            ntn.FirstNode = tn;
                            ntn.ExpressionType = KecaknoahOperatorType.OrElse;
                            tn = ntn;

                        }
                        eln.Condition = tn.FirstNode;
                        foreach (var j in bl) eln.AddNode(j);
                        result.ElifBlocks.Add(eln);
                        if (df)
                        {
                            result.ElseBlock = eln;
                            df = false;
                        }
                        wls.Clear();
                    }
                }
            }
            return result;
        }
        private IList<KecaknoahCoroutineDeclareAstNode> ParseCoroutineDeclare(Queue<KecaknoahToken> tokens)
        {
            var result = new List<KecaknoahCoroutineDeclareAstNode>();
            while (true)
            {
                var nt = tokens.Dequeue();
                if (nt.Type != KecaknoahTokenType.Identifer) throw new KecaknoahParseException(nt.CreateErrorAt("識別子を指定してください。"));
                var lan = new KecaknoahCoroutineDeclareAstNode();
                lan.Name = nt.TokenString;
                nt = tokens.Dequeue();
                if (nt.Type != KecaknoahTokenType.Assign) throw new KecaknoahParseException(nt.CreateErrorAt("coroutine宣言は必ず代入してください。"));
                lan.InitialExpression = ParseExpression(tokens);

                if (tokens.CheckSkipToken(KecaknoahTokenType.Colon))
                {
                    //引数
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(nt.CreateErrorAt("coroutine宣言の引数リストが不正です。"));
                    tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                    while (true)
                    {
                        lan.ParameterExpressions.Add(ParseExpression(tokens));
                        if (tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) break;
                        if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) throw new KecaknoahParseException(nt.CreateErrorAt("coroutine宣言の引数リストが閉じていません。"));
                        tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                    }
                }
                result.Add(lan);
                if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) break;
            }
            return result;
        }
 private IList<KecaknoahLocalAstNode> ParseLocal(Queue<KecaknoahToken> tokens)
 {
     var result = new List<KecaknoahLocalAstNode>();
     while (true)
     {
         var nt = tokens.Dequeue();
         if (nt.Type != KecaknoahTokenType.Identifer) throw new KecaknoahParseException(nt.CreateErrorAt("識別子を指定してください。"));
         var lan = new KecaknoahLocalAstNode();
         lan.Name = nt.TokenString;
         result.Add(lan);
         if (tokens.SkipLogicalLineBreak()) return result;
         nt = tokens.Dequeue();
         switch (nt.Type)
         {
             case KecaknoahTokenType.Assign:
                 lan.InitialExpression = ParseExpression(tokens);
                 if (tokens.SkipLogicalLineBreak()) return result;
                 if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) throw new KecaknoahParseException(nt.CreateErrorAt("無効なlocal宣言です。"));
                 tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                 break;
             case KecaknoahTokenType.Comma:
                 tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                 continue;
             default:
                 throw new KecaknoahParseException(nt.CreateErrorAt("無効なlocal宣言です。"));
         }
     }
 }
        private static void ParseFunctionArgumentsList(Queue<KecaknoahToken> tokens, KecaknoahFunctionAstNode result)
        {
            var nt = tokens.Peek();
            switch (nt.Type)
            {
                case KecaknoahTokenType.NewLine:
                case KecaknoahTokenType.Semicolon:
                    break;
                case KecaknoahTokenType.ParenStart:
                    tokens.Dequeue();
                    while (true)
                    {
                        nt = tokens.Dequeue();
                        switch (nt.Type)
                        {
                            case KecaknoahTokenType.Identifer:
                                result.Parameters.Add(nt.TokenString);
                                tokens.CheckSkipToken(KecaknoahTokenType.Comma);
                                break;
                            case KecaknoahTokenType.VariableArguments:
                                result.AllowsVariableArguments = true;
                                if (!tokens.CheckToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(nt.CreateErrorAt("可変長引数は最後に配置してください"));
                                break;
                            case KecaknoahTokenType.ParenEnd:
                                goto EndArgsList;
                            default:
                                throw new KecaknoahParseException(nt.CreateErrorAt("仮引数リストに識別子・可変長引数以外を指定しないでください。"));
                        }

                    }
                EndArgsList:;
                    break;
            }
        }
 private KecaknoahFunctionAstNode ParseFunction(Queue<KecaknoahToken> tokens, bool top)
 {
     var result = new KecaknoahFunctionAstNode();
     if (tokens.CheckSkipToken(KecaknoahTokenType.StaticKeyword))
     {
         if (top)
         {
             throw new KecaknoahParseException(tokens.Dequeue().CreateErrorAt("トップレベルのメソッドにstaticは指定できません。"));
         }
         else
         {
             result.StaticMethod = true;
         }
     }
     var nt = tokens.Dequeue();
     if (nt.Type != KecaknoahTokenType.Identifer) throw new KecaknoahParseException(nt.CreateErrorAt("メソッド名にはキーワードではない識別子を指定してください。"));
     result.Name = nt.TokenString;
     ParseFunctionArgumentsList(tokens, result);
     if (!tokens.SkipLogicalLineBreak()) throw new KecaknoahParseException(nt.CreateErrorAt("func宣言の後ろに改行が必要です。"));
     foreach (var n in ParseBlock(tokens)) result.AddNode(n);
     if (!tokens.CheckSkipToken(KecaknoahTokenType.EndFuncKeyword)) throw new KecaknoahParseException(nt.CreateErrorAt("endfuncがありません。"));
     return result;
 }
        private KecaknoahFactorExpressionAstNode ParseFactorExpression(Queue<KecaknoahToken> tokens)
        {
            var t = tokens.Dequeue();
            string lv = "";
            switch (t.Type)
            {
                case KecaknoahTokenType.CoresumeKeyword:
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(t.CreateErrorAt("coresumeが不正です。"));
                    t = tokens.Dequeue();
                    if (t.Type != KecaknoahTokenType.Identifer) throw new KecaknoahParseException(t.CreateErrorAt("coresumeが不正です。"));
                    var result = new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.CoroutineResume, StringValue = t.TokenString };
                    if (tokens.CheckSkipToken(KecaknoahTokenType.Comma))
                    {
                        //代入とステート返却
                        result.ExpressionNode = ParseExpression(tokens);
                        result.BooleanValue = true;
                    }
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(t.CreateErrorAt("coresumeが不正です。"));
                    return result;
                case KecaknoahTokenType.And:
                    var lambda = new KecaknoahFactorExpressionAstNode();
                    lambda.FactorType = KecaknoahFactorType.Lambda;
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenStart)) throw new KecaknoahParseException(t.CreateErrorAt("ラムダ式の&には引数リストを続けてください。"));
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd))
                        while (true)
                        {
                            lambda.ElementNodes.Add(new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.Identifer, StringValue = tokens.Dequeue().TokenString });
                            if (tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) break;
                            if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("ラムダ引数がカッコで閉じていなません。"));
                        }
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.Lambda)) throw new KecaknoahParseException(t.CreateErrorAt("ラムダ式の引数リストに=>で式を続けてください。"));
                    lambda.ExpressionNode = ParseExpression(tokens);
                    return lambda;
                case KecaknoahTokenType.ParenStart:
                    tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                    var exp = ParseExpression(tokens);
                    tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                    if (!tokens.CheckSkipToken(KecaknoahTokenType.ParenEnd)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("カッコは閉じてください。"));
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.ParenExpression, ExpressionNode = exp };
                case KecaknoahTokenType.BracketStart:
                    var are = new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.Array };
                    tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                    while (true)
                    {
                        are.ElementNodes.Add(ParseExpression(tokens));
                        tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                        if (tokens.CheckSkipToken(KecaknoahTokenType.BracketEnd)) break;
                        if (!tokens.CheckSkipToken(KecaknoahTokenType.Comma)) throw new KecaknoahParseException(tokens.Peek().CreateErrorAt("配列がカッコで閉じていなません。"));
                        tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                    }
                    return are;
                case KecaknoahTokenType.TrueKeyword:
                case KecaknoahTokenType.FalseKeyword:
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.BooleanValue, BooleanValue = Convert.ToBoolean(t.TokenString) };
                case KecaknoahTokenType.NilKeyword:
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.Nil };
                case KecaknoahTokenType.VargsKeyword:
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.VariableArguments };
                case KecaknoahTokenType.Identifer:
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.Identifer, StringValue = t.TokenString };
                case KecaknoahTokenType.StringLiteral:
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.StringValue, StringValue = t.TokenString };
                case KecaknoahTokenType.BinaryNumberLiteral:
                    lv = t.TokenString.Substring(2);
                    if (lv.Length > 64) lv = lv.Substring(lv.Length - 64);
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.IntegerValue, IntegerValue = unchecked(Convert.ToInt64(lv, 2)) };
                case KecaknoahTokenType.OctadecimalNumberLiteral:
                    lv = t.TokenString.Substring(2);
                    if (lv.Length > 64) lv = lv.Substring(lv.Length - 21);
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.IntegerValue, IntegerValue = unchecked(Convert.ToInt64(lv, 8)) };
                case KecaknoahTokenType.HexadecimalNumberLiteral:
                    lv = t.TokenString.Substring(2);
                    if (lv.Length > 64) lv = lv.Substring(lv.Length - 16);
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.IntegerValue, IntegerValue = unchecked(Convert.ToInt64(lv, 16)) };
                case KecaknoahTokenType.HexatridecimalNumberLiteral:
                    return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.IntegerValue, IntegerValue = unchecked(Base36.Decode(t.TokenString.Substring(2))) };
                case KecaknoahTokenType.DecimalNumberLiteral:
                    if (t.TokenString.IndexOf('.') >= 0)
                    {
                        lv = t.TokenString.Substring(0, t.TokenString.Length - 1);
                        var v = 0.0;
                        var r = double.TryParse(lv, out v);
                        return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.DoubleValue, DoubleValue = r ? v : double.MaxValue };
                    }
                    else
                    {
                        var v = 0L;
                        var r = long.TryParse(t.TokenString, out v);
                        return new KecaknoahFactorExpressionAstNode { FactorType = KecaknoahFactorType.IntegerValue, IntegerValue = r ? v : long.MaxValue };
                    }
                default:
                    throw new KecaknoahParseException(t.CreateErrorAt("意味不明なfactorが検出されました。"));

            }
        }