Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        private static ExpressionBase ParseClauseCore(PositionalTokenizer tokenizer)
        {
            ExpressionBase clause;

            switch (tokenizer.NextChar)
            {
            case '!':
                tokenizer.Advance();
                clause = ParseClause(tokenizer);
                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }

                return(new ConditionalExpression(null, ConditionalOperation.Not, clause));

            case '(':
                tokenizer.Advance();
                clause = ExpressionBase.Parse(tokenizer);
                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }

                if (tokenizer.NextChar != ')')
                {
                    if (tokenizer.NextChar == '\0')
                    {
                        return(ParseError(tokenizer, "No closing parenthesis found"));
                    }

                    return(ParseError(tokenizer, "Expected closing parenthesis, found: " + tokenizer.NextChar));
                }

                clause.IsLogicalUnit = true;
                tokenizer.Advance();
                return(clause);

            case '"':
                try
                {
                    var stringValue = tokenizer.ReadQuotedString().ToString();
                    return(new StringConstantExpression(stringValue));
                }
                catch (InvalidOperationException ex)
                {
                    return(ParseError(tokenizer, ex.Message));
                }

            case '0':
                if (tokenizer.Match("0x"))
                {
                    string hexNumber = "";
                    while (Char.IsDigit(tokenizer.NextChar) || (tokenizer.NextChar >= 'A' && tokenizer.NextChar <= 'F') || (tokenizer.NextChar >= 'a' && tokenizer.NextChar <= 'f'))
                    {
                        hexNumber += tokenizer.NextChar;
                        tokenizer.Advance();
                    }

                    int hexValue = 0;
                    Int32.TryParse(hexNumber, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hexValue);
                    return(new IntegerConstantExpression(hexValue));
                }
                goto case '1';

            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                var  number = tokenizer.ReadNumber();
                uint value;
                UInt32.TryParse(number.ToString(), out value);
                return(new IntegerConstantExpression((int)value));
            }

            case '-':
                tokenizer.Advance();
                if (tokenizer.NextChar >= '0' && tokenizer.NextChar <= '9')
                {
                    if (tokenizer.Match("0x"))
                    {
                        string hexNumber = "";
                        while (Char.IsDigit(tokenizer.NextChar) || (tokenizer.NextChar >= 'A' && tokenizer.NextChar <= 'F') || (tokenizer.NextChar >= 'a' && tokenizer.NextChar <= 'f'))
                        {
                            hexNumber += tokenizer.NextChar;
                            tokenizer.Advance();
                        }

                        int hexValue = 0;
                        Int32.TryParse(hexNumber, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hexValue);
                        return(new IntegerConstantExpression(-hexValue));
                    }

                    var number = tokenizer.ReadNumber();
                    int value;
                    Int32.TryParse(number.ToString(), out value);
                    return(new IntegerConstantExpression(-value));
                }
                return(ParseError(tokenizer, "Minus without value"));

            case '{':
                tokenizer.Advance();
                return(DictionaryExpression.Parse(tokenizer));

            case '[':
                tokenizer.Advance();
                return(ParseArray(tokenizer));

            default:
                var line       = tokenizer.Line;
                var column     = tokenizer.Column;
                var identifier = tokenizer.ReadIdentifier();
                if (identifier.IsEmpty)
                {
                    var error = ParseError(tokenizer, "Unexpected character: " + tokenizer.NextChar);
                    tokenizer.Advance();
                    return(error);
                }

                SkipWhitespace(tokenizer);

                if (identifier == "return")
                {
                    clause = ExpressionBase.Parse(tokenizer);
                    if (clause.Type == ExpressionType.ParseError)
                    {
                        return(clause);
                    }

                    return(new ReturnExpression(new KeywordExpression(identifier.ToString(), line, column), clause));
                }

                if (identifier == "function")
                {
                    return(FunctionDefinitionExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "for")
                {
                    return(ForExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "if")
                {
                    return(IfExpression.Parse(tokenizer, line, column));
                }

                if (tokenizer.NextChar == '(')
                {
                    tokenizer.Advance();

                    var parameters = new List <ExpressionBase>();
                    ParseParameters(tokenizer, parameters);

                    var functionCall = new FunctionCallExpression(new VariableExpression(identifier.ToString(), line, column), parameters);
                    functionCall.EndLine   = tokenizer.Line;
                    functionCall.EndColumn = tokenizer.Column - 1;
                    return(functionCall);
                }

                if (tokenizer.NextChar == '[')
                {
                    IndexedVariableExpression parent = null;

                    do
                    {
                        tokenizer.Advance();

                        var index = ExpressionBase.Parse(tokenizer);
                        if (index.Type == ExpressionType.ParseError)
                        {
                            return(index);
                        }

                        SkipWhitespace(tokenizer);
                        if (tokenizer.NextChar != ']')
                        {
                            return(ParseError(tokenizer, "Expecting closing bracket after index"));
                        }
                        tokenizer.Advance();
                        SkipWhitespace(tokenizer);

                        if (parent != null)
                        {
                            parent = new IndexedVariableExpression(parent, index);
                        }
                        else
                        {
                            parent = new IndexedVariableExpression(new VariableExpression(identifier.ToString(), line, column), index);
                        }
                    } while (tokenizer.NextChar == '[');

                    return(parent);
                }

                return(new VariableExpression(identifier.ToString(), line, column));
            }
        }