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; }
internal IList<KecaknoahILCode> PrecompileBinaryExpression(KecaknoahBinaryExpressionAstNode node) { var result = new List<KecaknoahILCode>(); result.AddRange(PrecompileExpression(node.FirstNode)); result.AddRange(PrecompileExpression(node.SecondNode)); result.Add(new KecaknoahILCode { Type = (KecaknoahILCodeType)Enum.Parse(typeof(KecaknoahILCodeType), node.ExpressionType.ToString(), true) }); 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; }
internal IList<KecaknoahILCode> PrecompileBinaryExpression(KecaknoahBinaryExpressionAstNode node) { var result = new List<KecaknoahILCode>(); //ショートサーキット switch (node.ExpressionType) { /* case KecaknoahOperatorType.AndAlso: var aid = Guid.NewGuid().ToString().Substring(0, 8); result.AddRange(PrecompileExpression(node.FirstNode)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.AsValue }); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.FalseJump, StringValue = $"AndAlso-{aid}" }); result.AddRange(PrecompileExpression(node.SecondNode)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Label, StringValue = $"AndAlso-{aid}" }); break; case KecaknoahOperatorType.OrElse: var eid = Guid.NewGuid().ToString().Substring(0, 8); result.AddRange(PrecompileExpression(node.FirstNode)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.AsValue }); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.TrueJump, StringValue = $"OrElse-{eid}" }); result.AddRange(PrecompileExpression(node.SecondNode)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Label, StringValue = $"OrElse-{eid}" }); break; */ default: result.AddRange(PrecompileExpression(node.FirstNode)); result.AddRange(PrecompileExpression(node.SecondNode)); result.Add(new KecaknoahILCode { Type = (KecaknoahILCodeType)Enum.Parse(typeof(KecaknoahILCodeType), node.ExpressionType.ToString(), true) }); break; } return result; }