public static void AssertTypeMatch(Token token, TokenType tokenType) { if (token.TokenType != tokenType) { RevnException.ThrowParserException($"{tokenType} expected", token); } }
private ExpressionAST ParseVariableAssignment() { var variable = new VariableExpressionAST(); variable.IsToSet = true; variable.IsMutable = parser.LastToken.TokenType == TokenType.Var; parser.ProceedToken(); // val/var を消費 Assert.AssertTypeMatch(parser.LastToken, TokenType.Identifier); variable.Name = parser.LastToken.Value; parser.ProceedToken(); // 変数名を消費 if (parser.LastToken.TokenType == TokenType.BlockStartOrColon) { parser.ProceedToken(); // : を消費 Assert.AssertTypeMatch(parser.LastToken, TokenType.Identifier); variable.ReturnType = parser.LastToken.Value; parser.ProceedToken(); // 型を消費 } if (parser.LastToken.TokenType != TokenType.Equals) { if (variable.ReturnType == null) { RevnException.ThrowParserException($"Variable {variable.Name} must have a type.", parser.LastToken); } functionGenerator.AddVariable(variable); return(variable); } parser.ProceedToken(); // = を消費 var assignment = new AssignmentAST { LHS = variable, RHS = GenerateExpressionAST() }; if (variable.ReturnType == null) { variable.ReturnType = assignment.RHS.ReturnType; } functionGenerator.AddVariable(variable); return(assignment); }
private List <Argument> GenerateArgs() { Assert.AssertTypeMatch(parser.LastToken, TokenType.LParen); var args = new List <Argument>(); Argument arg = new Argument(); // 一回目のループで ( は消費される while (parser.ProceedToken().TokenType != TokenType.RParen) { // TODO 引数を区切るコンマの場合 arg を初期化 // if (LastToken.TokenType == TokenType.Comma) arg.Name = parser.LastToken.Value; parser.ProceedToken(); // 引数名を消費 if (parser.LastToken.TokenType != TokenType.BlockStartOrColon) { RevnException.ThrowParserException("Excpected ':'", parser.LastToken); } parser.ProceedToken(); // : を消費 arg.Type = parser.LastToken.Value; parser.ProceedToken(); // 型名を消費 // TODO string だけ一応今は特別対応 if (arg.Type.ToLower() == "string") { arg.Type = "string"; } // 配列だけ一応分けておく(多分プロパティになる気がする) if (parser.LastToken.TokenType == TokenType.LBracket) { arg.Type += parser.LastToken.Value; parser.ProceedToken(); arg.Type += parser.LastToken.Value; } args.Add(arg); } parser.ProceedToken(); // ) を消費 return(args); }
private ExpressionAST ParseIdentifier(string inferedType) { string identifier = parser.LastToken.Value; parser.ProceedToken(); while (parser.LastToken.TokenType == TokenType.Period) { parser.ProceedToken(); // . を消費 Assert.AssertTypeMatch(parser.LastToken, TokenType.Identifier); identifier += "." + parser.LastToken.Value; parser.ProceedToken(); // 変数を消費 } if (parser.LastToken.TokenType != TokenType.LParen) { if (!functionGenerator.HasLocalVariable(identifier)) { RevnException.ThrowParserException("Variable is not assigned.", parser.LastToken); } string type = functionGenerator.GetVariable(identifier).ReturnType; var variable = new VariableExpressionAST(); variable.ReturnType = type; variable.Name = identifier; variable.Index = LocalVariableIndex; return(variable); } if (inferedType == null) { inferedType = "void"; } parser.ProceedToken(); // ( を消費 var args = new List <ExpressionAST>(); if (parser.LastToken.TokenType != TokenType.RParen) { while (true) { var arg = GenerateExpressionAST(); args.Add(arg); if (parser.LastToken.TokenType == TokenType.RParen) { break; } if (parser.LastToken.TokenType != TokenType.Comma) { RevnException.ThrowParserException("Expected comma or )", parser.LastToken); } parser.ProceedToken(); // , を消費 } } parser.ProceedToken(); // ) を消費 return(new CallExpressionAST(identifier, args, inferedType)); }