internal static void SkipWhitespace(PositionalTokenizer tokenizer) { tokenizer.SkipWhitespace(); while (tokenizer.Match("//")) { var expressionTokenizer = tokenizer as ExpressionTokenizer; if (expressionTokenizer != null) { int line = tokenizer.Line; int column = tokenizer.Column - 2; var comment = tokenizer.ReadTo('\n'); if (comment.Length > 0 && comment[comment.Length - 1] == '\r') { comment = comment.SubToken(0, comment.Length - 1); } expressionTokenizer.AddComment(new CommentExpression("//" + comment.ToString()) { Location = new TextRange(line, column, line, column + comment.Length + 1) }); } else { tokenizer.ReadTo('\n'); } tokenizer.SkipWhitespace(); } }
private ParseErrorExpression ProcessRichPresenceDisplay(StringConstantExpression stringExpression, InterpreterScope scope, out string displayString) { displayString = null; ExpressionBase result; var varargs = GetParameter(scope, "varargs", out result) as ArrayExpression; if (varargs == null) { var error = result as ParseErrorExpression; if (error == null) { error = new ParseErrorExpression("unexpected varargs", stringExpression); } return(error); } var context = scope.GetContext <RichPresenceDisplayContext>(); var builder = context.DisplayString; var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(stringExpression.Value)); while (tokenizer.NextChar != '\0') { var token = tokenizer.ReadTo('{'); builder.Append(token.ToString()); if (tokenizer.NextChar == '\0') { break; } var positionalTokenColumn = tokenizer.Column; tokenizer.Advance(); var index = tokenizer.ReadNumber(); if (tokenizer.NextChar != '}') { return(new ParseErrorExpression("Invalid positional token", stringExpression.Line, stringExpression.Column + positionalTokenColumn, stringExpression.Line, stringExpression.Column + tokenizer.Column - 1)); } tokenizer.Advance(); var parameterIndex = Int32.Parse(index.ToString()); if (parameterIndex >= varargs.Entries.Count) { return(new ParseErrorExpression("Invalid parameter index: " + parameterIndex, stringExpression.Line, stringExpression.Column + positionalTokenColumn, stringExpression.Line, stringExpression.Column + tokenizer.Column - 1)); } var functionCall = varargs.Entries[parameterIndex] as FunctionCallExpression; var functionDefinition = scope.GetFunction(functionCall.FunctionName.Name); if (functionDefinition == null) { return(new ParseErrorExpression("Unknown function: " + functionCall.FunctionName.Name)); } var richPresenceFunction = functionDefinition as FunctionDefinition; if (richPresenceFunction == null) { return(new ParseErrorExpression(functionCall.FunctionName.Name + " cannot be called as a rich_presence_display parameter", functionCall)); } var error = richPresenceFunction.BuildMacro(context, scope, functionCall); if (error != null) { return(new ParseErrorExpression(error, functionCall)); } } displayString = builder.ToString(); return(null); }
public string GetFormattedErrorMessage(Tokenizer tokenizer) { var neededLines = new List <int>(); var error = Error; while (error != null) { for (int i = error.Location.Start.Line; i <= error.Location.End.Line; i++) { if (!neededLines.Contains(i)) { neededLines.Add(i); } } error = error.InnerError; } neededLines.Sort(); var lineDictionary = new TinyDictionary <int, string>(); var positionalTokenizer = new PositionalTokenizer(tokenizer); int lineIndex = 0; while (lineIndex < neededLines.Count) { while (positionalTokenizer.NextChar != '\0' && positionalTokenizer.Line != neededLines[lineIndex]) { positionalTokenizer.ReadTo('\n'); positionalTokenizer.Advance(); } lineDictionary[neededLines[lineIndex]] = positionalTokenizer.ReadTo('\n').TrimRight().ToString(); lineIndex++; } var builder = new StringBuilder(); error = Error; while (error != null) { builder.AppendFormat("{0}:{1} {2}", error.Location.Start.Line, error.Location.Start.Column, error.Message); builder.AppendLine(); //for (int i = error.Line; i <= error.EndLine; i++) int i = error.Location.Start.Line; // TODO: show all lines associated to error? { var line = lineDictionary[error.Location.Start.Line]; builder.Append(":: "); var startColumn = 0; while (Char.IsWhiteSpace(line[startColumn])) { startColumn++; } if (i == error.Location.Start.Line) { builder.Append("{{color|#C0C0C0|"); builder.Append(line.Substring(startColumn, error.Location.Start.Column - startColumn - 1)); builder.Append("}}"); startColumn = error.Location.Start.Column - 1; } if (i == error.Location.End.Line) { builder.Append(line.Substring(startColumn, error.Location.End.Column - startColumn)); builder.Append("{{color|#C0C0C0|"); builder.Append(line.Substring(error.Location.End.Column)); builder.Append("}}"); } else { builder.Append(line.Substring(startColumn)); } builder.AppendLine(); } builder.AppendLine(); error = error.InnerError; } while (builder.Length > 0 && Char.IsWhiteSpace(builder[builder.Length - 1])) { builder.Length--; } return(builder.ToString()); }
public override bool Evaluate(InterpreterScope scope, out ExpressionBase result) { var stringExpression = GetStringParameter(scope, "format_string", out result); if (stringExpression == null) { return(false); } var varargs = GetParameter(scope, "varargs", out result) as ArrayExpression; if (varargs == null) { if (!(result is ParseErrorExpression)) { result = new ParseErrorExpression("unexpected varargs", stringExpression); } return(false); } var builder = new StringBuilder(); var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(stringExpression.Value)); while (tokenizer.NextChar != '\0') { var token = tokenizer.ReadTo('{'); builder.Append(token.ToString()); if (tokenizer.NextChar == '\0') { break; } var positionalTokenColumn = tokenizer.Column; tokenizer.Advance(); if (tokenizer.NextChar == '}') { result = new ParseErrorExpression("Empty parameter index", stringExpression.Location.Start.Line, stringExpression.Location.Start.Column + positionalTokenColumn, stringExpression.Location.Start.Line, stringExpression.Location.Start.Column + tokenizer.Column - 1); return(false); } var index = tokenizer.ReadNumber(); if (tokenizer.NextChar != '}') { result = new ParseErrorExpression("Invalid positional token", stringExpression.Location.Start.Line, stringExpression.Location.Start.Column + positionalTokenColumn, stringExpression.Location.Start.Line, stringExpression.Location.Start.Column + tokenizer.Column - 1); return(false); } tokenizer.Advance(); Int32 parameterIndex; if (!Int32.TryParse(index.ToString(), out parameterIndex) || parameterIndex < 0 || parameterIndex >= varargs.Entries.Count) { result = new ParseErrorExpression("Invalid parameter index: " + index.ToString(), stringExpression.Location.Start.Line, stringExpression.Location.Start.Column + positionalTokenColumn, stringExpression.Location.Start.Line, stringExpression.Location.Start.Column + tokenizer.Column - 1); return(false); } result = varargs.Entries[parameterIndex]; var functionCall = result as FunctionCallExpression; if (functionCall != null) { if (!functionCall.Evaluate(scope, out result)) { return(false); } } if (result.IsLiteralConstant) { result.AppendStringLiteral(builder); } else { result = new ParseErrorExpression("Cannot convert expression to string", result); return(false); } } result = new StringConstantExpression(builder.ToString()); return(true); }