public static bool TryCreateFromDeclaration(string name, string body, out MethodMacro method) { method = null; try { PreProcessorEngine engine = new PreProcessorEngine(new PreProcessorOptions()); using (var reader = new StringReader("#define " + name + body)) { engine.Process(new TextReaderBag(reader)); Macro created = null; if (engine.MacroMap.TryGetValue(name, out created) && created.IsMethod) { method = (MethodMacro)created; return(true); } } } catch { return(false); } return(false); }
/// <summary> /// Called when a define token is hit /// </summary> /// <remarks></remarks> private void ProcessPoundDefine(PreprocessorLine line) { // Get the non whitespace tokens List <Token> list = line.GetValidTokens(); ThrowIfFalse(list[0].TokenType == TokenType.PoundDefine); Macro macro = null; if (list.Count == 3 && list[1].TokenType == TokenType.Word) { string name = list[1].Value; macro = new Macro(name, list[2].Value); } else if (list.Count == 2 && list[1].TokenType == TokenType.Word) { string name = list[1].Value; macro = new Macro(name, string.Empty); } else if (list.Count == 1) { _scanner.AddWarning("Encountered an empty #define"); } else if (list.Count > 3 && list[1].TokenType == TokenType.Word && list[2].TokenType == TokenType.ParenOpen) { macro = ProcessPoundDefineMethod(line); } else { macro = ProcessPoundDefineComplexMacro(line); } if (macro != null) { Macro oldMacro = null; if (_macroMap.TryGetValue(macro.Name, out oldMacro) && oldMacro.IsPermanent) { TraceToStream("Kept: {0} -> {1} Attempted Value {2}", oldMacro.Name, oldMacro.Value, macro.Value); } else { _macroMap[macro.Name] = macro; if (macro.IsMethod) { MethodMacro method = (MethodMacro)macro; TraceToStream("Defined: {0} -> {1}", macro.Name, method.MethodSignature); } else { TraceToStream("Defined: {0} -> {1}", macro.Name, macro.Value); } } } }
/// <summary> /// Convert the macros in the result into a list of constants /// </summary> /// <returns></returns> /// <remarks></remarks> public List <NativeConstant> ConvertMacrosToConstants() { var list = new List <NativeConstant>(); foreach (Macro macro in MacroMap.Values) { if (macro.IsMethod) { MethodMacro method = (MethodMacro)macro; list.Add(new NativeConstant(macro.Name, method.MethodSignature, ConstantKind.MacroMethod)); } else { list.Add(new NativeConstant(macro.Name, macro.Value)); } } return(list); }
private List <Token> ReplaceMethodMacro(MethodMacro method, List <Token> args) { // First run the replacement List <Token> retList = method.Replace(args); // When creating the arguments for a macro, non-trivial arguments (1+2) come accross // as text macros. For those items we need to reparse them here and put them back into the stream. // Have to do this after the above loop so that ## and # are processed correctly int i = 0; while (i < retList.Count) { Token cur = retList[i]; if (cur.TokenType == TokenType.Text && args.IndexOf(cur) >= 0) { retList.RemoveAt(i); retList.InsertRange(i, Scanner.TokenizeText(cur.Value, _scanner.Options)); } i += 1; } return(retList); }
private void ReplaceDefinedTokens(PreprocessorLine line) { ThrowIfNull(line); int i = 0; List <Token> list = line.TokenList; while ((i < list.Count)) { Token token = list[i]; if (token.TokenType != TokenType.Word) { i += 1; continue; } Macro macro = null; if (_macroMap.TryGetValue(token.Value, out macro)) { // Remove the original token list.RemoveAt(i); List <Token> replaceList = null; if (macro.IsMethod) { MethodMacro method = (MethodMacro)macro; List <Token> args = ParseAndRemoveMacroMethodArguments(list, i); if (args == null) { // Parse did not succeed, move to the next token i += 1; } else { // Insert the tokens replaceList = ReplaceMethodMacro(method, args); } } else { // Use the scanner to create the replacement tokens replaceList = Scanner.TokenizeText(macro.Value, CreateScannerOptions()); } if (replaceList != null) { CollapseDoublePounds(replaceList); list.InsertRange(i, replaceList); } } else { i += 1; } } // Do one more pass to check and see if we need a recursive replace bool needAnotherPass = false; foreach (Token cur in line.TokenList) { if (cur.TokenType == TokenType.Word && _macroMap.ContainsKey(cur.Value)) { needAnotherPass = true; break; } } if (needAnotherPass) { ReplaceDefinedTokens(line); } }