public int EvaluateExpression(string Line) { var TokenReader = new CTokenReader(Line, TokenizeSpaces: false); TokenReader.MoveNextNoSpace(); return Context.EvaluateExpression(TokenReader); }
/// <summary> /// TODO: Have to refactor ParseIdentifier + Expact. They have repeated code!!! /// </summary> private void ParseIdentifier(CTokenReader Tokens) { Tokens.ExpectCurrentType(CTokenType.Identifier); var Identifier = Tokens.Current.Raw; Tokens.MoveNextSpace(); if (Context.Macros.ContainsKey(Identifier)) { var Macro = Context.Macros[Identifier]; var MacroFunction = Context.Macros[Identifier] as MacroFunction; if (MacroFunction != null) { if (Tokens.Current.Type == CTokenType.Space) { Tokens.MoveNextNoSpace(); } if (Tokens.Current.Raw != "(") { throw (new Exception(String.Format("Trying to use a function-like macro without calling it? MACRO: {0}, Token: {1}", Identifier, Tokens.Current))); } } if (MacroFunction != null) { var Parameters = ParseParameterList(Tokens, JustIdentifiers: false); for (int n = 0; n < Parameters.Length; n++) { //Console.WriteLine(" {0}", Parameters[n]); Parameters[n] = Expand(Parameters[n], null, null); //Console.WriteLine(" -> {0}", Parameters[n]); } var Map = MapFunctionParameters(MacroFunction.Parameters, Parameters); Identifier = Expand(MacroFunction.Replacement, Map, new HashSet<string>(new[] { Identifier })); } else { var MacroConstant = Macro as MacroConstant; Identifier = Expand(MacroConstant.Replacement, null, new HashSet<string>(new[] { Identifier })); //Console.WriteLine("a: {0}", MacroConstant.Replacement); } } else { //Identifier = Identifier; } Context.TextWriter.Write(ReplaceSimpleVariable(Identifier)); }
/// <summary> /// /// </summary> /// <returns></returns> private string[] ParseParameterList(CTokenReader Tokens, bool JustIdentifiers = false) { //Console.WriteLine("++++++++"); var Params = new List<string>(); Tokens.ExpectCurrentAndMoveNextSpace("("); while (Tokens.HasMore && Tokens.Current.Raw != ")") { string Param = ""; if (JustIdentifiers) { Param = Tokens.Current.Raw; Tokens.MoveNextNoSpace(); if (Tokens.Current.Raw == ",") { Tokens.ExpectCurrentAndMoveNextNoSpace(","); } } else { int OpenCount = 0; while (Tokens.HasMore) { if (Tokens.Current.Raw == ")") { if (OpenCount <= 0) { break; } else { OpenCount--; } } Param += Tokens.Current.Raw; if (Tokens.Current.Raw == "(") OpenCount++; Tokens.MoveNextSpace(); if (Tokens.Current.Raw == "," && OpenCount == 0) { Tokens.ExpectCurrentAndMoveNextNoSpace(","); break; } } } //Console.WriteLine("aa: {0} : {1}", Param, Tokens.Current); Params.Add(Param); } //Console.WriteLine("--------"); Tokens.ExpectCurrentAndMoveNextSpace(")"); return Params.ToArray(); }
/// <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; }
/// <summary> /// /// </summary> /// <param name="ParseLeftExpression"></param> /// <param name="ParseRightExpression"></param> /// <param name="Operators"></param> /// <param name="Context"></param> /// <returns></returns> private int _EvaluateExpressionStep(Func<CTokenReader, int> ParseLeftExpression, Func<CTokenReader, int> ParseRightExpression, HashSet<string> Operators, CTokenReader Tokens) { int Left; int Right; Left = ParseLeftExpression(Tokens); while (true) { var Operator = Tokens.Current.Raw; if (!Operators.Contains(Operator)) { //Console.WriteLine("Not '{0}' in '{1}'", Operator, String.Join(",", Operators)); break; } Tokens.MoveNextNoSpace(); Right = ParseRightExpression(Tokens); Left = BinaryOperation(Left, Operator, Right); } return Left; }
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); }
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))); } } }
/// <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; }