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が検出されました。")); } }
private IList<KecaknoahILCode> PrecompileLambda(KecaknoahFactorExpressionAstNode exp) { var il = PrecompileExpression(exp.ExpressionNode); il.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Return }); var lma = exp.ElementNodes.Select(p => ((KecaknoahFactorExpressionAstNode)p).StringValue).ToList(); switch (CheckLocalReference(exp, lma)) { case 0: return PrecompileClassLambda(il, lma); case 1: case 2: return PrecompileLexicalLambda(il, lma); default: throw new ArgumentException("ラムダ式の形式が不正です。"); } }