예제 #1
0
 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;
 }
예제 #2
0
 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;
 }
예제 #3
0
        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;
        }
예제 #4
0
 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;
 }
예제 #5
0
 private KecaknoahReturnAstNode ParseReturn(Queue<KecaknoahToken> tokens)
 {
     var result = new KecaknoahReturnAstNode();
     var nt = tokens.Dequeue();
     result.Type = nt.Type == KecaknoahTokenType.ReturnKeyword ? KecaknoahAstNodeType.ReturnStatement : KecaknoahAstNodeType.YieldStatement;
     if (!tokens.SkipLogicalLineBreak()) result.Value = ParseExpression(tokens);
     return result;
 }
예제 #6
0
 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;
 }
예제 #7
0
 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宣言です。"));
         }
     }
 }
예제 #8
0
 private KecaknoahAstNode ParseFirstLevel(Queue<KecaknoahToken> tokens)
 {
     var result = new KecaknoahAstNode();
     tokens.SkipLogicalLineBreak();
     try
     {
         while (tokens.Count != 0)
         {
             var t = tokens.Dequeue();
             switch (t.Type)
             {
                 case KecaknoahTokenType.UseKeyword:
                     t = tokens.Dequeue();
                     if (t.Type != KecaknoahTokenType.StringLiteral) throw new KecaknoahParseException(t.CreateErrorAt("use文には文字列を指定してください。"));
                     result.AddNode(new KecaknoahUseAstNode { Target = t.TokenString });
                     break;
                 case KecaknoahTokenType.ClassKeyword:
                     result.AddNode(ParseClass(tokens));
                     break;
                 case KecaknoahTokenType.FuncKeyword:
                     result.AddNode(ParseFunction(tokens, true));
                     break;
                 default:
                     throw new KecaknoahParseException(t.CreateErrorAt("トップレベルにはクラスとメソッド、use文以外は定義できません。"));
             }
             tokens.SkipLogicalLineBreak();
         }
     }
     catch (KecaknoahParseException)
     {
         throw;
     }
     return result;
 }
예제 #9
0
 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;
 }
예제 #10
0
 private IList<KecaknoahAstNode> ParseBlock(Queue<KecaknoahToken> tokens)
 {
     var result = new List<KecaknoahAstNode>();
     while (true)
     {
         tokens.SkipLogicalLineBreak();
         //式かもしれないのでPeek
         var nt = tokens.Peek();
         switch (nt.Type)
         {
             case KecaknoahTokenType.IfKeyword:
                 tokens.Dequeue();
                 result.Add(ParseIf(tokens, false));
                 break;
             case KecaknoahTokenType.CaseKeyword:
                 tokens.Dequeue();
                 result.Add(ParseCase(tokens));
                 break;
             case KecaknoahTokenType.ForKeyword:
                 tokens.Dequeue();
                 result.Add(ParseFor(tokens, false));
                 break;
             case KecaknoahTokenType.WhileKeyword:
                 tokens.Dequeue();
                 result.Add(ParseWhile(tokens, false));
                 break;
             case KecaknoahTokenType.ForeachKeyword:
                 tokens.Dequeue();
                 result.Add(ParseForeach(tokens, false));
                 break;
             case KecaknoahTokenType.DoKeyword:
                 break;
             case KecaknoahTokenType.ElifKeyword:
             case KecaknoahTokenType.ElseKeyword:
             case KecaknoahTokenType.EndifKeyword:
             case KecaknoahTokenType.WhenKeyword:
             case KecaknoahTokenType.DefaultKeyword:
             case KecaknoahTokenType.EndCaseKeyword:
             case KecaknoahTokenType.EndFuncKeyword:
             case KecaknoahTokenType.NextKeyword:
                 //呼ばれ元で終了判定するから飛ばさないでね
                 goto EndBlock;
             default:
                 result.AddRange(ParseSingleLineStatement(tokens));
                 break;
         }
     }
 EndBlock: return result;
 }
예제 #11
0
        private KecaknoahClassAstNode ParseClass(Queue<KecaknoahToken> tokens)
        {
            var result = new KecaknoahClassAstNode();
            var nt = tokens.Dequeue();
            if (nt.Type != KecaknoahTokenType.Identifer) throw new KecaknoahParseException(nt.CreateErrorAt("クラス名にはキーワードではない識別子を指定してください。"));
            result.Name = nt.TokenString;
            if (!tokens.SkipLogicalLineBreak()) throw new KecaknoahParseException(nt.CreateErrorAt("class宣言の後ろに改行が必要です。"));

            while (true)
            {
                tokens.SkipLogicalLineBreak();
                var t = tokens.Dequeue();
                if (t.Type == KecaknoahTokenType.EndclassKeyword) break;
                switch (t.Type)
                {
                    case KecaknoahTokenType.FuncKeyword:
                        result.AddFunctionNode(ParseFunction(tokens, false));
                        break;
                    case KecaknoahTokenType.LocalKeyword:
                        result.AddLocalNode(ParseLocal(tokens));
                        break;
                    default:
                        throw new KecaknoahParseException(nt.CreateErrorAt("クラス内にはメソッドかlocal宣言のみ記述出来ます。"));
                }
            }
            return result;
        }
예제 #12
0
 private KecaknoahAstNode ParseFirstLevel(Queue<KecaknoahToken> tokens)
 {
     var result = new KecaknoahAstNode();
     tokens.SkipLogicalLineBreak();
     try
     {
         while (tokens.Count != 0)
         {
             var t = tokens.Dequeue();
             switch (t.Type)
             {
                 case KecaknoahTokenType.ClassKeyword:
                     result.AddNode(ParseClass(tokens));
                     break;
                 case KecaknoahTokenType.FuncKeyword:
                     result.AddNode(ParseFunction(tokens, true));
                     break;
                 default:
                     throw new KecaknoahParseException(t.CreateErrorAt("トップレベルにはクラスとメソッド以外は定義できません。"));
             }
             tokens.SkipLogicalLineBreak();
         }
     }
     catch (KecaknoahParseException)
     {
         throw;
     }
     return result;
 }
예제 #13
0
        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が検出されました。"));

            }
        }
예제 #14
0
        private KecaknoahExpressionAstNode ParseBinaryExpression(Queue<KecaknoahToken> tokens, int priority)
        {
            if (priority > OperatorMaxPriority) return ParseUnaryExpression(tokens);
            var left = ParseBinaryExpression(tokens, priority + 1);
            var result = new KecaknoahBinaryExpressionAstNode();
            result.FirstNode = left;
            while (true)
            {
                if (tokens.Count == 0) break;
                if (tokens.CheckToken(
                    KecaknoahTokenType.ParenEnd, KecaknoahTokenType.Comma, KecaknoahTokenType.BracketEnd,
                    KecaknoahTokenType.ThenKeyword, KecaknoahTokenType.ElseKeyword, KecaknoahTokenType.Semicolon,
                    KecaknoahTokenType.NewLine, KecaknoahTokenType.Colon))
                {
                    //tokens.Dequeue();
                    break;
                }
                var nt = tokens.Peek();
                if (OperatorPriorities[nt.Type] != priority) break;
                tokens.Dequeue();
                tokens.SkipLogicalLineBreak();    //TODO: 暗黙改行
                var right = ParseBinaryExpression(tokens, priority + 1);

                result.SecondNode = right;
                result.ExpressionType = OperatorsTokenTable[nt.Type];
                var newres = new KecaknoahBinaryExpressionAstNode();
                newres.FirstNode = result;
                result = newres;
            }
            if (priority == 1)
            {
                var pn = result.FirstNode as KecaknoahBinaryExpressionAstNode;
                if (pn == null) return result.FirstNode;
                while (pn.FirstNode is KecaknoahBinaryExpressionAstNode)
                {
                    switch (pn.ExpressionType)
                    {
                        case KecaknoahOperatorType.Assign:
                        case KecaknoahOperatorType.PlusAssign:
                        case KecaknoahOperatorType.MinusAssign:
                        case KecaknoahOperatorType.MultiplyAssign:
                        case KecaknoahOperatorType.DivideAssign:
                        case KecaknoahOperatorType.AndAssign:
                        case KecaknoahOperatorType.OrAssign:
                        case KecaknoahOperatorType.XorAssign:
                        case KecaknoahOperatorType.ModularAssign:
                        case KecaknoahOperatorType.LeftBitShiftAssign:
                        case KecaknoahOperatorType.RightBitShiftAssign:
                        case KecaknoahOperatorType.NilAssign:
                            break;
                        default:
                            return pn;
                    }
                    var kb = pn.FirstNode as KecaknoahBinaryExpressionAstNode;
                    var nn = new KecaknoahBinaryExpressionAstNode();
                    nn.ExpressionType = pn.ExpressionType;
                    nn.SecondNode = pn.SecondNode;
                    nn.FirstNode = kb.SecondNode;
                    pn.FirstNode = kb.FirstNode;
                    pn.SecondNode = nn;
                }
                return pn;
            }
            return result.FirstNode;
        }
예제 #15
0
        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;
        }
예제 #16
0
 /// <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;
 }
예제 #17
0
 private KecaknoahTryAstNode ParseTry(Queue<KecaknoahToken> tokens)
 {
     var result = new KecaknoahTryAstNode();
     tokens.SkipLogicalLineBreak();
     result.AddNode(ParseBlock(tokens));
     while (true)
     {
         var nt = tokens.Dequeue();
         switch (nt.Type)
         {
             case KecaknoahTokenType.CatchKeyword:
                 nt = tokens.Dequeue();
                 if (nt.Type != KecaknoahTokenType.Identifer) throw new KecaknoahParseException(nt.CreateErrorAt("catchブロックに変数名を指定してください。"));
                 result.CatcherVariableName = nt.TokenString;
                 tokens.SkipLogicalLineBreak();
                 result.CatcherBlock.Clear();
                 result.CatcherBlock = ParseBlock(tokens);
                 break;
             case KecaknoahTokenType.FinallyKeyword:
                 nt = tokens.Dequeue();
                 tokens.SkipLogicalLineBreak();
                 result.FinallyBlock.Clear();
                 result.FinallyBlock = ParseBlock(tokens);
                 break;
             case KecaknoahTokenType.EndTryKeyword:
                 goto EndTry;
             default:
                 throw new KecaknoahParseException(nt.CreateErrorAt("不正なtry文です。"));
         }
     }
     EndTry: return result;
 }