Forward compatibility: flex
[foam-extend-3.2.git] / src / surfMesh / surfaceFormats / stl / STLsurfaceFormatASCII.L
blob877d3793dcc05f4302f376b9f785b49a9f0ac316
1 /*--------------------------------*- C++ -*----------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
28 #undef yyFlexLexer
30  /* ------------------------------------------------------------------------ *\
31    ------ local definitions
32  \* ------------------------------------------------------------------------ */
34 #include "STLsurfaceFormatCore.H"
36 using namespace Foam;
38 // Dummy yyFlexLexer::yylex() to keep the linker happy. It is not called
39 //! @cond dummy
40 int yyFlexLexer::yylex()
42     FatalErrorIn("yyFlexLexer::yylex()")
43         << "Should not have called this function"
44         << abort(FatalError);
45     return 0;
47 //! @endcond dummy
49 // Dummy yywrap to keep yylex happy at compile time.
50 // It is called by yylex but is not used as the mechanism to change file.
51 // See <<EOF>>
52 //! @cond dummy
53 #if YY_FLEX_MINOR_VERSION < 6 && YY_FLEX_SUBMINOR_VERSION < 34
54 extern "C" int yywrap()
55 #else
56 int yyFlexLexer::yywrap()
57 #endif
59     return 1;
61 //! @endcond dummy
64 //- A lexer for parsing STL ASCII files.
65 //  Returns DynamicList(s) of points and facets (zoneIds).
66 //  The facets are within a solid/endsolid grouping
67 class STLASCIILexer
69     public yyFlexLexer
71     // Private data
73         bool  sorted_;
74         label groupID_;      // current solid group
75         label lineNo_;
76         word  startError_;
78         DynamicList<point> points_;
79         DynamicList<label> facets_;
80         DynamicList<word>  names_;
81         DynamicList<label> sizes_;
82         HashTable<label>   lookup_;
84 public:
86     // Constructors
88         //- From input stream and the approximate number of vertices in the STL
89         STLASCIILexer(istream* is, const label approxNpoints);
92     // Member Functions
94         //- The lexer function itself
95         int lex();
97     // Access
99         //- Do all the solid groups appear in order
100         bool sorted() const
101         {
102             return sorted_;
103         }
105         //- A list of points corresponding to a pointField
106         DynamicList<point>& points()
107         {
108             return points_;
109         }
111         //- A list of facet IDs (group IDs)
112         //  corresponds to the number of triangles
113         DynamicList<label>& facets()
114         {
115             return facets_;
116         }
118         //- Names
119         DynamicList<word>& names()
120         {
121             return names_;
122         }
124         //- Sizes
125         DynamicList<label>& sizes()
126         {
127             return sizes_;
128         }
132 STLASCIILexer::STLASCIILexer(istream* is, const label approxNpoints)
134     yyFlexLexer(is),
135     sorted_(true),
136     groupID_(-1),
137     lineNo_(1),
138     points_(approxNpoints),
139     facets_(approxNpoints)
143  /* ------------------------------------------------------------------------ *\
144    ------ cppLexer::yylex()
145  \* ------------------------------------------------------------------------ */
147 #define YY_DECL int STLASCIILexer::lex()
151 one_space             [ \t\f\r]
152 space                 {one_space}*
153 some_space            {one_space}+
154 cspace                ","{space}
156 alpha                 [_A-Za-z]
157 digit                 [0-9]
158 dec_digit             [0-9]
159 octal_digit           [0-7]
160 hex_digit             [0-9a-fA-F]
162 identifier            {alpha}({alpha}|{digit})*
163 integer               {dec_digit}+
164 label                 [1-9]{dec_digit}*
165 zeroLabel             {digit}*
166 signedInteger         [-+]?{integer}
168 word                  ([[:alnum:]]|[[:punct:]])*
169 string                {word}({some_space}{word})*
171 exponent_part         [eE][-+]?{digit}+
172 fractional_constant   [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
174 double                (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))
175 float                 {double}
177 x                     {float}
178 y                     {float}
179 z                     {float}
181 solid                 {space}("solid"|"SOLID"){space}
182 color                 {space}("color"|"COLOR"){some_space}{float}{some_space}{float}{some_space}{float}{space}
183 facet                 {space}("facet"|"FACET"){space}
184 normal                {space}("normal"|"NORMAL"){space}
185 point                 {space}{x}{some_space}{y}{some_space}{z}{space}
186 outerloop             {space}("outer"{some_space}"loop")|("OUTER"{some_space}"LOOP"){space}
187 vertex                {space}("vertex"|"VERTEX"){space}
188 endloop               {space}("endloop"|"ENDLOOP"){space}
189 endfacet              {space}("endfacet"|"ENDFACET"){space}
190 endsolid              {space}("endsolid"|"ENDSOLID")({some_space}{word})*
193  /* ------------------------------------------------------------------------ *\
194                       -----  Exclusive start states -----
195  \* ------------------------------------------------------------------------ */
197 %option stack
199 %x readSolidName
200 %x readFacet
201 %x readNormal
202 %x readVertices
203 %x readVertex
204 %x stlError
209     // End of read character pointer returned by strtof
210     // char* endPtr;
212     STLpoint normal;
213     STLpoint vertex;
214     label cmpt = 0;   // component index used for reading vertex
216     static const char* stateNames[7] =
217     {
218         "reading solid",
219         "reading solid name",
220         "reading facet",
221         "reading normal",
222         "reading vertices",
223         "reading vertex",
224         "error"
225     };
227     static const char* stateExpects[7] =
228     {
229         "'solid', 'color', 'facet' or 'endsolid'",
230         "<string>",
231         "'normal', 'outer loop' or 'endfacet'",
232         "<float> <float> <float>",
233         "'vertex' or 'endloop'",
234         "<float> <float> <float>",
235         ""
236     };
240  /* ------------------------------------------------------------------------ *\
241                             ------ Start Lexing ------
242  \* ------------------------------------------------------------------------ */
244  /*                      ------ Reading control header ------                */
246 {solid} {
247         BEGIN(readSolidName);
248     }
250 <readSolidName>{string} {
251         word name(Foam::string::validate<word>(YYText()));
253         HashTable<label>::const_iterator fnd = lookup_.find(name);
254         if (fnd != lookup_.end())
255         {
256             if (groupID_ != fnd())
257             {
258                 // group appeared out of order
259                 sorted_ = false;
260             }
261             groupID_ = fnd();
262         }
263         else
264         {
265             groupID_ = sizes_.size();
266             lookup_.insert(name, groupID_);
267             names_.append(name);
268             sizes_.append(0);
269         }
270         BEGIN(INITIAL);
271     }
273 <readSolidName>{space}\n {
274         word name("solid");
276         HashTable<label>::const_iterator fnd = lookup_.find(name);
277         if (fnd != lookup_.end())
278         {
279             if (groupID_ != fnd())
280             {
281                 // group appeared out of order
282                 sorted_ = false;
283             }
284             groupID_ = fnd();
285         }
286         else
287         {
288             groupID_ = sizes_.size();
289             lookup_.insert(name, groupID_);
290             names_.append(name);
291             sizes_.append(0);
292         }
294         lineNo_++;
295         BEGIN(INITIAL);
296     }
298 {color} {
299     }
301 {facet} {
302         BEGIN(readFacet);
303     }
305 <readFacet>{normal} {
306         BEGIN(readNormal);
307     }
309 <readNormal>{point} {
310         /*
311          skip reading normals:
312          normal.x() = strtof(YYText(), &endPtr);
313          normal.y() = strtof(endPtr, &endPtr);
314          normal.z() = strtof(endPtr, &endPtr);
315          normals_.append(normal);
316          */
317         BEGIN(readFacet);
318     }
320 <readFacet>{outerloop} {
321         BEGIN(readVertices);
322     }
324 <readVertices>{vertex} {
325         BEGIN(readVertex);
326     }
328 <readVertex>{space}{signedInteger}{space} {
329         vertex[cmpt++] = atol(YYText());
331         if (cmpt == 3)
332         {
333             cmpt = 0;
334             points_.append(vertex);
335             BEGIN(readVertices);
336         }
337     }
339 <readVertex>{space}{float}{space} {
340         vertex[cmpt++] = atof(YYText());
342         if (cmpt == 3)
343         {
344             cmpt = 0;
345             points_.append(vertex);
346             BEGIN(readVertices);
347         }
348     }
350 <readVertices>{endloop} {
351         BEGIN(readFacet);
352     }
354 <readFacet>{endfacet} {
355         facets_.append(groupID_);
356         sizes_[groupID_]++;
357         BEGIN(INITIAL);
358     }
360 {endsolid} {
361     }
364  /* ------------------ Ignore remaining space and \n s. -------------------- */
366 <*>{space} {}
367 <*>\n      { lineNo_++; }
370  /* ------------------- Any other characters are errors -------------------- */
372 <*>. {
373         startError_ = YYText();
374         yy_push_state(stlError);
375     }
378  /* ---------------------------- Error handler ----------------------------- */
380 <stlError>.* {
381         yy_pop_state();
382         FatalErrorIn
383         (
384             "fileFormats::STLsurfaceFormatCore::readASCII(const fileName&)"
385         )   << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl
386             << "    expected " << stateExpects[YY_START]
387             << " but found '" << startError_.c_str() << YYText() << "'"
388             << exit(FatalError);
389     }
392  /*  ------------------------ On EOF terminate ----------------------------  */
394 <<EOF>> {
395             yyterminate();
396     }
401 // member function
403 bool Foam::fileFormats::STLsurfaceFormatCore::readASCII
405     istream& is,
406     const off_t dataFileSize
409     // Create the lexer with the approximate number of vertices in the STL
410     // from the file size
411     STLASCIILexer lexer(&is, dataFileSize/400);
412     while (lexer.lex() != 0) {}
414     sorted_ = lexer.sorted();
416     // transfer to normal lists
417     points_.transfer(lexer.points());
418     zoneIds_.transfer(lexer.facets());
419     names_.transfer(lexer.names());
420     sizes_.transfer(lexer.sizes());
422     return true;
425  /* ------------------------------------------------------------------------ *\
426     ------ End of STLfileFormatASCII.L
427  \* ------------------------------------------------------------------------ */