/// <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> /// <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 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; }
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; } }