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 IList<KecaknoahILCode> PrecompileWhile(KecaknoahLoopAstNode fn) { var id = Guid.NewGuid().ToString().Substring(0, 8); var result = new List<KecaknoahILCode>(); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Label, StringValue = $"{id}" }); result.AddRange(PrecompileExpression(fn.Condition)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.FalseJump, StringValue = $"{id}-End" }); result.AddRange(PrecompileBlock(fn.Children, id)); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Jump, StringValue = $"{id}" }); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Label, StringValue = $"{id}-End" }); return result; }