some refactoring
[external/ragel.git] / ragel / parsedata.h
1 /*
2  *  Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
3  */
4
5 /*  This file is part of Ragel.
6  *
7  *  Ragel is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  * 
12  *  Ragel is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  * 
17  *  You should have received a copy of the GNU General Public License
18  *  along with Ragel; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20  */
21
22 #ifndef _PARSEDATA_H
23 #define _PARSEDATA_H
24
25 #include <iostream>
26 #include <limits.h>
27 #include <sstream>
28 #include "avlmap.h"
29 #include "bstmap.h"
30 #include "vector.h"
31 #include "dlist.h"
32 #include "fsmgraph.h"
33 #include "compare.h"
34 #include "vector.h"
35 #include "common.h"
36 #include "parsetree.h"
37
38 /* Forwards. */
39 using std::ostream;
40
41 struct VarDef;
42 struct Join;
43 struct Expression;
44 struct Term;
45 struct FactorWithAug;
46 struct FactorWithLabel;
47 struct FactorWithRep;
48 struct FactorWithNeg;
49 struct Factor;
50 struct Literal;
51 struct Range;
52 struct RegExpr;
53 struct ReItem;
54 struct ReOrBlock;
55 struct ReOrItem;
56 struct LongestMatch;
57 typedef DList<LongestMatch> LmList;
58
59
60 /* Graph dictionary. */
61 struct GraphDictEl 
62 :
63         public AvlTreeEl<GraphDictEl>,
64         public DListEl<GraphDictEl>
65 {
66         GraphDictEl( const char *k ) 
67                 : key(k), value(0), isInstance(false) { }
68         GraphDictEl( const char *k, VarDef *value ) 
69                 : key(k), value(value), isInstance(false) { }
70
71         const char *getKey() { return key; }
72
73         const char *key;
74         VarDef *value;
75         bool isInstance;
76
77         /* Location info of graph definition. Points to variable name of assignment. */
78         InputLoc loc;
79 };
80
81 typedef AvlTree<GraphDictEl, const char*, CmpStr> GraphDict;
82 typedef DList<GraphDictEl> GraphList;
83
84 /* Priority name dictionary. */
85 typedef AvlMapEl<char*, int> PriorDictEl;
86 typedef AvlMap<char*, int, CmpStr> PriorDict;
87
88 /* Local error name dictionary. */
89 typedef AvlMapEl<const char*, int> LocalErrDictEl;
90 typedef AvlMap<const char*, int, CmpStr> LocalErrDict;
91
92 /* Tree of instantiated names. */
93 typedef BstMapEl<const char*, NameInst*> NameMapEl;
94 typedef BstMap<const char*, NameInst*, CmpStr> NameMap;
95 typedef Vector<NameInst*> NameVect;
96 typedef BstSet<NameInst*> NameSet;
97
98 /* Node in the tree of instantiated names. */
99 struct NameInst
100 {
101         NameInst( const InputLoc &loc, NameInst *parent, const char *name, int id, bool isLabel ) : 
102                 loc(loc), parent(parent), name(name), id(id), isLabel(isLabel),
103                 isLongestMatch(false), numRefs(0), numUses(0), start(0), final(0) {}
104
105         InputLoc loc;
106
107         /* Keep parent pointers in the name tree to retrieve 
108          * fully qulified names. */
109         NameInst *parent;
110
111         const char *name;
112         int id;
113         bool isLabel;
114         bool isLongestMatch;
115
116         int numRefs;
117         int numUses;
118
119         /* Names underneath us, excludes anonymous names. */
120         NameMap children;
121
122         /* All names underneath us in order of appearance. */
123         NameVect childVect;
124
125         /* Join scopes need an implicit "final" target. */
126         NameInst *start, *final;
127
128         /* During a fsm generation walk, lists the names that are referenced by
129          * epsilon operations in the current scope. After the link is made by the
130          * epsilon reference and the join operation is complete, the label can
131          * have its refcount decremented. Once there are no more references the
132          * entry point can be removed from the fsm returned. */
133         NameVect referencedNames;
134
135         /* Pointers for the name search queue. */
136         NameInst *prev, *next;
137
138         /* Check if this name inst or any name inst below is referenced. */
139         bool anyRefsRec();
140 };
141
142 typedef DList<NameInst> NameInstList;
143
144 /* Stack frame used in walking the name tree. */
145 struct NameFrame 
146 {
147         NameInst *prevNameInst;
148         int prevNameChild;
149         NameInst *prevLocalScope;
150 };
151
152 /* Class to collect information about the machine during the 
153  * parse of input. */
154 struct ParseData
155 {
156         /* Create a new parse data object. This is done at the beginning of every
157          * fsm specification. */
158         ParseData( const char *fileName, char *sectionName, const InputLoc &sectionLoc );
159         ~ParseData();
160
161         /*
162          * Setting up the graph dict.
163          */
164
165         /* Initialize a graph dict with the basic fsms. */
166         void initGraphDict();
167         void createBuiltin( const char *name, BuiltinMachine builtin );
168
169         /* Make a name id in the current name instantiation scope if it is not
170          * already there. */
171         NameInst *addNameInst( const InputLoc &loc, const char *data, bool isLabel );
172         void makeRootNames();
173         void makeNameTree( GraphDictEl *gdNode );
174         void makeExportsNameTree();
175         void fillNameIndex( NameInst *from );
176         void printNameTree();
177
178         /* Increments the usage count on entry names. Names that are no longer
179          * needed will have their entry points unset. */
180         void unsetObsoleteEntries( FsmAp *graph );
181
182         /* Resove name references in action code and epsilon transitions. */
183         NameSet resolvePart( NameInst *refFrom, const char *data, bool recLabelsOnly );
184         void resolveFrom( NameSet &result, NameInst *refFrom, 
185                         const NameRef &nameRef, int namePos );
186         NameInst *resolveStateRef( const NameRef &nameRef, InputLoc &loc, Action *action );
187         void resolveNameRefs( InlineList *inlineList, Action *action );
188         void resolveActionNameRefs();
189
190         /* Set the alphabet type. If type types are not valid returns false. */
191         bool setAlphType( const InputLoc &loc, char *s1, char *s2 );
192         bool setAlphType( const InputLoc &loc, char *s1 );
193
194         /* Override one of the variables ragel uses. */
195         bool setVariable( char *var, InlineList *inlineList );
196
197         /* Unique actions. */
198         void removeDups( ActionTable &actionTable );
199         void removeActionDups( FsmAp *graph );
200
201         /* Dumping the name instantiation tree. */
202         void printNameInst( NameInst *nameInst, int level );
203
204         /* Make the graph from a graph dict node. Does minimization. */
205         FsmAp *makeInstance( GraphDictEl *gdNode );
206         FsmAp *makeSpecific( GraphDictEl *gdNode );
207         FsmAp *makeAll();
208
209         /* Checking the contents of actions. */
210         void checkAction( Action *action );
211         void checkInlineList( Action *act, InlineList *inlineList );
212
213         void analyzeAction( Action *action, InlineList *inlineList );
214         void analyzeGraph( FsmAp *graph );
215         void makeExports();
216
217         void prepareMachineGen( GraphDictEl *graphDictEl );
218         void prepareMachineGenTBWrapped( GraphDictEl *graphDictEl );
219         void generateXML( ostream &out, XmlParser &xmlParser );
220         void generateReduced( XmlParser &xmlParser );
221         FsmAp *sectionGraph;
222         bool generatingSectionSubset;
223
224         void initKeyOps();
225
226         /*
227          * Data collected during the parse.
228          */
229
230         /* Dictionary of graphs. Both instances and non-instances go here. */
231         GraphDict graphDict;
232
233         /* The list of instances. */
234         GraphList instanceList;
235
236         /* Dictionary of actions. Lets actions be defined and then referenced. */
237         ActionDict actionDict;
238
239         /* Dictionary of named priorities. */
240         PriorDict priorDict;
241
242         /* Dictionary of named local errors. */
243         LocalErrDict localErrDict;
244
245         /* List of actions. Will be pasted into a switch statement. */
246         ActionList actionList;
247
248         /* The id of the next priority name and label. */
249         int nextPriorKey, nextLocalErrKey, nextNameId, nextCondId;
250         
251         /* The default priority number key for a machine. This is active during
252          * the parse of the rhs of a machine assignment. */
253         int curDefPriorKey;
254
255         int curDefLocalErrKey;
256
257         /* Alphabet type. */
258         HostType *userAlphType;
259         bool alphTypeSet;
260         InputLoc alphTypeLoc;
261
262         /* Element type and get key expression. */
263         InlineList *getKeyExpr;
264         InlineList *accessExpr;
265
266         /* Stack management */
267         InlineList *prePushExpr;
268         InlineList *postPopExpr;
269
270         /* Overriding variables. */
271         InlineList *pExpr;
272         InlineList *peExpr;
273         InlineList *eofExpr;
274         InlineList *csExpr;
275         InlineList *topExpr;
276         InlineList *stackExpr;
277         InlineList *actExpr;
278         InlineList *tokstartExpr;
279         InlineList *tokendExpr;
280         InlineList *dataExpr;
281
282         /* The alphabet range. */
283         char *lowerNum, *upperNum;
284         Key lowKey, highKey;
285         InputLoc rangeLowLoc, rangeHighLoc;
286
287         /* The name of the file the fsm is from, and the spec name. */
288         const char *fileName;
289         char *sectionName;
290         InputLoc sectionLoc;
291
292         /* Counting the action and priority ordering. */
293         int curActionOrd;
294         int curPriorOrd;
295
296         /* Root of the name tree. One root is for the instantiated machines. The
297          * other root is for exported definitions. */
298         NameInst *rootName;
299         NameInst *exportsRootName;
300         
301         /* Name tree walking. */
302         NameInst *curNameInst;
303         int curNameChild;
304
305         /* The place where resolved epsilon transitions go. These cannot go into
306          * the parse tree because a single epsilon op can resolve more than once
307          * to different nameInsts if the machine it's in is used more than once. */
308         NameVect epsilonResolvedLinks;
309         int nextEpsilonResolvedLink;
310
311         /* Root of the name tree used for doing local name searches. */
312         NameInst *localNameScope;
313
314         void setLmInRetLoc( InlineList *inlineList );
315         void initLongestMatchData();
316         void setLongestMatchData( FsmAp *graph );
317         void initNameWalk();
318         void initExportsNameWalk();
319         NameInst *nextNameScope() { return curNameInst->childVect[curNameChild]; }
320         NameFrame enterNameScope( bool isLocal, int numScopes );
321         void popNameScope( const NameFrame &frame );
322         void resetNameScope( const NameFrame &frame );
323
324         /* Make name ids to name inst pointers. */
325         NameInst **nameIndex;
326
327         /* Counter for assigning ids to longest match items. */
328         int nextLongestMatchId;
329         bool lmRequiresErrorState;
330
331         /* List of all longest match parse tree items. */
332         LmList lmList;
333
334         Action *newAction( const char *name, InlineList *inlineList );
335
336         Action *initTokStart;
337         int initTokStartOrd;
338
339         Action *setTokStart;
340         int setTokStartOrd;
341
342         Action *initActId;
343         int initActIdOrd;
344
345         Action *setTokEnd;
346         int setTokEndOrd;
347
348         void beginProcessing()
349         {
350                 ::condData = &thisCondData;
351                 ::keyOps = &thisKeyOps;
352         }
353
354         CondData thisCondData;
355         KeyOps thisKeyOps;
356
357         ExportList exportList;
358 };
359
360 void afterOpMinimize( FsmAp *fsm, bool lastInSeq = true );
361 Key makeFsmKeyHex( char *str, const InputLoc &loc, ParseData *pd );
362 Key makeFsmKeyDec( char *str, const InputLoc &loc, ParseData *pd );
363 Key makeFsmKeyNum( char *str, const InputLoc &loc, ParseData *pd );
364 Key makeFsmKeyChar( char c, ParseData *pd );
365 void makeFsmKeyArray( Key *result, char *data, int len, ParseData *pd );
366 void makeFsmUniqueKeyArray( KeySet &result, char *data, int len, 
367                 bool caseInsensitive, ParseData *pd );
368 FsmAp *makeBuiltin( BuiltinMachine builtin, ParseData *pd );
369 FsmAp *dotFsm( ParseData *pd );
370 FsmAp *dotStarFsm( ParseData *pd );
371
372 void errorStateLabels( const NameSet &locations );
373
374 struct InputItem
375 {
376         enum Type {
377                 HostData,
378                 Write,
379         };
380
381         Type type;
382         std::ostringstream data;
383         std::string name;
384         Vector<char *> writeArgs;
385
386         InputLoc loc;
387
388         InputItem *prev, *next;
389 };
390
391 /*
392  * Global data.
393  */
394
395 struct Parser;
396
397 typedef AvlMap<char*, Parser *, CmpStr> ParserDict;
398 typedef AvlMapEl<char*, Parser *> ParserDictEl;
399
400 typedef DList<InputItem> InputItemList;
401
402 extern ParserDict parserDict;
403 extern InputItemList inputItems;
404
405 #endif /* _PARSEDATA_H */