2 * Copyright 2001-2008 Adrian Thurston <thurston@complang.org>
5 /* This file is part of Ragel.
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.
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.
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
36 #include "parsetree.h"
46 struct FactorWithLabel
;
59 typedef DList
<LongestMatch
> LmList
;
62 /* Graph dictionary. */
65 public AvlTreeEl
<GraphDictEl
>,
66 public DListEl
<GraphDictEl
>
68 GraphDictEl( const char *k
)
69 : key(k
), value(0), isInstance(false) { }
70 GraphDictEl( const char *k
, VarDef
*value
)
71 : key(k
), value(value
), isInstance(false) { }
73 const char *getKey() { return key
; }
79 /* Location info of graph definition. Points to variable name of assignment. */
83 typedef AvlTree
<GraphDictEl
, const char*, CmpStr
> GraphDict
;
84 typedef DList
<GraphDictEl
> GraphList
;
86 /* Priority name dictionary. */
87 typedef AvlMapEl
<char*, int> PriorDictEl
;
88 typedef AvlMap
<char*, int, CmpStr
> PriorDict
;
90 /* Local error name dictionary. */
91 typedef AvlMapEl
<const char*, int> LocalErrDictEl
;
92 typedef AvlMap
<const char*, int, CmpStr
> LocalErrDict
;
94 /* Tree of instantiated names. */
95 typedef BstMapEl
<const char*, NameInst
*> NameMapEl
;
96 typedef BstMap
<const char*, NameInst
*, CmpStr
> NameMap
;
97 typedef Vector
<NameInst
*> NameVect
;
98 typedef BstSet
<NameInst
*> NameSet
;
100 /* Node in the tree of instantiated names. */
103 NameInst( const InputLoc
&loc
, NameInst
*parent
, const char *name
, int id
, bool isLabel
) :
104 loc(loc
), parent(parent
), name(name
), id(id
), isLabel(isLabel
),
105 isLongestMatch(false), numRefs(0), numUses(0), start(0), final(0) {}
109 /* Keep parent pointers in the name tree to retrieve
110 * fully qulified names. */
121 /* Names underneath us, excludes anonymous names. */
124 /* All names underneath us in order of appearance. */
127 /* Join scopes need an implicit "final" target. */
128 NameInst
*start
, *final
;
130 /* During a fsm generation walk, lists the names that are referenced by
131 * epsilon operations in the current scope. After the link is made by the
132 * epsilon reference and the join operation is complete, the label can
133 * have its refcount decremented. Once there are no more references the
134 * entry point can be removed from the fsm returned. */
135 NameVect referencedNames
;
137 /* Pointers for the name search queue. */
138 NameInst
*prev
, *next
;
140 /* Check if this name inst or any name inst below is referenced. */
144 typedef DList
<NameInst
> NameInstList
;
146 /* Stack frame used in walking the name tree. */
149 NameInst
*prevNameInst
;
151 NameInst
*prevLocalScope
;
156 LengthDef( char *name
)
160 LengthDef
*prev
, *next
;
163 typedef DList
<LengthDef
> LengthDefList
;
165 /* Class to collect information about the machine during the
169 /* Create a new parse data object. This is done at the beginning of every
170 * fsm specification. */
171 ParseData( const char *fileName
, char *sectionName
, const InputLoc
§ionLoc
);
175 * Setting up the graph dict.
178 /* Initialize a graph dict with the basic fsms. */
179 void initGraphDict();
180 void createBuiltin( const char *name
, BuiltinMachine builtin
);
182 /* Make a name id in the current name instantiation scope if it is not
184 NameInst
*addNameInst( const InputLoc
&loc
, const char *data
, bool isLabel
);
185 void makeRootNames();
186 void makeNameTree( GraphDictEl
*gdNode
);
187 void makeExportsNameTree();
188 void fillNameIndex( NameInst
*from
);
189 void printNameTree();
191 /* Increments the usage count on entry names. Names that are no longer
192 * needed will have their entry points unset. */
193 void unsetObsoleteEntries( FsmAp
*graph
);
195 /* Resove name references in action code and epsilon transitions. */
196 NameSet
resolvePart( NameInst
*refFrom
, const char *data
, bool recLabelsOnly
);
197 void resolveFrom( NameSet
&result
, NameInst
*refFrom
,
198 const NameRef
&nameRef
, int namePos
);
199 NameInst
*resolveStateRef( const NameRef
&nameRef
, InputLoc
&loc
, Action
*action
);
200 void resolveNameRefs( InlineList
*inlineList
, Action
*action
);
201 void resolveActionNameRefs();
203 /* Set the alphabet type. If type types are not valid returns false. */
204 bool setAlphType( const InputLoc
&loc
, char *s1
, char *s2
);
205 bool setAlphType( const InputLoc
&loc
, char *s1
);
207 /* Override one of the variables ragel uses. */
208 bool setVariable( char *var
, InlineList
*inlineList
);
210 /* Unique actions. */
211 void removeDups( ActionTable
&actionTable
);
212 void removeActionDups( FsmAp
*graph
);
214 /* Dumping the name instantiation tree. */
215 void printNameInst( NameInst
*nameInst
, int level
);
217 /* Make the graph from a graph dict node. Does minimization. */
218 FsmAp
*makeInstance( GraphDictEl
*gdNode
);
219 FsmAp
*makeSpecific( GraphDictEl
*gdNode
);
222 /* Checking the contents of actions. */
223 void checkAction( Action
*action
);
224 void checkInlineList( Action
*act
, InlineList
*inlineList
);
226 void analyzeAction( Action
*action
, InlineList
*inlineList
);
227 void analyzeGraph( FsmAp
*graph
);
230 void prepareMachineGen( GraphDictEl
*graphDictEl
);
231 void prepareMachineGenTBWrapped( GraphDictEl
*graphDictEl
);
232 void generateXML( ostream
&out
);
233 void generateReduced( InputData
&inputData
);
235 bool generatingSectionSubset
;
240 * Data collected during the parse.
243 /* Dictionary of graphs. Both instances and non-instances go here. */
246 /* The list of instances. */
247 GraphList instanceList
;
249 /* Dictionary of actions. Lets actions be defined and then referenced. */
250 ActionDict actionDict
;
252 /* Dictionary of named priorities. */
255 /* Dictionary of named local errors. */
256 LocalErrDict localErrDict
;
258 /* List of actions. Will be pasted into a switch statement. */
259 ActionList actionList
;
261 /* The id of the next priority name and label. */
262 int nextPriorKey
, nextLocalErrKey
, nextNameId
, nextCondId
;
264 /* The default priority number key for a machine. This is active during
265 * the parse of the rhs of a machine assignment. */
268 int curDefLocalErrKey
;
271 HostType
*userAlphType
;
273 InputLoc alphTypeLoc
;
275 /* Element type and get key expression. */
276 InlineList
*getKeyExpr
;
277 InlineList
*accessExpr
;
279 /* Stack management */
280 InlineList
*prePushExpr
;
281 InlineList
*postPopExpr
;
283 /* Overriding variables. */
289 InlineList
*stackExpr
;
291 InlineList
*tokstartExpr
;
292 InlineList
*tokendExpr
;
293 InlineList
*dataExpr
;
295 /* The alphabet range. */
296 char *lowerNum
, *upperNum
;
298 InputLoc rangeLowLoc
, rangeHighLoc
;
300 /* The name of the file the fsm is from, and the spec name. */
301 const char *fileName
;
305 /* Counting the action and priority ordering. */
309 /* Root of the name tree. One root is for the instantiated machines. The
310 * other root is for exported definitions. */
312 NameInst
*exportsRootName
;
314 /* Name tree walking. */
315 NameInst
*curNameInst
;
318 /* The place where resolved epsilon transitions go. These cannot go into
319 * the parse tree because a single epsilon op can resolve more than once
320 * to different nameInsts if the machine it's in is used more than once. */
321 NameVect epsilonResolvedLinks
;
322 int nextEpsilonResolvedLink
;
324 /* Root of the name tree used for doing local name searches. */
325 NameInst
*localNameScope
;
327 void setLmInRetLoc( InlineList
*inlineList
);
328 void initLongestMatchData();
329 void setLongestMatchData( FsmAp
*graph
);
331 void initExportsNameWalk();
332 NameInst
*nextNameScope() { return curNameInst
->childVect
[curNameChild
]; }
333 NameFrame
enterNameScope( bool isLocal
, int numScopes
);
334 void popNameScope( const NameFrame
&frame
);
335 void resetNameScope( const NameFrame
&frame
);
337 /* Make name ids to name inst pointers. */
338 NameInst
**nameIndex
;
340 /* Counter for assigning ids to longest match items. */
341 int nextLongestMatchId
;
342 bool lmRequiresErrorState
;
344 /* List of all longest match parse tree items. */
347 Action
*newAction( const char *name
, InlineList
*inlineList
);
349 Action
*initTokStart
;
361 void beginProcessing()
363 ::condData
= &thisCondData
;
364 ::keyOps
= &thisKeyOps
;
367 CondData thisCondData
;
370 ExportList exportList
;
371 LengthDefList lengthDefList
;
376 void afterOpMinimize( FsmAp
*fsm
, bool lastInSeq
= true );
377 Key
makeFsmKeyHex( char *str
, const InputLoc
&loc
, ParseData
*pd
);
378 Key
makeFsmKeyDec( char *str
, const InputLoc
&loc
, ParseData
*pd
);
379 Key
makeFsmKeyNum( char *str
, const InputLoc
&loc
, ParseData
*pd
);
380 Key
makeFsmKeyChar( char c
, ParseData
*pd
);
381 void makeFsmKeyArray( Key
*result
, char *data
, int len
, ParseData
*pd
);
382 void makeFsmUniqueKeyArray( KeySet
&result
, char *data
, int len
,
383 bool caseInsensitive
, ParseData
*pd
);
384 FsmAp
*makeBuiltin( BuiltinMachine builtin
, ParseData
*pd
);
385 FsmAp
*dotFsm( ParseData
*pd
);
386 FsmAp
*dotStarFsm( ParseData
*pd
);
388 void errorStateLabels( const NameSet
&locations
);