Backend main functions are now factored out.
[external/ragel.git] / rlgen-ruby / main.cpp
1 /*
2  *  Copyright 2007 Victor Hugo Borja <vic@rubyforge.org>
3  *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
4  */
5
6 /*  This file is part of Ragel.
7  *
8  *  Ragel is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  * 
13  *  Ragel is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  * 
18  *  You should have received a copy of the GNU General Public License
19  *  along with Ragel; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
21  */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <iostream>
27 #include <fstream>
28 #include <unistd.h>
29
30 #include "xmlparse.h"
31 #include "pcheck.h"
32 #include "vector.h"
33 #include "version.h"
34 #include "common.h"
35 #include "rlgen-ruby.h"
36 #include "ruby-tabcodegen.h"
37 #include "ruby-ftabcodegen.h"
38 #include "ruby-flatcodegen.h"
39 #include "ruby-fflatcodegen.h"
40 #include "rbx-gotocodegen.h"
41
42 using std::istream;
43 using std::ifstream;
44 using std::ostream;
45 using std::ios;
46 using std::cin;
47 using std::cout;
48 using std::cerr;
49 using std::endl;
50
51 /* Target ruby impl */
52 extern RubyImplEnum rubyImpl;
53
54 /* Target language and output style. */
55 extern CodeStyleEnum codeStyle;
56
57 /* Io globals. */
58 extern istream *inStream;
59 extern ostream *outStream;
60 extern output_filter *outFilter;
61 extern const char *outputFileName;
62
63 /* Graphviz dot file generation. */
64 extern bool graphvizDone;
65
66 extern int numSplitPartitions;
67
68 /*
69  * Callbacks invoked by the XML data parser.
70  */
71
72 /* Invoked by the parser when the root element is opened. */
73 ostream *rubyOpenOutput( char *inputFile )
74 {
75         if ( hostLang->lang != HostLang::Ruby ) {
76                 error() << "this code generator is for Ruby only" << endl;
77                 exit(1);
78         }
79
80         /* If the output format is code and no output file name is given, then
81          * make a default. */
82         if ( outputFileName == 0 ) {
83                 char *ext = findFileExtension( inputFile );
84                 if ( ext != 0 && strcmp( ext, ".rh" ) == 0 )
85                         outputFileName = fileNameFromStem( inputFile, ".h" );
86                 else
87                         outputFileName = fileNameFromStem( inputFile, ".rb" );
88         }
89
90         /* Make sure we are not writing to the same file as the input file. */
91         if ( outputFileName != 0 && strcmp( inputFile, outputFileName  ) == 0 ) {
92                 error() << "output file \"" << outputFileName  << 
93                                 "\" is the same as the input file" << endl;
94         }
95
96         if ( outputFileName != 0 ) {
97                 /* Create the filter on the output and open it. */
98                 outFilter = new output_filter( outputFileName );
99                 outFilter->open( outputFileName, ios::out|ios::trunc );
100                 if ( !outFilter->is_open() ) {
101                         error() << "error opening " << outputFileName << " for writing" << endl;
102                         exit(1);
103                 }
104
105                 /* Open the output stream, attaching it to the filter. */
106                 outStream = new ostream( outFilter );
107         }
108         else {
109                 /* Writing out ot std out. */
110                 outStream = &cout;
111         }
112         return outStream;
113 }
114
115 /* Invoked by the parser when a ragel definition is opened. */
116 CodeGenData *rubyMakeCodeGen( char *sourceFileName, char *fsmName, 
117                 ostream &out, bool wantComplete )
118 {
119         CodeGenData *codeGen = 0;
120         switch ( codeStyle ) {
121                 case GenTables: 
122                         codeGen = new RubyTabCodeGen(out);
123                         break;
124                 case GenFTables:
125                         codeGen = new RubyFTabCodeGen(out);
126                         break;
127                 case GenFlat:
128                         codeGen = new RubyFlatCodeGen(out);
129                         break;
130                 case GenFFlat:
131                         codeGen = new RubyFFlatCodeGen(out);
132                         break;
133                 case GenGoto:
134                         if ( rubyImpl == Rubinius ) {
135                                 codeGen = new RbxGotoCodeGen(out);
136                         } else {
137                                 cout << "Goto style is still _very_ experimental " 
138                                         "and only supported using Rubinius.\n"
139                                         "You may want to enable the --rbx flag "
140                                         " to give it a try.\n";
141                                 exit(1);
142                         }
143                         break;
144                 default:
145                         cout << "Invalid code style\n";
146                         exit(1);
147                         break;
148         }
149         codeGen->sourceFileName = sourceFileName;
150         codeGen->fsmName = fsmName;
151         codeGen->wantComplete = wantComplete;
152
153         return codeGen;
154 }
155
156 /*
157  * Local Variables:
158  * mode: c++
159  * indent-tabs-mode: 1
160  * c-file-style: "bsd"
161  * End:
162  */