using System; using System.Collections; public class excel2gram { public static void Main(string[] argv) { string command = argv[0]; ArrayList filenames = new ArrayList(); for (int i = 1; i < argv.Length; i++) { string excelname = argv[i]; if (!System.IO.Path.IsPathRooted(excelname)) { string cwd = System.Environment.CurrentDirectory; excelname = System.IO.Path.Combine(cwd, excelname); } filenames.Add(excelname); } Excel.Application app = new Excel.Application(); doit(app, filenames, command); app.Quit(); } public static void doit(Excel.Application app, ArrayList excelnames, string command) { ArrayList prods = new ArrayList(); ArrayList words = new ArrayList(); Hashtable nts = new Hashtable(); foreach (string excelname in excelnames) { Excel.Workbook wb = app.Workbooks.Open( excelname, // Filename 0, // UpdateLinks true, // ReadOnly 5, // Format "", // Password "", // WriteResPassword true, // IgnoreReadOnlyRecommended Excel.XlPlatform.xlWindows, // Origin "\t", // Delimiter false, // Editable false, // Notify 0, // Converter true, // AddToMru true, // Local true // CorruptLoad ); prods = process(wb, prods); nts = processTypes(wb, nts); words = processKeyword(wb, words); } switch (command) { default: System.Console.WriteLine("usage: a.out (grammar|keywords) excelfile"); break; case "gram": prods = addOpts(prods, nts); foreach (production p in prods) { System.Console.WriteLine(p.prod); } break; case "rewrite": prods = addOpts(prods, nts); emitParse2AST(nts, prods); break; case "keywords": foreach (string s in words) { System.Console.WriteLine(s); } break; } } class production { public string nt; public IList rule; public string ty; public string action; public production(string nt, IList rule, string ty, string action) { this.nt = nt; this.rule = rule; this.ty = ty; this.action = action; } public override string ToString() { return prod + " = " + ty + " " + action; } public string prod { get { string s = nt + " :"; foreach (string e in rule) { s += " " + e; } return s; } } } static ArrayList addOpts(ArrayList prods, Hashtable nts) { ArrayList L = new ArrayList(); foreach (production p in prods) { L.Add(p); } foreach (production p in prods) { foreach (string s in p.rule) { if (s.EndsWith("opt") && !nts.Contains(s)) { string basename = s.Substring(0, s.LastIndexOf("opt")); production q; string ty; if (nts.Contains(basename)) { ty = ((typeInfo)nts[basename]).ty; string action = ((typeInfo)nts[basename]).action; q = new production(s, new string[] {}, ty, action); L.Add(q); q = new production(s, new string[] { basename }, ty, "a1"); L.Add(q); nts[s] = new typeInfo(ty, ""); } else { ty = "InputElement"; q = new production(s, new string[] {}, ty, "null"); L.Add(q); q = new production(s, new string[] { basename }, ty, "a1"); L.Add(q); } nts[s] = new typeInfo(ty, ""); } } } return L; } static ArrayList process(Excel.Workbook wb, ArrayList prods) { foreach (Excel.Worksheet ws in wb.Sheets) { if (ws.Name.EndsWith("grammar")) { Excel.Range nonterms = ws.get_Range("grammar_Nonterminal",missing); Excel.Range rules = ws.get_Range("grammar_Rule",missing); Excel.Range types = ws.get_Range("grammar_type",missing); Excel.Range actions = ws.get_Range("grammar_Action",missing); for (int i = 1; i <= ws.UsedRange.Rows.Count; i++) { string nt = item(nonterms, i); string rule = item(rules, i); string ty = item(types, i); string action = item(actions, i); if (action == "") { if (rule == "") { action = "null"; } else { action = "a1"; } } if (nt != "") { string[] rx = rule.Trim(' ').Split(' '); production p = new production(nt, rx, ty, action); prods.Add(p); } } } } return prods; } class typeInfo { public string ty; public string action; public typeInfo(string ty, string action) { this.ty = ty; this.action = action; } } static Hashtable processTypes(Excel.Workbook wb, Hashtable T) { foreach (Excel.Worksheet ws in wb.Sheets) { if (ws.Name.EndsWith("types")) { Excel.Range nonterms = ws.get_Range("types_Nonterminal",missing); Excel.Range types = ws.get_Range("types_type",missing); Excel.Range actions = ws.get_Range("types_Default_Action",missing); for (int i = 1; i <= ws.UsedRange.Rows.Count; i++) { string nt = item(nonterms, i); string ty = item(types, i); string action = item(actions, i); if (nt != "") { T[nt] = new typeInfo(ty, action); } } } } return T; } static object missing = System.Reflection.Missing.Value; static string item(Excel.Range r, int row) { Excel.Range c; try { c = r.get_Range("A"+row, missing); } catch (System.Exception e) { System.Console.WriteLine("error: {0} --- {1}", row, e); throw e; } if (c.Value2 == null) { return ""; } return c.Value2.ToString(); } static string item(Excel.Worksheet ws, string column, int row) { Excel.Range c; try { c = ws.get_Range(column,missing).get_Range("A"+row, missing); } catch (System.Exception e) { System.Console.WriteLine("error: {0}.{1}[{2}] --- {3}", ws.Name, column, row, e); throw e; } if (c.Value2 == null) { return ""; } return c.Value2.ToString(); } static ArrayList processKeyword(Excel.Workbook wb, ArrayList words) { foreach (Excel.Worksheet ws in wb.Sheets) { if (ws.Name.EndsWith("keyword-tokens")) { Excel.Range keywords = ws.get_Range("tokens_Terminal",missing); for (int i = 1; i <= ws.UsedRange.Rows.Count; i++) { string token = item(keywords, i); if (token != "") { words.Add(token); } } } } return words; } private static Hashtable memo = new Hashtable(); static string mangle(string name) { if (memo.Contains(name)) { return (string)memo[name]; } string s = name .Replace('-', '_') .Replace(';', 'A'); memo[name] = s; return s; } static void emitParse2AST(Hashtable nts, IList prods) { string prefix = "rewrite_"; Console.WriteLine(@" ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // // Generated Files --- DO NOT EDIT! // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// using System.Collections; public class parse2AST { "); foreach (string nt in nts.Keys) { string ty = ((typeInfo)nts[nt]).ty; Console.WriteLine(@" public static {0} {1}{2}(nonterminalState node) {{ if (node.queue != null) {{ return ({0})disambiguate.resolve(node, ""{3}""); }} {0} retval; switch (node.rule) {{ default: throw new System.Exception(""{3}""); ", ty, prefix, mangle(nt), nt); foreach (production p in prods) { if (p.nt == nt) { Console.WriteLine("\tcase \"{0}\": {{", p.prod); if (p.rule.Count > 0) { Console.WriteLine("\t\tstate tmp = node.rightmost;"); } for (int i = p.rule.Count-1; i >= 0; i--) { string sym = (string)p.rule[i]; if (nts.Contains(sym)) { string symty = ((typeInfo)nts[sym]).ty; Console.WriteLine("\t\t{0} a{1} = {2}{3}((nonterminalState)tmp);;", symty, i+1, prefix, mangle(sym)); } else { Console.WriteLine("\t\tInputElement a{0} = {1}terminal(tmp);", i+1, prefix); } if (i > 0) { Console.WriteLine("\t\ttmp = tmp.below;"); } } Console.WriteLine(@" retval = {0}; break; }} ", p.action); } } Console.WriteLine(@" } IHasCoordinate ihc = ((object)retval) as IHasCoordinate; if (ihc != null) { ihc.begin = node.begin; ihc.end = node.end; } return retval; } "); } Console.WriteLine(@" public static InputElement {0}terminal(state node) {{ return ((terminalState)node).terminal; }} }} ", prefix); } }