public bool IsDefinedExpression(CTokenReader Tokens)
        {
            if (Tokens.Current.Raw == "(")
            {
                Tokens.MoveNextNoSpace();

                var Result = IsDefinedExpression(Tokens);

                Tokens.ExpectCurrent(")");
                Tokens.MoveNextNoSpace();
                return(Result);
            }

            if (Tokens.Current.Type != CTokenType.Identifier)
            {
                throw (new InvalidOperationException("Error!"));
            }

            var Identifier = Tokens.Current.Raw;

            Tokens.MoveNextNoSpace();

            //Console.WriteLine("IsDefined: {0}", Identifier);
            return(Macros.ContainsKey(Identifier));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="Context"></param>
        /// <returns></returns>
        public int EvaluateExpressionTernary(CTokenReader Tokens)
        {
            // TODO:
            var Left    = EvaluateExpressionLogicalOr(Tokens);
            var Current = Tokens.Current.Raw;

            if (Current == "?")
            {
                Tokens.MoveNextNoSpace();
                var TrueCond = EvaluateExpression(Tokens);
                Tokens.ExpectCurrent(":");
                Tokens.MoveNextNoSpace();
                var FalseCond = EvaluateExpressionTernary(Tokens);
                Left = TrinaryOperation(Left, TrueCond, FalseCond);
            }
            return(Left);
        }
        public int EvaluateExpressionUnary(CTokenReader Tokens)
        {
            switch (Tokens.Current.Type)
            {
            case CTokenType.Char:
            {
                var Value = (int)Tokens.Current.GetCharValue();
                Tokens.MoveNextNoSpace();
                return(Value);
            }

            case CTokenType.Integer:
            {
                var Value = (int)Tokens.Current.GetLongValue();
                Tokens.MoveNextNoSpace();
                return(Value);
            }

            case CTokenType.Float:
            {
                var Value = (float)Tokens.Current.GetDoubleValue();
                Tokens.MoveNextNoSpace();
                return((int)Value);
            }

            case CTokenType.Identifier:
            {
                if (Tokens.Current.Raw == "defined")
                {
                    Tokens.MoveNextNoSpace();
                    var Result = IsDefinedExpression(Tokens);
                    //Console.WriteLine(Result);
                    return(Result ? 1 : 0);
                }

                Macro  ValueMacro;
                string ValueString = "";
                int    ValueInt    = 0;

                if (Macros.TryGetValue(Tokens.Current.Raw, out ValueMacro))
                {
                    ValueString = ValueMacro.Replacement;
                }
                int.TryParse(ValueString, out ValueInt);

                Tokens.MoveNextNoSpace();

                return(ValueInt);
            }

            case CTokenType.Operator:
                switch (Tokens.Current.Raw)
                {
                case "(":
                {
                    Tokens.MoveNextNoSpace();
                    int Result = EvaluateExpression(Tokens);
                    Tokens.ExpectCurrent(")");
                    Tokens.MoveNextNoSpace();
                    return(Result);
                }

                case "-":
                case "!":
                case "+":
                {
                    var Operator = Tokens.Current.Raw;
                    Tokens.MoveNextNoSpace();
                    return(UnaryOperation(Operator, EvaluateExpressionUnary(Tokens)));
                }

                default:
                    Console.Error.WriteLine("Line: {0}", Tokens);
                    throw (new NotImplementedException(String.Format("Unknown preprocessor unary operator : {0}", Tokens.Current.Raw)));
                }

            default:
            {
                ShowLine(Tokens.Current);
                throw (new NotImplementedException(String.Format("Can't handle {0}", Tokens.Current)));
            }
            }
        }
Beispiel #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="Texts"></param>
        /// <returns></returns>
        private string Expand(string Text, Dictionary <string, string> Locals = null, HashSet <string> Used = null)
        {
            if (Used == null)
            {
                Used = new HashSet <string>();
            }
            string Output = "";
            var    Tokens = new CTokenReader(new CTokenizer(Text, TokenizeSpaces: true).Tokenize());

            Tokens.MoveNextSpace();
            while (Tokens.HasMore)
            {
                bool Stringify = false;

                if (Locals != null && Tokens.Current.Raw == "##")
                {
                    Tokens.MoveNextSpace();
                }

                if (Tokens.Current.Raw == "#")
                {
                    Tokens.MoveNextSpace();
                    if (Tokens.Current.Type == CTokenType.Identifier)
                    {
                        Stringify = true;
                    }
                    else
                    {
                        Stringify = false;
                        Output   += "#";
                    }
                }

                if (Tokens.Current.Type == CTokenType.Identifier)
                {
                    var CurrentIdentifier = Tokens.Current.Raw;
                    var UpdatedIdentifier = ReplaceSimpleVariable(CurrentIdentifier);
                    if (UpdatedIdentifier != CurrentIdentifier)
                    {
                        Output += UpdatedIdentifier;
                        Tokens.MoveNextSpace();
                        continue;
                    }
                    switch (CurrentIdentifier)
                    {
                    case "__VA_ARGS__":
                        CurrentIdentifier = "...";
                        break;
                    }

                    if (Locals != null && Locals.ContainsKey(CurrentIdentifier))
                    {
                        CurrentIdentifier = Locals[CurrentIdentifier];
                        if (Stringify)
                        {
                            CurrentIdentifier = CToken.Stringify(CurrentIdentifier);
                        }
                        Output += CurrentIdentifier;
                        Tokens.MoveNextSpace();
                    }
                    else if (!Used.Contains(CurrentIdentifier) && Context.Macros.ContainsKey(CurrentIdentifier))
                    {
                        var Macro = Context.Macros[CurrentIdentifier];

                        // Constant
                        if (Macro is MacroConstant)
                        {
                            Output += Expand(Macro.Replacement, null, new HashSet <string>(Used.Concat(new[] { CurrentIdentifier })));
                            Tokens.MoveNextSpace();
                        }
                        // Function
                        else
                        {
                            Tokens.MoveNextNoSpace();
                            Tokens.ExpectCurrent("(");
                            var MacroFunction = Context.Macros[CurrentIdentifier] as MacroFunction;

                            if (MacroFunction == null)
                            {
                                throw (new Exception("Trying to call a non-function macro"));
                            }

                            //Console.WriteLine(":: {0} :: ", Text);

                            var Parameters = ParseParameterList(Tokens, JustIdentifiers: false);
                            for (int n = 0; n < Parameters.Length; n++)
                            {
                                //Console.WriteLine("  {0}", Parameters[n]);
                                Parameters[n] = Expand(Parameters[n], Locals, Used);
                                //Console.WriteLine("    -> {0}", Parameters[n]);
                            }
                            var Map = MapFunctionParameters(MacroFunction.Parameters, Parameters);

                            //foreach (var Item in Map) Console.WriteLine("{0} -> {1}", Item.Key, Item.Value);

                            Output += Expand(MacroFunction.Replacement, Map, new HashSet <string>(new[] { CurrentIdentifier }));
                        }
                    }
                    else
                    {
                        Output += CurrentIdentifier;
                        Tokens.MoveNextSpace();
                    }
                }
                else
                {
                    Output += Tokens.Current.Raw;
                    Tokens.MoveNextSpace();
                }
            }
            return(Output);
        }