import java.io.*; import java.util.Enumeration; import antlr.collections.AST; class Main extends Common { /* print tree */ public static void printTree (AST branch) { while (branch != null) { print (branch.getText ()); print (" (" + branch.getType () + ")"); print (" (" + branch.getClass().getName() + ")"); println (""); indent ++; if (branch instanceof BlockNode) println ("mark = " + ((BlockNode) branch).mark); printTree (branch.getFirstChild ()); indent --; branch = branch.getNextSibling (); } } /* process */ private static EGLexer lexer; private static EGParser parser; private static void process (Tool tool) throws Exception { printInfo (tool.getClass().getName ()); // tool.info = info; tool.onInit (); EGTreeParser tree_parser = new EGTreeParser (); tree_parser.tool = tool; tree_parser.grammar (parser.getAST ()); tool.onFinish (); Tool.first_pass = false; } /* send options */ private static void sendOptions (DictTable table, boolean vocabulary) { if (table.size() != 0) { println ("options"); println ("{"); indent ++; if (vocabulary) println ("charVocabulary = '\\0'..'\\377';"); Enumeration seq = table.elements (); while (seq.hasMoreElements ()) { DictItem2 item = (DictItem2) seq.nextElement (); String txt = item.value; // if (! empty (txt) && txt.charAt (0) == '`') // txt = txt.substring (1, txt.length()-2); println (item.ident + " = " + txt + ";"); } indent --; println ("}"); println (""); } } /* namespaces */ private static void open_namespace () { if (info.automatic_namespace) { println ("OPEN_NAMESPACE"); println (""); } else { String name = info.product_namespace; if (! empty (name)) { println ("namespace " + name); println ("{"); println (""); } } } private static void close_namespace () { if (info.automatic_namespace) { println ("CLOSE_NAMESPACE"); println (""); } else { String name = info.product_namespace; if (! empty (name)) { println ("} // end of namespace " + name); println (""); } } } public static String namespace (String name) { if (empty (name)) return ""; else return name + "::"; } private static void print_info (String source, String target) { println (""); println ("/* EG: " + source + " -> " + target + " */"); println (""); } /* main */ public static void main (String[] args) { int err_code = 0; try { // arguments String inp_name = ""; String inp_dir = ""; String out_dir = ""; boolean i_opt = false; boolean o_opt = false; for (int i = 0; i < args.length; i++) { String txt = args [i]; if (i_opt) { if (! empty (inp_dir)) err ("Input directory name already defined"); inp_dir = txt; i_opt = false; } else if (o_opt) { if (! empty (out_dir)) err ("Output directory name already defined"); out_dir = txt; o_opt = false; } else if (txt.startsWith ("input_dir=")) { if (! empty (inp_dir)) err ("Input directory name already defined " + inp_dir); inp_dir = txt.substring (10); } else if (txt.startsWith ("output_dir=")) { if (! empty (out_dir)) err ("Output directory name already defined"); out_dir = txt.substring (11); } else if (txt.equals ("-i")) i_opt = true; else if (txt.equals ("-o")) o_opt = true; else { if (! empty (inp_name)) err ("Input file name already defined"); inp_name = txt; } } if (empty (inp_name)) err ("Missing input file name"); if (! empty (inp_dir) && ! inp_dir.endsWith ("/")) inp_dir = inp_dir + '/'; if (! empty (out_dir) && ! out_dir.endsWith ("/")) out_dir = out_dir + '/'; // lexer and parser lexer = new EGLexer (new DataInputStream (new FileInputStream (inp_dir + inp_name))); parser = new EGParser (lexer); input_parser = parser; // line number informations input_file_name = inp_dir + inp_name; lexer.setFilename (inp_dir + inp_name); parser.setFilename (inp_dir + inp_name); parser.setASTFactory (new NodeFactory ()); parser.grammar (); // test - print tree if (false) { // print tree AST ast = parser.getAST (); println ("tree:"); printTree (ast); println (""); } // dictionary of rules, structures, enumerations Common.info = new ParserInfo (); info.inp_dir = inp_dir; // test - simple tree parser if (false) { process (new Test ()); } // collect names of rules and structures process (new Scanner ()); final String prod = info.product_name; // output file name prefix if (empty (prod)) err ("Missing product_name option"); // common, public and private header if (empty (info.common_header)) err ("Missing common_header option"); if (empty (info.common_name)) err ("Missing common_name option"); info.enable_public_header = ! empty (info.public_header); info.enable_private_header = ! empty (info.private_header); info.enable_lexer_output = ! empty (info.lexer_name); info.enable_symbol_header = ! empty (info.symbol_header); if (empty (info.parser_name)) err ("Missing parser_name option"); if (info.antlr_mode) if (empty (info.lexer_name)) err ("Missing lexer_name option"); if (empty (info.lexer_class)) info.lexer_class = info.lexer_name; if (empty (info.parser_class)) info.parser_class = info.parser_name; if (empty (info.product_class)) info.product_class = info.product_name; info.basic_type = info.type_prefix + info.basic_type; /* info.expr_type = info.type_prefix + info.expr_type; info.binary_expr_type = info.type_prefix + info.binary_expr_type; info.unary_expr_type = info.type_prefix + info.unary_expr_type; */ info.writer_param = info.param_prefix + "writer"; info.writer_decl = info.product_class + " * " + info.writer_param; if (! empty (info.subst_type)) info.subst_type = info.type_prefix + info.subst_type; if (! empty (info.replace_type)) info.replace_type = info.type_prefix + info.replace_type; // open streams openStreams (out_dir); // fields, sequences, enumerations, tokens, literals, type compatibility Decl decl = new Decl (); process (decl); // add product_namespace if (! empty (info.product_namespace)) decl.grammarOption ("namespace", '"'+ info.product_namespace + "::" + '"'); // PRODUCT HEADER switchTo (productHeaderPack); print_info (inp_name, prod + ".hpp"); String sym = "__PROG_" + prod + "_HPP__"; println ("#ifndef " + sym); println ("#define " + sym); println (""); println ("#include "); println ("#include "); println ("using namespace std;"); println (""); println ("#include " + '"' + info.common_header + ".hpp" + '"'); println (""); print_extension ("product_include"); open_namespace (); print_extension ("product_header"); CodeOutput code_output = new CodeOutput (); code_output.sendHeader (); close_namespace (); println ("#endif /* " + sym + " */"); // COMMON HEADER switchTo (commonHeaderPack); print_info (inp_name, info.common_header + ".hpp"); sym = "__PROG_" + info.common_header + "_HPP__"; println ("#ifndef " + sym); println ("#define " + sym); println (""); println ("#include "); println ("#include "); if (info.automatic_namespace) println ("#include \"std.h\""); println ("using namespace std;"); println (""); print_extension ("common_include"); open_namespace (); code_output.sendCommonHeader (); close_namespace (); println ("#endif /* " + sym + " */"); // PUBLIC HEADER if (info.enable_public_header) { switchTo (publicHeaderPack); print_info (inp_name, info.public_header + ".hpp"); sym = "__PROG_" + info.public_header + "_HPP__"; println ("#ifndef " + sym); println ("#define " + sym); println (""); println ("#include " + '"' + info.common_header + ".hpp" + '"'); println (""); open_namespace (); code_output.sendPublicHeader (); close_namespace (); println ("#endif /* " + sym + " */"); } // PRIVATE HEADER if (info.enable_private_header) { switchTo (privateHeaderPack); print_info (inp_name, info.private_header + ".hpp"); sym = "__PROG_" + info.private_header + "_HPP__"; println ("#ifndef " + sym); println ("#define " + sym); println (""); if (info.enable_public_header) { println ("#include " + '"' + info.public_header + ".hpp" + '"'); println (""); } else { println ("#include " + '"' + info.common_header + ".hpp" + '"'); println (""); } open_namespace (); code_output.sendPrivateHeader (); close_namespace (); println ("#endif /* " + sym + " */"); } // LEXER GRAMMAR GrammarOutput grammar_output = new GrammarOutput (); if (info.enable_lexer_output && info.antlr_mode) { switchTo (lexerGrammarPack); print_info (inp_name, info.lexer_name + ".gpp"); println ("header"); println ("{"); indent ++; if (! empty (info.product_namespace)) println ("ANTLR_END_NAMESPACE"); if (info.switchable_literals) { println ("#include "); println ("#include "); println ("using namespace std;"); } print_extension ("lexer_include"); if (! empty (info.product_namespace)) println ("ANTLR_BEGIN_NAMESPACE(" + info.product_namespace+")"); print_extension ("lexer_header"); indent --; println ("}"); println (""); sendOptions (info.grammar_repository, false); // lexer println ("class " + info.lexer_name + " extends Lexer;"); // ANTLR does not support different file and class names println (""); sendOptions (info.lexer_repository, true); grammar_output.sendTokens (); println ("// lexer class extension"); println ("{"); println ("public:"); indent ++; if (info.switchable_literals) { println ("bool enable_literals;"); println (""); println ("virtual int testLiteralsTable (int ttype) const"); println ("{"); println (" if (enable_literals)"); println (" ttype = CharScanner::testLiteralsTable (ttype);"); println (" return ttype;"); println ("}"); println (""); println ("virtual int testLiteralsTable (const string & text, int ttype) const"); println ("{"); println (" if (enable_literals)"); println (" ttype = CharScanner::testLiteralsTable (text, ttype);"); println (" return ttype;"); println ("}"); println (""); println ("void LocalInit ()"); println ("{"); println (" enable_literals = true;"); println ("}"); } else { println ("void LocalInit () {}"); } print_extension ("lexer_class"); indent --; println ("}"); println (""); grammar_output.sendLiterals (); copy (inp_dir, info.lexer_input, ""); } // PARSER GRAMMAR switchTo (parserGrammarPack); print_info (inp_name, info.parser_name + ".gpp"); println ("header"); println ("{"); indent ++; if (! empty (info.product_namespace)) println ("ANTLR_END_NAMESPACE"); if (info.open_method) println ("#include " + '"' + info.lexer_name + ".hpp" + '"'); if (info.enable_public_header) println ("#include " + '"' + info.public_header + ".hpp" + '"'); else println ("#include " + '"' + prod + ".hpp" + '"'); if (info.enable_private_header) println ("#include " + '"' + info.private_header + ".hpp" + '"'); println (""); print_extension ("parser_include"); if (! empty (info.product_namespace)) println ("ANTLR_BEGIN_NAMESPACE(" + info.product_namespace+")"); print_extension ("parser_header"); indent --; println ("}"); println (""); sendOptions (info.grammar_repository, false); println ("class " + info.parser_name + " extends Parser;"); println (""); sendOptions (info.parser_repository, false); String pref = info.util_func_prefix; if (info.notes) { println ("{"); println ("public:"); indent ++; println (info.location_type + " " + pref + "getLocation ();"); println (info.note_type + " " + pref + "getStartNote ();"); println (info.note_type + " " + pref + "getStopNote ();"); println (""); } // println ("static " + info.parser_class + " * " + pref + "open_string (string input);"); // println ("static void " + pref + "close_string ();"); /* println ("static " + info.parser_class + " * " + pref + "open_string (string input, string file_name=\"\", int line=0)"); println ("{"); println (" std::istringstream stream (input);"); println (" return open_parser (stream, file_name, line);"); println ("}"); println (""); println ("void " + pref + "close_string ()"); println ("{"); println (" close_parser ();"); println ("}"); println (""); */ if (info.open_method) { println (info.lexer_class + " * lexer;"); println (""); println ("static " + info.parser_class + " * " + pref + "open_parser (std::istream & stream, string file_name, int line)"); println ("{"); println (" " + info.lexer_class + " * lexer = new " + info.lexer_class + " (stream);"); println (" lexer->setFilename (file_name);"); println (" if (line != 0) lexer->setLine (line);"); println (""); println (" " + info.parser_class + " * parser = new " + info.parser_class + " (*lexer);"); println (" parser->setFilename (file_name);"); println (" parser->lexer = lexer;"); println (""); println (" return parser;"); println ("}"); println (""); println ("void " + pref + "close_parser ()"); println ("{"); println (" assert (this != NULL);"); println (""); println (" delete this->lexer;"); println (" this->lexer = NULL;"); println (""); println (" delete this;"); println ("}"); println (""); } /* println (info.location_type + " " + pref + "getLocation ();"); println ("{"); println (" // recall line number"); println (" antlr::RefToken token = this->LT (1);"); println (" return token->getLine ();"); println ("}"); println (""); println (info.note_type + " " + pref + "getStartNote ();"); println ("{"); println (" // recall comments before lexical element"); println (" string s = \"\";"); println (""); println (" if (comments)"); println (" {"); println (" antlr::RefToken token = this->LT (1);"); println (""); println (" antlr::RefToken t = filter -> getHiddenBefore (token);"); println (" while (t != NULL)"); println (" {"); println (" s = t->getText () + s;"); println (" t = filter->getHiddenBefore (t);"); println (" }"); println (" }"); println (""); println (" return s;"); println ("}"); println (""); println (info.note_type + " " + pref + "getStopNote ();"); println ("{"); println (" // recall comments after lexical element"); println (" return \"\";"); println ("}"); println (""); */ print_extension ("parser_class"); indent --; println ("}"); println (""); // duplicate grammar rules process (grammar_output); // C++ COMMON CODE switchTo (commonCodePack); print_info (inp_name, info.common_name + ".cpp"); println ("#include " + '"' + info.common_header + ".hpp" + '"'); if (info.enable_private_header) println ("#include " + '"' + info.private_header + ".hpp" + '"'); else if (info.enable_public_header) println ("#include " + '"' + info.public_header + ".hpp" + '"'); println (""); open_namespace (); print_comment ("decl"); code_output.sendCode (); close_namespace (); // SYMBOL HEADER, LEXER and PARSER if (! info.antlr_mode) { ParserOutput parser_output = new ParserOutput (); parser_output.initSymbols (); // SYMBOL HEADER if (info.enable_symbol_header) { switchTo (symbolHeaderPack); print_info (inp_name, info.symbol_header + ".hpp"); sym = "__PROG_" + info.symbol_header + "_HPP__"; println ("#ifndef " + sym); println ("#define " + sym); println (""); open_namespace (); parser_output.declareSymbols (); close_namespace (); println ("#endif /* " + sym + " */"); } // LEXER HEADER if (info.enable_lexer_output) { switchTo (lexerHeaderPack); print_info (inp_name, info.lexer_name + ".hpp"); sym = "__PROG_" + info.lexer_name + "_HPP__"; println ("#ifndef " + sym); println ("#define " + sym); println (""); println ("#include " + '"' + info.common_header + ".hpp" + '"'); if (info.enable_symbol_header) println ("#include " + '"' + info.symbol_header + ".hpp" + '"'); println (""); print_extension ("lexer_include"); open_namespace (); print_extension ("lexer_header"); // parser_output.initSymbols (); parser_output.lexer_header_output (); close_namespace (); println ("#endif /* " + sym + " */"); } // PARSER HEADER switchTo (parserHeaderPack); print_info (inp_name, info.parser_name + ".hpp"); sym = "__PROG_" + info.parser_name + "_HPP__"; println ("#ifndef " + sym); println ("#define " + sym); println (""); if (! info.enable_lexer_output) { println ("#include " + '"' + info.common_header + ".hpp" + '"'); if (info.enable_symbol_header) println ("#include " + '"' + info.symbol_header + ".hpp" + '"'); } if (info.enable_lexer_output) println ("#include " + '"' + info.lexer_name + ".hpp" + '"'); println (""); print_extension ("parser_include"); open_namespace (); print_extension ("parser_header"); parser_output.header_output (); close_namespace (); println ("#endif /* " + sym + " */"); // LEXER CODE if (info.enable_lexer_output) { switchTo (lexerCodePack); print_info (inp_name, info.lexer_name + ".cpp"); println ("#include " + '"' + info.lexer_name + ".hpp" + '"'); open_namespace (); parser_output.lexer_code_output (); close_namespace (); } // PARSER CODE switchTo (parserCodePack); print_info (inp_name, info.parser_name + ".cpp"); println ("#include " + '"' + info.parser_name + ".hpp" + '"'); if (info.enable_private_header) println ("#include " + '"' + info.private_header + ".hpp" + '"'); else if (info.enable_public_header) println ("#include " + '"' + info.public_header + ".hpp" + '"'); println (""); open_namespace (); switchTo (parserImplPack); // store code parser_output.code_output (); switchTo (parserCodePack); // back to original stream copyFrom (parserDeclPack); // constant declaraion copyFrom (parserImplPack); // stored code if (! info.enable_lexer_output) parser_output.lexer_code_output (); close_namespace (); } // C++ PRODUCT CODE switchTo (productCodePack); print_info (inp_name, prod + ".cpp"); println ("#include " + '"' + prod + ".hpp" + '"'); if (info.enable_private_header) println ("#include " + '"' + info.private_header + ".hpp" + '"'); else if (info.enable_public_header) println ("#include " + '"' + info.public_header + ".hpp" + '"'); println (""); open_namespace (); print_comment ("list"); ListOutput list_output = new ListOutput (); list_output.binary_support (); process (list_output); if (info.tree_code) { TreeOutput tree_output = new TreeOutput (); tree_output.sendCode (); } close_namespace (); // write files closeStreams (); /* printInfo ("allocated notes " + info.note_decl_cnt); printInfo ("processed start notes " + info.start_note_dupl_cnt); printInfo ("processed stop notes " + info.stop_note_dupl_cnt); printInfo ("sended start notes " + info.start_note_list_cnt); printInfo ("sended stop notes " + info.stop_note_list_cnt); */ printInfo ("O.K."); } catch (Exception e) { err_code = 1; printErrInfo (e.toString ()); e.printStackTrace (System.err); // !? } System.exit (err_code); } }