/// <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が検出されました。")); } }