private static List <Preprocessor.token> MatchArrayPostscript(TokenProvider tp) { List <Preprocessor.token> ret = new List <Preprocessor.token>(); Preprocessor.token t = tp.Current; if (t.value == "[") { ret.Add(t); t = tp.MoveNext(); if (t.type == Preprocessor.token.token_type.number) { ret.Add(t); t = tp.MoveNext(); } if (t.value != "]") { throw new Exception(); } ret.Add(t); t = tp.MoveNext(); } return(ret); }
internal static ParsedEntry ParseFile(TokenProvider tp) { ParsedEntry ret = new ParsedEntry { Type = ParsedEntry.type.file, Tokens = tp.tokens }; Preprocessor.token t = tp.Current; while (t.type != Preprocessor.token.token_type.beyond_eof) { if (t.type == Preprocessor.token.token_type.comment) { t = tp.MoveNext(); continue; } List <Preprocessor.token> cur_tokens = new List <Preprocessor.token>(); ParsedEntry entry = new ParsedEntry { Tokens = cur_tokens }; if (t.value == "typedef") { cur_tokens.Add(t); t = tp.MoveNext(); List <Preprocessor.token> typedef_to = MatchType(tp); cur_tokens.AddRange(typedef_to); t = tp.Current; cur_tokens.Add(t); string typedef_from = t.value; t = tp.MoveNext(); if (t.value != ";") { throw new Exception(); } typedefs.Add(typedef_from, typedef_to); t = tp.MoveNext(); entry.Type = ParsedEntry.type.typedef; } else { // Parse type List <Preprocessor.token> mtype = MatchType(tp); if (mtype.Count == 0) { throw new Exception("Invalid type: " + tp.Current.value); } cur_tokens.AddRange(mtype); // Read identifier t = tp.Current; if (t.type == Preprocessor.token.token_type.identifier) { cur_tokens.Add(t); t = tp.MoveNext(); } // See if we identify a function if (t.value == "(") { // Function header t = tp.MoveNext(); List <ParsedEntry> args = new List <ParsedEntry>(); while (t.value != ")") { List <Preprocessor.token> type = MatchType(tp); cur_tokens.AddRange(type); t = tp.Current; if ((t.value != ")") && (t.value != ",")) { type.Add(t); cur_tokens.Add(t); t = tp.MoveNext(); } if (t.value == ")") { break; } if (t.value != ",") { throw new Exception(); } args.Add(new ParsedEntry { Type = ParsedEntry.type.variable_definition, Tokens = type }); cur_tokens.Add(t); t = tp.MoveNext(); } entry.Children.AddRange(args); cur_tokens.Add(t); t = tp.MoveNext(); if (t.value == ";") { cur_tokens.Add(t); t = tp.MoveNext(); entry.Type = ParsedEntry.type.function_declaration; } else if (t.value == "{") { entry.Type = ParsedEntry.type.function_definition; ParseStatementBlock(tp, entry); } } else if (t.value == ";") { entry.Type = ParsedEntry.type.variable_definition; cur_tokens.Add(t); t = tp.MoveNext(); } else if (t.value == "=") { entry.Type = ParsedEntry.type.variable_definition; cur_tokens.Add(t); t = tp.MoveNext(); ParseExpression(tp, entry); } else { throw new Exception(); } } ret.Children.Add(entry); } return(ret); }
static List <Preprocessor.token> MatchType(TokenProvider tp) { List <Preprocessor.token> ret = new List <Preprocessor.token>(); Preprocessor.token t = tp.Current; while (true) { if (t.type == Preprocessor.token.token_type.comment) { t = tp.MoveNext(); } else if ((t.value == "extern") || (t.value == "static") || (t.value == "const") || (t.value == "unsigned") || (t.value == "signed")) { ret.Add(t); t = tp.MoveNext(); } else if ((t.value == "int") || (t.value == "long") || (t.value == "char") || (t.value == "short") || (t.value == "float") || (t.value == "double") || (t.value == "void")) { ret.Add(t); t = tp.MoveNext(); if (t.value == "*") { ret.Add(t); t = tp.MoveNext(); } if ((t.value != "long") && (t.value != "short") && (t.value != "int")) { return(ret); } } else if (typedefs.ContainsKey(t.value)) { ret.AddRange(typedefs[t.value]); t = tp.MoveNext(); return(ret); } else if ((t.value == "struct") || (t.value == "union")) { ret.Add(t); t = tp.MoveNext(); string struct_name = null; if (t.value != "{") { struct_name = t.value; ret.Add(t); t = tp.MoveNext(); } if (t.value == "{") { ret.Add(t); t = tp.MoveNext(); // Read the struct definition List <Preprocessor.token> struct_def = new List <Preprocessor.token>(); while (true) { List <Preprocessor.token> type = MatchType(tp); if (type.Count == 0) { throw new Exception("Invalid type: " + tp.Current.value); } struct_def.AddRange(type); ret.AddRange(type); t = tp.Current; if (t.type == Preprocessor.token.token_type.identifier) { struct_def.Add(t); ret.Add(t); t = tp.MoveNext(); } List <Preprocessor.token> array = MatchArrayPostscript(tp); struct_def.AddRange(array); ret.AddRange(array); t = tp.Current; if (t.value != ";") { throw new Exception(); } struct_def.Add(t); ret.Add(t); t = tp.MoveNext(); if (t.value == "}") { ret.Add(t); break; } } t = tp.MoveNext(); if (struct_name != null) { struct_defs.Add(struct_name, struct_def); } } else if (struct_name == null) { throw new Exception("Invalid struct definition"); } else if (!struct_defs.ContainsKey(struct_name)) { throw new Exception("struct " + struct_name + " is not defined"); } return(ret); } else { throw new Exception("Invalid type: " + t.value); } } }