internal static List <token> Process(string input, Dictionary <string, List <token> > defines, Program.IncludeFileLocator file_locator) { /* The C standard defines eight phases of translation * * The first four are handled by the preprocessor: * - Trigraph replacement * - Line splicing (joining lines separated by the \ character) * - Tokenization + replacing comments with whitespace * - Marco expansion and directive handling */ string post_trigraph = Replace(input, new string[][] { new string[] { "??=", "#" }, new string[] { "??/", "\\" }, new string[] { "??'", "^" }, new string[] { "??(", "[" }, new string[] { "??)", "]" }, new string[] { "??!", "|" }, new string[] { "??<", "{" }, new string[] { "??>", "}" }, new string[] { "??-", "~" }, }, false); string spliced_lines = SpliceLines(post_trigraph); List <token> tokens = Tokenize(spliced_lines); int i = 0; List <token> expanded_tokens = ConvertToTree(tokens, ref i); List <token> new_tokens = HandleDirectives(expanded_tokens, defines, file_locator); return(new_tokens); }
private static void HandleInclude(List <token> ret, List <token> tokens, int i, Dictionary <string, List <token> > defines, Program.IncludeFileLocator file_locator) { token file_name = tokens[i].parameters[0]; if (file_name.value == "<") { file_name = new token { type = token.token_type.identifier, value = tokens[i].value.Split(' ', '\t')[1].Trim() } } ; if ((file_name.type != token.token_type.identifier) && (file_name.type != token.token_type.string_literal)) { throw new Exception(); } bool search_cur_dir = false; if (file_name.value.StartsWith("\"")) { search_cur_dir = true; } string fname = file_name.value.Trim('\"', '<', '>'); string file_text = file_locator.ReadFile(fname, search_cur_dir); ret.AddRange(Process(file_text, defines, file_locator)); }
private static void HandlePragma(List <token> ret, List <token> tokens, int i, Dictionary <string, List <token> > defines, Program.IncludeFileLocator file_locator) { throw new NotImplementedException(); }
private static void HandleDefine(List <token> ret, List <token> tokens, int i, Dictionary <string, List <token> > defines, Program.IncludeFileLocator file_locator) { token macro_name = tokens[i].parameters[0]; List <token> defined_as = new List <token>(); for (int j = 1; j < tokens[i].parameters.Count; j++) { defined_as.Add(tokens[i].parameters[j]); } List <token> new_defined_as = HandleDirectives(defined_as, defines, file_locator); defines[macro_name.value] = new_defined_as; }
private static void HandleIfDef(List <token> ret, List <token> tokens, int i, Dictionary <string, List <token> > defines, Program.IncludeFileLocator file_locator) { if (tokens[i].parameters.Count != 1) { throw new Exception(); } if (defines.ContainsKey(tokens[i].parameters[0].value)) { ret.AddRange(HandleDirectives(tokens[i].if_tokens, defines, file_locator)); } else { ret.AddRange(HandleDirectives(tokens[i].else_tokens, defines, file_locator)); } }
private static List <token> HandleDirectives(List <token> tokens, Dictionary <string, List <token> > defines, Program.IncludeFileLocator file_locator) { List <token> ret = new List <token>(); if (tokens == null) { return(ret); } for (int i = 0; i < tokens.Count; i++) { token tok = tokens[i]; if (tok.type == token.token_type.preprocessor_directive) { string directive = tok.directive; if (directive == "#include") { HandleInclude(ret, tokens, i, defines, file_locator); } else if (directive == "#if") { HandleIf(ret, tokens, i, defines, file_locator); } else if (directive == "#ifdef") { HandleIfDef(ret, tokens, i, defines, file_locator); } else if (directive == "#define") { HandleDefine(ret, tokens, i, defines, file_locator); } else if (directive == "#error") { HandleError(ret, tokens, i, defines, file_locator); } else if (directive == "#warning") { HandleWarning(ret, tokens, i, defines, file_locator); } else if (directive == "#pragma") { HandlePragma(ret, tokens, i, defines, file_locator); } else if (directive == "#ifndef") { HandleIfndef(ret, tokens, i, defines, file_locator); } else { throw new Exception("Unsupported preprocessor directive: " + tok.value); } } else { if ((tok.type == token.token_type.identifier) && defines.ContainsKey(tok.value)) { ret.AddRange(defines[tok.value]); } else { ret.Add(tok); } } } return(ret); }