/// <summary> /// ノードを追加します。 /// </summary> /// <param name="node">追加するノード</param> protected internal void AddNode(KecaknoahAstNode node) => children.Add(node);
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; }
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; }
private IList<KecaknoahILCode> PrecompileExpression(KecaknoahAstNode node) { var result = new List<KecaknoahILCode>(); if (node.Type != KecaknoahAstNodeType.Expression) throw new ArgumentException("ASTが式でない件について"); var en = node as KecaknoahExpressionAstNode; if (en is KecaknoahBinaryExpressionAstNode) { var exp = en as KecaknoahBinaryExpressionAstNode; result.AddRange(PrecompileBinaryExpression(exp)); } else if (en is KecaknoahFactorExpressionAstNode) { var exp = en as KecaknoahFactorExpressionAstNode; switch (exp.FactorType) { case KecaknoahFactorType.IntegerValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushInteger, IntegerValue = exp.IntegerValue }); break; case KecaknoahFactorType.SingleValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.SingleValue }); break; case KecaknoahFactorType.DoubleValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.DoubleValue }); break; case KecaknoahFactorType.StringValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushString, StringValue = exp.StringValue }); break; case KecaknoahFactorType.BooleanValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushBoolean, BooleanValue = exp.BooleanValue }); break; case KecaknoahFactorType.Nil: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushNil }); break; case KecaknoahFactorType.Identifer: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = exp.StringValue }); break; case KecaknoahFactorType.ParenExpression: result.AddRange(PrecompileExpression(exp.ExpressionNode)); break; case KecaknoahFactorType.CoroutineResume: if (exp.BooleanValue) { // state = coresume(cor, val) result.AddRange(PrecompileExpression(exp.ExpressionNode)); } result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.ResumeCoroutine, StringValue = exp.StringValue, BooleanValue = exp.BooleanValue }); break; case KecaknoahFactorType.Array: foreach (var i in exp.ElementNodes) result.AddRange(PrecompileExpression(i)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.MakeArray, IntegerValue = exp.ElementNodes.Count }); break; case KecaknoahFactorType.Lambda: var lma = exp.ElementNodes.Select(p => ((KecaknoahFactorExpressionAstNode)p).StringValue).ToList(); var name = $"Lambda-{Guid.NewGuid().ToString().Substring(0, 17)}"; var func = new KecaknoahScriptMethodInfo(name); var eil = PrecompileExpression(exp.ExpressionNode); eil.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Return }); foreach (var i in eil.Where(p => p.Type == KecaknoahILCodeType.LoadObject && lma.Contains(p.StringValue))) { i.Type = KecaknoahILCodeType.PushArgument; i.IntegerValue = lma.IndexOf(i.StringValue); } func.Codes = new KecaknoahIL(); func.Codes.PushCodes(eil); if (cuc.Count == 0) { current.methods.Add(func); } else { cuc.Peek().AddInstanceMethod(func); } result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = name }); break; } } else if (en is KecaknoahArgumentCallExpressionAstNode) { var exp = en as KecaknoahArgumentCallExpressionAstNode; if (exp.Target is KecaknoahFactorExpressionAstNode && (exp.Target as KecaknoahFactorExpressionAstNode).FactorType == KecaknoahFactorType.VariableArguments) { //vargs foreach (var arg in exp.Arguments) result.AddRange(PrecompileExpression(arg)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadVarg, IntegerValue = exp.Arguments.Count }); } else { if (exp.ExpressionType == KecaknoahOperatorType.IndexerAccess) { result.AddRange(PrecompileIndexerCall(exp)); } else { result.AddRange(PrecompileFunctionCall(exp)); } } } else if (en is KecaknoahMemberAccessExpressionAstNode) { var exp = en as KecaknoahMemberAccessExpressionAstNode; result.AddRange(PrecompileExpression(exp.Target)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadMember, StringValue = exp.MemberName }); } else if (en is KecaknoahPrimaryExpressionAstNode) { var exp = en as KecaknoahPrimaryExpressionAstNode; //後置 switch (exp.ExpressionType) { case KecaknoahOperatorType.Increment: result.AddRange(PrecompileSuffixIncrement(exp)); break; case KecaknoahOperatorType.Decrement: result.AddRange(PrecompileSuffixDecrement(exp)); break; default: throw new NotImplementedException("多分実装してない1次式なんだと思う"); } result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Pop }); } else if (en is KecaknoahUnaryExpressionAstNode) { var exp = en as KecaknoahUnaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Minus: result.AddRange(PrecompileExpression(exp.Target)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Negative }); break; case KecaknoahOperatorType.Not: result.AddRange(PrecompileExpression(exp.Target)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Not }); break; case KecaknoahOperatorType.Increment: result.AddRange(PrecompilePrefixIncrement(exp)); break; case KecaknoahOperatorType.Decrement: result.AddRange(PrecompilePrefixDecrement(exp)); break; } } else { throw new InvalidOperationException("ごめん何言ってるかさっぱりわかんない"); } return result; }
private IList<KecaknoahILCode> PrecompileExpression(KecaknoahAstNode node) { var result = new List<KecaknoahILCode>(); if (node.Type != KecaknoahAstNodeType.Expression) throw new ArgumentException("ASTが式でない件について"); var en = node as KecaknoahExpressionAstNode; if (en is KecaknoahBinaryExpressionAstNode) { var exp = en as KecaknoahBinaryExpressionAstNode; result.AddRange(PrecompileBinaryExpression(exp)); } else if (en is KecaknoahFactorExpressionAstNode) { var exp = en as KecaknoahFactorExpressionAstNode; switch (exp.FactorType) { case KecaknoahFactorType.IntegerValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushInteger, IntegerValue = exp.IntegerValue }); break; case KecaknoahFactorType.SingleValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.SingleValue }); break; case KecaknoahFactorType.DoubleValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.DoubleValue }); break; case KecaknoahFactorType.StringValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushString, StringValue = exp.StringValue }); break; case KecaknoahFactorType.BooleanValue: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushBoolean, BooleanValue = exp.BooleanValue }); break; case KecaknoahFactorType.Nil: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushNil }); break; case KecaknoahFactorType.Identifer: result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = exp.StringValue }); break; case KecaknoahFactorType.ParenExpression: result.AddRange(PrecompileExpression(exp.ExpressionNode)); break; case KecaknoahFactorType.CoroutineResume: if (exp.BooleanValue) { // state = coresume(cor, val) result.AddRange(PrecompileExpression(exp.ExpressionNode)); } result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.ResumeCoroutine, StringValue = exp.StringValue, BooleanValue = exp.BooleanValue }); break; case KecaknoahFactorType.Array: foreach (var i in exp.ElementNodes) result.AddRange(PrecompileExpression(i)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.MakeArray, IntegerValue = exp.ElementNodes.Count }); break; case KecaknoahFactorType.Lambda: result.AddRange(PrecompileLambda(exp)); break; } } else if (en is KecaknoahArgumentCallExpressionAstNode) { var exp = en as KecaknoahArgumentCallExpressionAstNode; if (exp.Target is KecaknoahFactorExpressionAstNode && (exp.Target as KecaknoahFactorExpressionAstNode).FactorType == KecaknoahFactorType.VariableArguments) { //vargs foreach (var arg in exp.Arguments) result.AddRange(PrecompileExpression(arg)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadVarg, IntegerValue = exp.Arguments.Count }); } else { if (exp.ExpressionType == KecaknoahOperatorType.IndexerAccess) { result.AddRange(PrecompileIndexerCall(exp)); } else { result.AddRange(PrecompileFunctionCall(exp)); } } } else if (en is KecaknoahMemberAccessExpressionAstNode) { var exp = en as KecaknoahMemberAccessExpressionAstNode; result.AddRange(PrecompileExpression(exp.Target)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadMember, StringValue = exp.MemberName }); } else if (en is KecaknoahPrimaryExpressionAstNode) { var exp = en as KecaknoahPrimaryExpressionAstNode; //後置 switch (exp.ExpressionType) { case KecaknoahOperatorType.Increment: result.AddRange(PrecompileSuffixIncrement(exp)); break; case KecaknoahOperatorType.Decrement: result.AddRange(PrecompileSuffixDecrement(exp)); break; default: throw new NotImplementedException("多分実装してない1次式なんだと思う"); } result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Pop }); } else if (en is KecaknoahUnaryExpressionAstNode) { var exp = en as KecaknoahUnaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Minus: result.AddRange(PrecompileExpression(exp.Target)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Negative }); break; case KecaknoahOperatorType.Not: result.AddRange(PrecompileExpression(exp.Target)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Not }); break; case KecaknoahOperatorType.Increment: result.AddRange(PrecompilePrefixIncrement(exp)); break; case KecaknoahOperatorType.Decrement: result.AddRange(PrecompilePrefixDecrement(exp)); break; } } else { throw new InvalidOperationException("ごめん何言ってるかさっぱりわかんない"); } return result; }