330 lines
8.4 KiB
C#
330 lines
8.4 KiB
C#
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);
|
|
}
|
|
}
|