Update suitable examples and tests to use blank mode
[shapes.git] / source / shapesyylex.ll
blob3ee6bc91034f1d9c56afc62b86bd582fc5fca3ff
1 /* This file is part of Shapes.
2  *
3  * Shapes is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 3 of the License, or
6  * any later version.
7  *
8  * Shapes is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with Shapes.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Copyright 2008, 2010, 2013, 2014 Henrik Tidefelt
17  */
21 #include <cmath>
23 #include "shapesscanner.h"
24 #include "shapesvalue.h"
25 #include "shapestypes.h"
26 #include "astflow.h"
27 #include "astvar.h"
28 #include "astclass.h"
29 #include "shapesexceptions.h"
30 #include "texlabelmanager.h"
31 #include "globals.h"
32 #include "exitcodes.h"
34 using namespace Shapes;
35 #include "yyltype.h"
36 #include "shapesparser.hh"
38 #include <string>
39 #include <cstdlib>
40 #include <iostream>
41 #include <fstream>
42 #include <sstream>
43 #include <iomanip>
44 #include <cstdio> /* This is a workaround for a bug in Flex. */
46 #define YY_USER_ACTION doBeforeEachAction( );
47 #define YY_EXIT_FAILURE Shapes::Interaction::EXIT_INTERNAL_ERROR
49 double shapes_strtod( char * str, char ** end );
50 char shapes_hexToChar( char c1, char c2 );
54 WhiteSpace [ ]
56 LexDirPrefix ^[ \t]*"##"
57 Float [~]?[0-9]+([.][0-9]*)?("*^"[~]?[0-9]+)?
58 Greek "α"|"β"|"γ"|"Γ"|"δ"|"Δ"|"ε"|"ζ"|"η"|"Θ"|"ι"|"κ"|"λ"|"Λ"|"μ"|"ν"|"χ"|"Ξ"|"π"|"Π"|"ρ"|"σ"|"Σ"|"τ"|"ϕ"|"ω"|"Ω"
59 LowerCaseLetter [a-z_?]
60 UpperCaseLetter [A-Z]
61 Letter {LowerCaseLetter}|{UpperCaseLetter}|{Greek}
62 SimpleIdentifier {Letter}({Letter}|[0-9])*
63 Encapsulation "^^"
64 NamespaceSep ".."
65 NonEmptyNamespacePath ({Encapsulation}|{NamespaceSep})?({SimpleIdentifier}{NamespaceSep})*{SimpleIdentifier}
66 UTF8char [\x00-\x7F]|([\xC0-\xDF][\x80-\xBF])|([\xE0-\xEF][\x80-\xBF][\x80-\xBF])|([\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])
67 DynamicMark "@"
68 StateMark "#"|"•"
69 TypeMark "//"|"§"
72 %option c++
73 %option noyywrap
74 %option yylineno
76 %option prefix="shapes"
77 %option yyclass="ShapesScanner"
79 %x DiscardRestOfLineAndBEGIN_INITIAL
80 %x Incl
81 %x Needs
82 %x InclOptFile
83 %x InclFile
84 %x InclFrom
85 %x InclPath
86 %x NamespacePrefix
87 %x String
88 %x PoorMansString
89 %x DataStringPlain
90 %x DataStringHex
91 %x Comment
92 %x LaTeXOption
93 %x LaTeXClass
94 %x LaTeXPreamble
95 %x LaTeXDocumentTop
96 %x RandSeed
97 %x NewUnitName
98 %x NewUnitEqual
99 %x NewUnitValue
100 %x Author
101 %x Echo
102 %x Push
103 %x Pop
104 %x Lookin
105 %x TreeNamespaceAlias
106 %x TreeNamespaceEqual
107 %x TreeNamespaceOriginal
112 {LexDirPrefix}"classoption"[ \t]+ { BEGIN( LaTeXOption ); }
113 {LexDirPrefix}"documentclass"[ \t]+ { BEGIN( LaTeXClass ); }
114 {LexDirPrefix}"preamble"[ \t] { BEGIN( LaTeXPreamble ); }
115 {LexDirPrefix}"documenttop"[ \t] { BEGIN( LaTeXDocumentTop ); }
116 {LexDirPrefix}"no-lmodernT1"[\n] { Kernel::theTeXLabelManager.setlmodernT1( shapeslloc, false ); endOfLine( ); }
117 {LexDirPrefix}"no-utf8"[\n] { Kernel::theTeXLabelManager.setutf8( shapeslloc, false ); endOfLine( ); }
118 {LexDirPrefix}"seed"[ \t]+ { BEGIN( RandSeed ); }
119 {LexDirPrefix}"unit"[ \t]+ { BEGIN( NewUnitName ); }
120 {LexDirPrefix}"author"[ \t] { BEGIN( Author ); }
121 {LexDirPrefix}"include"[ \t]+ { BEGIN( Incl ); return T_srcLoc; }
122 {LexDirPrefix}"needs"[ \t]+ { BEGIN( Needs ); return T_srcLoc; }
123 {LexDirPrefix}"echo"[ \t] { BEGIN( Echo ); }
124 {LexDirPrefix}"push"[ \t]+ { BEGIN( Push ); }
125 {LexDirPrefix}"pop"[ \t]+ { BEGIN( Pop ); }
126 {LexDirPrefix}"lookin"[ \t]+ { BEGIN( Lookin ); }
127 {LexDirPrefix}"alias"[ \t]+ { BEGIN( TreeNamespaceAlias ); }
128 {LexDirPrefix} {
129         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Unrecognized lexer directive (all lines beginning with ## are lexer directives)." ) ) );
130         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
133 <DiscardRestOfLineAndBEGIN_INITIAL>.* {
134         BEGIN( INITIAL );
136 <DiscardRestOfLineAndBEGIN_INITIAL>[\n] {
137   endOfLine( );
138         BEGIN( INITIAL );
141 <LaTeXOption>[^,\n]+ { Kernel::theTeXLabelManager.addDocumentOption( shapeslloc, yytext ); }
142 <LaTeXOption>[\n] {
143   endOfLine( );
144         BEGIN( INITIAL );
147 <LaTeXClass>.+ { Kernel::theTeXLabelManager.setDocumentClass( shapeslloc, yytext ); }
148 <LaTeXClass>[\n] {
149   endOfLine( );
150         BEGIN( INITIAL );
153 <LaTeXPreamble>.* { Kernel::theTeXLabelManager.addPreambleLine( shapeslloc, yytext ); }
154 <LaTeXPreamble>[\n] {
155   endOfLine( );
156         BEGIN( INITIAL );
159 <LaTeXDocumentTop>.* { Kernel::theTeXLabelManager.addDocumentTopLine( shapeslloc, yytext ); }
160 <LaTeXDocumentTop>[\n] {
161   endOfLine( );
162         BEGIN( INITIAL );
165 <RandSeed>.* {
166         char * end;
167         long int s = strtol( yytext, & end, 10 );
168         if( *end != '\0' )
169                 {
170                         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Failed to scan integer." ) ) );
171                 }
172         else
173                 {
174                         if( s < 0 )
175                                 {
176                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Random nuber generator seed must not be negative." ) ) );
177                                 }
178                         else
179                                 {
180                                         srand( s );
181                                 }
182                 }
184 <RandSeed>[\n] {
185   endOfLine( );
186         BEGIN( INITIAL );
189 <NewUnitName>{SimpleIdentifier} {
190         newUnitName_ = strdup( yytext );
191         BEGIN( NewUnitEqual );
193 <NewUnitName>. {
194         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected identifier." ) ) );
195         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
197 <NewUnitEqual>[ \t]*"="[ \t]* { BEGIN( NewUnitValue ); }
198 <NewUnitEqual>. {
199         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected '='." ) ) );
200         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
202 <NewUnitValue>{Float}{SimpleIdentifier} {
203         char * end;
204         double val = shapes_strtod( yytext, & end );
206         typedef typeof lengthUnits_ MapType;
207         MapType::const_iterator i;
208         if( ( i = lengthUnits_.find( end ) ) != lengthUnits_.end( ) )
209                 {
210                         double newUnitValue = val * i->second;
212                         if( ( i = lengthUnits_.find( newUnitName_ ) ) != lengthUnits_.end( ) )
213                                 {
214                                         if( i->second != newUnitValue )
215                                                 {
216                                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
217                                                 }
218                                 }
219                         else if( ( i = angleUnits_.find( newUnitName_ ) ) != angleUnits_.end( ) )
220                                 {
221                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
222                                 }
223                         else
224                                 {
225                                         lengthUnits_[ newUnitName_ ] = newUnitValue;
226                                 }
227                 }
228         else if( ( i = angleUnits_.find( end ) ) != angleUnits_.end( ) )
229                 {
230                         double newUnitValue = val * i->second;
232                         if( ( i = angleUnits_.find( newUnitName_ ) ) != angleUnits_.end( ) )
233                                 {
234                                         if( i->second != newUnitValue )
235                                                 {
236                                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
237                                                 }
238                                 }
239                         else if( ( i = lengthUnits_.find( newUnitName_ ) ) != lengthUnits_.end( ) )
240                                 {
241                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
242                                 }
243                         else
244                                 {
245                                         angleUnits_[ newUnitName_ ] = newUnitValue;
246                                 }
247                 }
248         else
249                 {
250                         Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknownUnit( shapeslloc, strrefdup( end ) ) );
251                 }
253         BEGIN( INITIAL );
255 <NewUnitValue>{Float}"°" {
256         char * end;
257         double val = shapes_strtod( yytext, & end );
259         double newUnitValue = val * ( M_PI / 180 );
261         typedef typeof lengthUnits_ MapType;
262         MapType::const_iterator i;
264         if( ( i = angleUnits_.find( newUnitName_ ) ) != angleUnits_.end( ) )
265                 {
266                         if( i->second != newUnitValue )
267                                 {
268                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
269                                 }
270                 }
271         else if( ( i = lengthUnits_.find( newUnitName_ ) ) != lengthUnits_.end( ) )
272                 {
273                         Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
274                 }
275         else
276                 {
277                         angleUnits_[ newUnitName_ ] = newUnitValue;
278                 }
280         BEGIN( INITIAL );
282 <NewUnitValue>. {
283         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected a length." ) ) );
284         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
288 {Float}"rad" {
289         char * end;
290         shapeslval.floatVal = shapes_strtod( yytext, & end );
291         return T_float;
294 {Float}"°" |
295 {Float}"deg" {
296         char * end;
297         shapeslval.floatVal = M_PI / 180 * shapes_strtod( yytext, & end );
298         return T_float;
301 {Float}"grad" {
302         char * end;
303         shapeslval.floatVal = M_PI / 200 * shapes_strtod( yytext, & end );
304         return T_float;
307 {Float}"bp" {
308         char * end;
309         shapeslval.floatVal = shapes_strtod( yytext, & end );
310         return T_length;
313 {Float}"mm" {
314         char * end;
315         shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 0.1 * 72 / 2.54 );
316         return T_length;
319 {Float}"cm" {
320         char * end;
321         shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 72 / 2.54 );
322         return T_length;
325 {Float}"m" {
326         char * end;
327         shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 100 * 72 / 2.54 );
328         return T_length;
331 {Float}"in" {
332         char * end;
333         shapeslval.floatVal = shapes_strtod( yytext, & end ) * 72;
334         return T_length;
337 {Float}{SimpleIdentifier} {
338         char * end;
339         double val = shapes_strtod( yytext, & end );
341         typedef typeof lengthUnits_ MapType;
342         MapType::const_iterator i;
343         if( ( i = lengthUnits_.find( end ) ) != lengthUnits_.end( ) )
344                 {
345                         shapeslval.floatVal = val * i->second;
346                         return T_length;
347                 }
348         if( ( i = angleUnits_.find( end ) ) != angleUnits_.end( ) )
349                 {
350                         shapeslval.floatVal = val * i->second;
351                         return T_float;
352                 }
354         Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknownUnit( shapeslloc, strrefdup( end ) ) );
355         return T_length; /* Just a guess, it won't really matter since things have gone wrong anyway. */
358 {Float}[\%][D0] {
359         char * end;
360         double val = shapes_strtod( yytext, & end );
361         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST );
362         return T_speciallength;
365 {Float}[\%][C1] {
366         char * end;
367         double val = shapes_strtod( yytext, & end );
368         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC );
369         return T_speciallength;
372 {Float}[\%][M2] {
373         char * end;
374         double val = shapes_strtod( yytext, & end );
375         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CORR );
376         return T_speciallength;
379 {Float}[\%][F3] {
380         char * end;
381         double val = shapes_strtod( yytext, & end );
382         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC | Computation::SPECIALU_CORR );
383         return T_speciallength;
386 {Float}[\%][d4] {
387         char * end;
388         double val = shapes_strtod( yytext, & end );
389         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_NOINFLEX );
390         return T_speciallength;
393 {Float}[\%][c5] {
394         char * end;
395         double val = shapes_strtod( yytext, & end );
396         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC | Computation::SPECIALU_NOINFLEX );
397         return T_speciallength;
400 {Float}[\%][m6] {
401         char * end;
402         double val = shapes_strtod( yytext, & end );
403         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CORR | Computation::SPECIALU_NOINFLEX );
404         return T_speciallength;
407 {Float}[\%][f7] {
408         char * end;
409         double val = shapes_strtod( yytext, & end );
410         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC | Computation::SPECIALU_CORR | Computation::SPECIALU_NOINFLEX );
411         return T_speciallength;
414 {Float}[\%][i9] {
415         char * end;
416         double val = shapes_strtod( yytext, & end );
417         shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_NOINFLEX );
418         return T_speciallength;
422 {Float} {
423         char * end;
424         shapeslval.floatVal = shapes_strtod( yytext, & end );
425         return T_float;
428 "\'"[~]?[0-9]+ {
429         const char * src = yytext + 1;
430         bool negative = false;
431         if( *src == '~' )
432                 {
433                         negative = true;
434                         ++src;
435                 }
436         char * end;
437         int absval = strtol( src, & end, 10 );
438         if( negative )
439                 {
440                         shapeslval.intVal = - absval;
441                 }
442         else
443                 {
444                         shapeslval.intVal = absval;
445                 }
446         return T_int;
449 "\'0x"[0-9A-F]+ {
450         char * end;
451         shapeslval.intVal = strtol( yytext + 3, & end, 16 );
452         return T_int;
455 "\'0b"[0-1]+ {
456         char * end;
457         shapeslval.intVal = strtol( yytext + 3, & end, 2 );
458         return T_int;
461 "\'\""{UTF8char} {
462         const char * src = yytext + 2;
463         if( *src >= 0 )
464                 {
465                         shapeslval.uintVal = *src;
466                 }
467         else
468                 {
469                         switch( 0xF0 & *src )
470                                 {
471                                 case 0xE0:
472                                         shapeslval.uintVal = *src & 0x0F;
473                                         shapeslval.uintVal *= 0x40;
474                                         ++src;
475                                         shapeslval.uintVal += *src & 0x3F;
476                                         shapeslval.uintVal *= 0x40;
477                                         ++src;
478                                         shapeslval.uintVal += *src & 0x3F;
479                                         break;
480                                 case 0xF0:
481                                         shapeslval.uintVal = *src & 0x07;
482                                         shapeslval.uintVal *= 0x40;
483                                         ++src;
484                                         shapeslval.uintVal += *src & 0x3F;
485                                         shapeslval.uintVal *= 0x40;
486                                         ++src;
487                                         shapeslval.uintVal += *src & 0x3F;
488                                         shapeslval.uintVal *= 0x40;
489                                         ++src;
490                                         shapeslval.uintVal += *src & 0x3F;
491                                         break;
492                                 default:
493                                         shapeslval.uintVal = *src & 0x1F;
494                                         shapeslval.uintVal *= 0x40;
495                                         ++src;
496                                         shapeslval.uintVal += *src & 0x3F;
497                                         break;
498                                 }
499                 }
500         return T_char;
503 "\'&U+"[0-9A-F]+";" {
504         char * end;
505         int absval = strtol( yytext + 4, & end, 16 );
506         if( *end != ';' )
507                 {
508                         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Malformed hexadecimal number in character literal." ) ) );
509                 }
510         shapeslval.uintVal = absval;
511         return T_char;
514 "\'&G+"{SimpleIdentifier}";" {
515         yytext[ yyleng - 1 ] = '\0'; /* Cut away the terminating ';' */
516         shapeslval.uintVal = unicodeFromGlyphname( yytext + 4 );
517         return T_char;
520 "∞" {
521         shapeslval.floatVal = HUGE_VAL;
522         return T_float;
525 "true" {
526         shapeslval.boolVal = true;
527         return T_bool;
530 "false" {
531         shapeslval.boolVal = false;
532         return T_bool;
535 "%last" {
536         return T_last;
539 "--" { return T_minusminus; }
540 "++" { return T_plusplus; }
541 "..." { return T_dddot; }
543 "::" { return T_declaretype; }
544 ":=" { return T_assign; }
545 "=" { return T_eqeq; }
546 "/="|"≠" { return T_eqneq; }
548 "->"|"→" { return T_mapsto; }
549 "../" { return T_surrounding; }
550 "[]" { return T_emptybrackets; }
551 "[...]" { return T_dddotbrackets; }
552 "()"|"⊙" { return T_compose; }
554 "(>" { return T_unionLeft; }
555 "<)" { return T_unionRight; }
556 "<>" { return T_split; }
557 "(<" { return T_splitLeft; }
558 ">)" { return T_splitRight; }
559 "(|" { return T_absLeft; }
560 "|)" { return T_absRight; }
562 "(<)" { return T_paren_less; }
563 "(>)" { return T_paren_greater; }
564 "(<=)" { return T_paren_lesseq; }
565 "(>=)" { return T_paren_greatereq; }
567 [\(\)\[\]\<\>] { return yytext[0]; }
568 [\.\,\;\:\_\@\!\#\&\|\^\-\+\'\"\\] { return yytext[0]; }
569 [*/~=] { return yytext[0]; }
571 [\{] {
572         namespaceLimits_.push( searchContext_->lexicalPath( )->size( ) );
573         ++bracketDepth_;
574         return yytext[0];
576 [\}] {
577         /* The closing brace is inbalanced if the namespaceLimits_ stack is empty,
578          * but we leave the reporting of that error to the parser and just treat
579          * the balanced case here.
580          */
581         if( ! namespaceLimits_.empty( ) )
582                 namespaceLimits_.pop( );
583         /* Likewise, we let the parser report the error in case of an unbalanced closing brace.
584          */
585         if( bracketDepth_ > 0 ){
586                 --bracketDepth_;
587         }
588         return yytext[0];
591 "*/"|"∥" { return T_projection; }
592 "/_"|"∠" { return T_angle; }
593 "&|" { return T_ampersandMore; }
595 "<="|"≤" { return T_lesseq; }
596 ">="|"≥" { return T_greatereq; }
598 "<<"|"≪" { return T_llthan; }
599 ">>"|"≫" { return T_ggthan; }
601 "@@" {
602         /* This is a bit of a hack.  The parser needs to know the namespace
603          * at this point, so we embedd this information in a placed identifier.
604          */
605         shapeslval.placedIdent = placedIdentifier( yytext );
606         return T_atat;
609 "and"|"⋀" { return T_and; }
610 "or"|"⋁" { return T_or; }
611 "xor"|"⊻" { return T_xor; }
612 "not"|"¬" { return T_not; }
614 "dynamic" { return T_dynamic; }
616 "cycle" { return T_cycle; }
618 "indexof" { return T_indexof; }
619 "depthof" { return T_depthof; }
620 "VARNAME" { return T_variableName; }
621 "resolved_identifier_string" { return T_absrefof; }
623 "continuation" { return T_continuation; /* Reserved for future use */ }
624 "continue" { return T_continue; /* Reserved for future use */ }
625 "escape_continuation" { return T_esc_continuation; }
626 "escape_continue" { return T_esc_continue; }
627 "escape_backtrace" { return T_esc_backtrace; }
629 "freeze" { return T_freeze; }
631 "class" { return T_class; }
632 "__members__" { return T_members; }
633 "__prepare__" { return T_prepare; }
634 "__abstract__" { return T_abstract; }
635 "__overrides<" { return T_overrides; }
636 ">__" { return T_gr__; }
638 {WhiteSpace}+ ;
639 [\t]+ {
640         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal use of reserved tab character." ) ) );
643 [\n] {
644   endOfLine( );
647 <INITIAL>"|**".*[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; }
648 <INITIAL>"/**" { quoteDepth_ = 1; BEGIN( Comment ); }
649 <INITIAL>"**/" { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found closing comment delimiter outside comment." ) ); }
650 <Comment>"/**" { ++quoteDepth_; more( ); }
651 <Comment>"**/" {
652         --quoteDepth_;
653         if( quoteDepth_ == 0 )
654                 {
655                         BEGIN( INITIAL );
656                 }
657         else
658                 {
659                         more( );
660                 }
662 <Comment>. { }
663 <Comment>[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; }
664 <Comment><<EOF>> {
665         /* It seems like YY_USER_ACTION is not invoked at EOF, so we do this manually,
666          * however ignornig yyleng (which has the value 1).
667          */
668         shapeslloc.firstColumn = shapeslloc.lastColumn;
669         throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found EOF while scanning comment." ) );
672 <INITIAL>[`][\n]? {
673         if( yyleng > 1 )
674                 {
675                         ++shapeslloc.lastLine;
676                         shapeslloc.lastColumn = 0;
677                 }
678         quoteDepth_ = 1;
679         BEGIN( String );
681 <INITIAL>"´" { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found closing quote outside string." ) ); }
682 <String>"`" { ++quoteDepth_; more( ); }
683 <String>"´" {
684         --quoteDepth_;
685         if( quoteDepth_ == 0 )
686                 {
687                         yytext[ yyleng - 2 ] = '\0';
688                         rinseString( );
689                         --shapeslloc.firstColumn;
690                         BEGIN( INITIAL );
691                         return T_string;
692                 }
693         else
694                 {
695                         more( );
696                         yymore( ); /* The purpose of this line is only to let flex know that we use yy_more_flag */
697                 }
700 <String,PoorMansString>[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; more( ); }
701 <String,PoorMansString>. { more( ); }
702 <String,PoorMansString><<EOF>> {
703         /* It seems like YY_USER_ACTION is not invoked at EOF, so we do this manually,
704          * however ignornig yyleng (which has the value 1).
705          */
706         shapeslloc.firstColumn = shapeslloc.lastColumn;
707         throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found EOF while scanning string." ) );
710 <INITIAL>"(\""[\n]? {
711         if( yyleng > 2 )
712                 {
713                         ++shapeslloc.lastLine;
714                         shapeslloc.lastColumn = 0;
715                 }
716         quoteDepth_ = 1;
717         BEGIN( PoorMansString );
719 <INITIAL>"\")" { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found closing poor man's quote outside string." ) ); }
720 <PoorMansString>"\")" {
721         yytext[ yyleng - 2 ] = '\0';
722         rinseString( );
723         --shapeslloc.firstColumn;
724         BEGIN( INITIAL );
725         return T_string;
728 <INITIAL>"\"{" {
729         while( ! dataStringChunks_.empty( ) )
730                 {
731                         delete dataStringChunks_.back( ).first;
732                         dataStringChunks_.pop_back( );
733                 }
734         dataStringTotalLength_ = 0;
735         BEGIN( DataStringHex );
737 <DataStringPlain,DataStringHex>[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; }
738 <DataStringPlain>[ -z]+ {
739         dataStringChunks_.push_back( std::pair< char *, size_t >( strdup( yytext ), yyleng ) );
740         dataStringTotalLength_ += yyleng;
742 <DataStringHex>[ \t]+ { }
743 <DataStringHex>(([A-F0-9]{2})|[a-z])+ {
744         char * res = new char[ yyleng + 1 ];
745         char * dst = res;
746         for( const char * src = yytext; *src != '\0'; ++dst )
747                 {
748                         if( 'a' <= *src && *src <= 'z' )
749                                 {
750                                         switch( *src )
751                                                 {
752                                                 case 'n':
753                                                         *dst = '\n';
754                                                         break;
755                                                 case 't':
756                                                         *dst = '\t';
757                                                         break;
758                                                 default:
759                                                         *dst = '\0';
760                                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( std::string( "Invalid character name in escape mode: " ) + *src ) ) );
761                                                 }
762                                         src += 1;
763                                 }
764                         else
765                                 {
766                                         *dst = shapes_hexToChar( src[0], src[1] );
767                                          src += 2;
768                                 }
769                 }
770         dataStringChunks_.push_back( std::pair< char *, size_t >( res, dst - res ) );
771         dataStringTotalLength_ += dst - res;
773 <DataStringHex>[{] { BEGIN( DataStringPlain ); }
774 <DataStringPlain>[}] { BEGIN( DataStringHex ); }
775 <DataStringHex>[}] {
776         concatenateDataString( );
777         BEGIN( INITIAL );
778         return T_string;
780 <DataStringPlain,DataStringHex>. {
781         throw Exceptions::ScannerError( shapeslloc, strrefdup( "Stray character in \"{...} string." ) );
784 <Incl>[^ \t\n]+ {
785         if( searchContext_->insidePrivateNamespace( ) ){
786                 /* Including files from within a private namespace is forbidden to ensure that it will be possible to enter new namespaces
787                  * in the included file.
788                  * Report error, but still do the inclusion to avoid introducing additional errors.
789                  */
790                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
791         }
792         currentNeedFile = yytext;
793         currentNeedPushCount = 0;
794         currentNeedIsNeed = false;
795         currentNeedHasNamespace = false;
796         BEGIN( InclFrom );
799 <Needs>[^ \t\n]+".shext" {
800         yytext[ yyleng - 6 ] = '\0'; /* Drop the filename suffix. */
801         if( searchContext_->insidePrivateNamespace( ) ){
802                 /* See comment for <Incl>.
803                  */
804                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
805         }
806         if( bracketDepth_ > 0 ){
807                 /* Report error, but still do the inclusion to avoid introducing additional errors.
808                  */
809                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "##needs is only allowed in the global scope." ) ) );
810         }
812         currentNeedFile = yytext;
813         currentNeedPushCount = 0;
814         currentNeedIsNeed = true;
815         currentNeedHasNamespace = false;
816         BEGIN( InclFrom );
818 <Needs>{NonEmptyNamespacePath} {
819         setNamespace( yytext );
820         if( searchContext_->insidePrivateNamespace( ) ){
821                 /* See comment for <Incl>.
822                  */
823                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
824         }
825         if( bracketDepth_ > 0 ){
826                 /* Report error, but still do the inclusion to avoid introducing additional errors.
827                  */
828                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "##needs is only allowed in the global scope." ) ) );
829         }
831         currentNeedPushCount = 0;
832         currentNeedIsNeed = true;
833         currentNeedHasNamespace = true;
834         currentNeedFile = "";
835         BEGIN( InclOptFile );
837 <Needs>"/"[ \t]* {
838         namespace_ = Ast::NamespaceReference( Ast::NamespaceReference::RELATIVE, Ast::THE_EMPTY_NAMESPACE_PATH );
839         if( searchContext_->insidePrivateNamespace( ) ){
840                 /* See comment for <Incl>.
841                  */
842                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
843         }
844         if( bracketDepth_ > 0 ){
845                 /* Report error, but still do the inclusion to avoid introducing additional errors.
846                  */
847                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "##needs is only allowed in the global scope." ) ) );
848         }
850         currentNeedPushCount = 0;
851         currentNeedIsNeed = true;
852         currentNeedHasNamespace = true;
853         currentNeedFile = "";
854         BEGIN( InclFile );
856 <Needs>. {
857         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected namespace name or filename with suffix \".shext\"." ) ) );
858         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
861 <InclOptFile>[ \t]+ { }
862 <InclOptFile>[\n] { doInclusion( ); }
863 <InclOptFile>"/"[ \t]* { BEGIN( InclFile ); }
864 <InclOptFile>":"[ \t]+ { BEGIN( InclPath ); }
865 <InclOptFile>":". { throw Exceptions::ScannerError( shapeslloc, strrefdup( "The \":\" must be followed by whitespace." ) ); }
866 <InclOptFile>. { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Expected \"/\" or \":\"." ) ); }
868 <InclFile>[^ \t\n]+ { currentNeedFile = yytext; BEGIN( InclFrom ); }
869 <InclFile>.|[n] { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Expected filename base after \"/\"." ) ); }
871 <InclFrom>[ \t]+ { }
872 <InclFrom>[\n] { doInclusion( ); }
873 <InclFrom>":"[ \t]+ { BEGIN( InclPath ); }
874 <InclFrom>":". { throw Exceptions::ScannerError( shapeslloc, strrefdup( "The \":\" must be followed by whitespace." ) ); }
875 <InclFrom>. { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Expected \":\"." ) ); }
877 <InclPath>.+ {
878         push_frontNeedPath( yytext );
879         ++currentNeedPushCount;
881 <InclPath>[\n] {
882         if( currentNeedPushCount == 0 )
883                 {
884                         throw Exceptions::ScannerError( shapeslloc, strrefdup( "Missing path after \":\"." ) );
885                 }
886         doInclusion( );
889 <Echo>.* {
890         std::cerr << yytext << std::endl ;
891         BEGIN( INITIAL );
894 <Author>.* {
895         if( ! stateStack_.empty( ) )
896                 {
897                         Kernel::theDocInfo.addExtensionAuthorString( shapeslloc.file_->name( ) + std::string( " by " ) + yytext );
898                 }
899         else
900                 {
901                         if( ! Kernel::theDocInfo.addInfo( "Author", SimplePDF::newString( yytext ) ) )
902                                 {
903                                         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Multiply specified ##author." ) ) );
904                                 }
905                 }
906         BEGIN( INITIAL );
909 <Push>{NonEmptyNamespacePath} {
910         setNamespace( yytext );
911         if( namespace_.base( ) != Ast::NamespaceReference::RELATIVE ){
912                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Pushed namespace path must be relative." ) ) );
913         }else if( searchContext_->insidePrivateNamespace( ) ){
914                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Cannot push inside private namespace." ) ) );
915         }else{
916                 searchContextStack_.push( searchContext_ );
917                 Ast::NamespacePath * newNamespacePrefixMem = new Ast::NamespacePath( *searchContext_->lexicalPath( ) );
918                 for( Shapes::Ast::NamespacePath::const_iterator i = namespace_.path( ).begin( ); i != namespace_.path( ).end( ); ++i ){
919                         newNamespacePrefixMem->push_back( strdup( *i ) );
920                 }
921                 RefCountPtr< const Ast::NamespacePath > newNamespacePrefix( newNamespacePrefixMem );
922                 RefCountPtr< const char > privateName( Ast::SearchContext::makePrivateName( uniqueNamespaceNumber_ ) );
923                 ++uniqueNamespaceNumber_;
924                 searchContext_ = RefCountPtr< const Ast::SearchContext >( new Ast::SearchContext( newNamespacePrefix, searchContext_->encapsulationPath( ), searchContext_->lookinStack( ), privateName ) );
925         }
926         BEGIN( INITIAL );
927         return T_namespaceSpecial;
929 <Push>{Encapsulation} {
930         if( searchContext_->insidePrivateNamespace( ) ){
931                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Cannot push inside private namespace." ) ) );
932         }else{
933                 searchContextStack_.push( searchContext_ );
934                 RefCountPtr< const char > encapsulationName( newEncapsulationName( ) );
935                 RefCountPtr< const char > privateName( newPrivateName( ) );
936                 Ast::NamespacePath * newNamespacePrefixMem = new Ast::NamespacePath( *searchContext_->lexicalPath( ) );
937                 newNamespacePrefixMem->push_back( strdup( encapsulationName.getPtr( ) ) );
938                 RefCountPtr< const Ast::NamespacePath > newNamespacePrefix( newNamespacePrefixMem );
939                 searchContext_ = RefCountPtr< const Ast::SearchContext >( new Ast::SearchContext( newNamespacePrefix, newNamespacePrefix, searchContext_->lookinStack( ), privateName ) );
940         }
941         BEGIN( INITIAL );
942         return T_namespaceSpecial;
944 <Push>"-" {
945         if( searchContext_->insidePrivateNamespace( ) ){
946                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Cannot push inside private namespace." ) ) );
947         }else{
948                 searchContextStack_.push( searchContext_ );
949                 Ast::NamespacePath * newNamespacePrefixMem = new Ast::NamespacePath( *searchContext_->lexicalPath( ) );
950                 newNamespacePrefixMem->push_back( strdup( searchContext_->privateName( ).getPtr( ) ) );
951                 RefCountPtr< const Ast::NamespacePath > newNamespacePrefix( newNamespacePrefixMem );
952                 searchContext_ = RefCountPtr< const Ast::SearchContext >( new Ast::SearchContext( newNamespacePrefix, searchContext_->encapsulationPath( ), searchContext_->lookinStack( ), RefCountPtr< const char >( NullPtr< const char >( ) ) ) );
953         }
954         BEGIN( INITIAL );
955         return T_namespaceSpecial;
957 <Push>. {
958         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected namespace name or \"-\"." ) ) );
959         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
962 <Pop>{NonEmptyNamespacePath} {
963         setNamespace( yytext );
964         RefCountPtr< const Ast::NamespacePath > lexicalPath = searchContext_->lexicalPath( );
965         if( namespace_.base( ) != Ast::NamespaceReference::RELATIVE ){
966                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Popped namespace path must be relative." ) ) );
967         }else if( lexicalPath->size( ) < namespace_.path( ).size( ) ){
968                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Popping more levels than current depth of namespace stack." ) ) );
969         }else if( lexicalPath->size( ) == namespaceLimits_.top( ) ){
970                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to pop externally defined namespace stack." ) ) );
971         }else if( searchContext_->insidePrivateNamespace( ) ){
972                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Mismatched pop of named namespace; expected pop of private namespace." ) ) );
973         }else if( searchContext_->insideEncapsulationNamespace( ) ){
974                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Mismatched pop of named namespace; expected pop of encapsulation namespace." ) ) );
975         }else{
976                 bool match = true;
977                 Ast::NamespacePath::const_reverse_iterator j = lexicalPath->rbegin( );
978                 for( Shapes::Ast::NamespacePath::const_reverse_iterator i = namespace_.path( ).rbegin( ); i != namespace_.path( ).rend( ); ++i, ++j ){
979                         if( strcmp( *j, *i ) != 0 ){
980                                 match = false;
981                                 break;
982                         }
983                 }
984                 if( ! match ){
985                         std::stack< const char * > revStack;
986                         Ast::NamespacePath::const_reverse_iterator j = lexicalPath->rbegin( );
987                         for( size_t i = 0; i < namespace_.path( ).size( ); ++i, ++j ){
988                                 revStack.push( *j );
989                         }
990                         std::ostringstream oss;
991                         oss << "Namespace stack mismatched pop; expected " ;
992                         bool first = true;
993                         while( ! revStack.empty( ) ){
994                                 if( first ){
995                                         first = false;
996                                 }else{
997                                         oss << Interaction::NAMESPACE_SEPARATOR ;
998                                 }
999                                 oss << revStack.top( ) ;
1000                                 revStack.pop( );
1001                         }
1002                         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( oss ) ) );
1003                 }
1004                 size_t expectedDepth = lexicalPath->size( ) - namespace_.path( ).size( );
1005                 searchContext_ = searchContextStack_.top( );
1006                 searchContextStack_.pop( );
1007                 if( searchContext_->lexicalPath( )->size( ) != expectedDepth ){
1008                         std::ostringstream oss;
1009                         oss << "Expected pop of " << ( lexicalPath->size( ) - searchContext_->lexicalPath( )->size( ) ) << " namespace levels, not " << namespace_.path( ).size( ) << "." ;
1010                         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( oss ) ) );
1011                 }
1012         }
1013         BEGIN( INITIAL );
1014         return T_namespaceSpecial;
1016 <Pop>{Encapsulation} {
1017         RefCountPtr< const Ast::NamespacePath > lexicalPath = searchContext_->lexicalPath( );
1018         if( lexicalPath->size( ) == namespaceLimits_.top( ) ){
1019                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to pop externally defined namespace stack." ) ) );
1020         }else if( searchContext_->insidePrivateNamespace( ) ){
1021                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Mismatched pop of encapsulation namespace; expected pop of private namespace." ) ) );
1022         }else if( ! searchContext_->insideEncapsulationNamespace( ) ){
1023                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Mismatched pop of encapsulation namespace; expected pop of named namespace." ) ) );
1024         }else{
1025                 searchContext_ = searchContextStack_.top( );
1026                 searchContextStack_.pop( );
1027         }
1028         BEGIN( INITIAL );
1029         return T_namespaceSpecial;
1031 <Pop>"-" {
1032         RefCountPtr< const Ast::NamespacePath > lexicalPath = searchContext_->lexicalPath( );
1033         if( lexicalPath->size( ) == namespaceLimits_.top( ) ){
1034                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to pop externally defined namespace stack." ) ) );
1035         }else if( searchContext_->insideEncapsulationNamespace( ) ){
1036                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Mismatched pop of private namespace; expected pop of encapsulation namespace." ) ) );
1037         }else if( ! searchContext_->insidePrivateNamespace( ) ){
1038                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Mismatched pop of private namespace; expected pop of named namespace." ) ) );
1039         }else{
1040                 searchContext_ = searchContextStack_.top( );
1041                 searchContextStack_.pop( );
1042         }
1043         BEGIN( INITIAL );
1044         return T_namespaceSpecial;
1046 <Pop>. {
1047         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected namespace name or \"-\"." ) ) );
1048         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
1051 <Lookin>{NonEmptyNamespacePath} {
1052         setNamespace( yytext );
1053         if( namespace_.path( ).empty( ) ){
1054                 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Malformed namespace path." ) ) );
1055         }else{
1056                 RefCountPtr< const Ast::LookinPathStack > newLookinStack( new Ast::LookinPathStack( resolvedNamespace( ), searchContext_->lookinStack( ) ) );
1057                 searchContext_ = RefCountPtr< const Ast::SearchContext >( new Ast::SearchContext( searchContext_->lexicalPath( ), searchContext_->encapsulationPath( ), newLookinStack, searchContext_->privateName( ) ) );
1058         }
1059         BEGIN( INITIAL );
1060         return T_namespaceSpecial;
1062 <Lookin>. {
1063         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected namespace path." ) ) );
1064         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
1067 <TreeNamespaceAlias>{SimpleIdentifier} {
1068         treeNamespaceAlias_ = placedIdentifier( yytext );
1069         aliasLoc_ = shapeslloc;
1070         BEGIN( TreeNamespaceEqual );
1072 <TreeNamespaceAlias>. {
1073         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected namespace identifier." ) ) );
1074         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
1076 <TreeNamespaceEqual>[ \t]*"="[ \t]* { BEGIN( TreeNamespaceOriginal ); }
1077 <TreeNamespaceEqual>. {
1078         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected '='." ) ) );
1079         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
1081 <TreeNamespaceOriginal>{NonEmptyNamespacePath} {
1082         setNamespace( yytext );
1083         shapeslval.node = new Ast::DefineAlias( aliasLoc_, shapeslloc, treeNamespaceAlias_, namespace_ );
1084         BEGIN( INITIAL );
1085         return T_alias;
1087 <TreeNamespaceOriginal>. {
1088         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected namespace path." ) ) );
1089         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
1092 <<EOF>> {
1093   /* It seems like YY_USER_ACTION is not invoked at EOF, so we do this manually,
1094    * however ignornig yyleng (which has the value 1).
1095    */
1096   shapeslloc.firstColumn = shapeslloc.lastColumn;
1098   while( true ){
1100     if( stateStack_.size( ) > stateStackSizeStack_.top( ) ){
1101       yy_delete_buffer( YY_CURRENT_BUFFER );
1102       yy_switch_to_buffer( stateStack_.top( ) );
1103       stateStack_.pop( );
1104       shapeslloc.swap( locStack_.top( ) );
1105       delete locStack_.top( );
1106       locStack_.pop( );
1107       for( size_t tmp = pathCountStack_.top( ); tmp > 0; --tmp )
1108         {
1109           pop_frontNeedPath( );
1110         }
1111       pathCountStack_.pop( );
1112       namespaceLimits_.pop( );
1113       searchContext_ = searchContextStack_.top( );
1114       searchContextStack_.pop( );
1115       goto done;
1116     }
1118     while( loadStack_.size( ) > loadStackSizeStack_.top( ) )
1119       {
1120         const Ast::FileID *fileID = loadStack_.topFileID( );
1121         RefCountPtr< const Ast::NamespacePath > lexicalPath = loadStack_.topNamespace( );
1122         loadStack_.pop( );
1123         NeededFile neededFile( lexicalPath, fileID );
1124         if( neededFiles_.find( neededFile ) != neededFiles_.end( ) )
1125           continue;
1126         neededFiles_.insert( neededFile );
1127         std::ifstream * iFile = new std::ifstream( fileID->name( ) );
1128         if( ! iFile->good( ) )
1129           {
1130             delete iFile;
1131             throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( fileID->name( ) ), NULL, NULL );
1132           }
1133         yy_delete_buffer( YY_CURRENT_BUFFER );
1134         yy_switch_to_buffer( yy_create_buffer( iFile, YY_BUF_SIZE ) );
1135         shapeslloc = Ast::SourceLocation( fileID );
1136         searchContext_ = RefCountPtr< const Ast::SearchContext >( new Ast::SearchContext( lexicalPath, Ast::THE_EMPTY_NAMESPACE_PATH, RefCountPtr< const Ast::LookinPathStack >( NullPtr< const Ast::LookinPathStack >( ) ), newPrivateName( ) ) );
1137         goto done;
1138       }
1140     if( loadStackSizeStack_.size( ) == 1 )
1141       break; /* Both size stacks have a zero as the bottom element, so both stateStack_ and loadStack_ arete be empty. */
1143     loadStackSizeStack_.pop( );
1144     stateStackSizeStack_.pop( );
1146    }
1148   if( ! yyinQueue_.empty( ) )
1149     {
1150       yy_delete_buffer( YY_CURRENT_BUFFER );
1151       yy_switch_to_buffer( yy_create_buffer( yyinQueue_.front( ).first, YY_BUF_SIZE ) );
1152       shapeslloc = Ast::SourceLocation( yyinQueue_.front( ).second );
1153       searchContext_ = RefCountPtr< const Ast::SearchContext >( new Ast::SearchContext( Ast::THE_EMPTY_NAMESPACE_PATH, Ast::THE_EMPTY_NAMESPACE_PATH, RefCountPtr< const Ast::LookinPathStack >( NullPtr< const Ast::LookinPathStack >( ) ), newPrivateName( ) ) );
1154       yyinQueue_.pop_front( );
1155       if( inPrelude_ )
1156         {
1157           inPrelude_ = false;
1158           if( interactive_ ){
1159             return T_interactiveMark;
1160           }else{
1161             return T_preludesep;
1162           }
1163         }
1164     }
1165   else if( inPrelude_ )
1166     {
1167       inPrelude_ = false;
1168       return T_preludesep;
1169     }
1170   else
1171     {
1172       return T_EOF;
1173     }
1175   done:
1176     ;
1179 {NonEmptyNamespacePath}{NamespaceSep} {
1180         setNamespace( yytext );
1181         BEGIN( NamespacePrefix );
1182         namespace_yyleng_ = yyleng;
1183         more( );
1185 {NamespaceSep} {
1186         setNamespace( yytext );
1187         BEGIN( NamespacePrefix );
1188         namespace_yyleng_ = yyleng;
1189         more( );
1191 {Encapsulation} {
1192         setNamespace( yytext );
1193         BEGIN( NamespacePrefix );
1194         namespace_yyleng_ = yyleng;
1195         more( );
1198 "TeX" {
1199         shapeslval.ident = simpleIdentifier( yytext );
1200         return T_identifier_tex;
1202 {SimpleIdentifier} {
1203         shapeslval.ident = simpleIdentifier( yytext );
1204         return T_identifier_except_tex;
1206 "'"{SimpleIdentifier} {
1207         shapeslval.char_p = strdup( yytext + 1 );
1208         return T_symbol;
1210 <NamespacePrefix>{SimpleIdentifier} {
1211         shapeslval.ident = prependNamespace( yytext + namespace_yyleng_ );
1212         BEGIN( INITIAL );
1213         return T_pathed_identifier;
1216 {TypeMark}{SimpleIdentifier} {
1217         shapeslval.ident = simpleIdentifier( yytext + 2 ); /* The type mark is allways 2 bytes. */
1218         return T_typename;
1220 <NamespacePrefix>{TypeMark}{SimpleIdentifier} {
1221         shapeslval.ident = prependNamespace( yytext + namespace_yyleng_ + 2 ); /* The type mark is allways 2 bytes. */
1222         BEGIN( INITIAL );
1223         return T_typename;
1226 {DynamicMark}{SimpleIdentifier} {
1227         shapeslval.ident = simpleIdentifier( yytext + 1 );
1228         return T_dynamic_identifier;
1230 <NamespacePrefix>{DynamicMark}{SimpleIdentifier} {
1231         shapeslval.ident = prependNamespace( yytext + namespace_yyleng_ + 1 );
1232         BEGIN( INITIAL );
1233         return T_dynamic_identifier;
1236 {StateMark}{SimpleIdentifier} {
1237         const char * id = yytext;
1238         /* Depending on which state mark is used, we must skip different number of bytes. */
1239         if( *id == '#' )
1240                 {
1241                         id += 1;
1242                 }
1243         else /* The state mark is '•' */
1244                 {
1245                         id += 3;
1246                 }
1247         shapeslval.ident = simpleIdentifier( id );
1248         return T_state_identifier;
1250 <NamespacePrefix>{StateMark}{SimpleIdentifier} {
1251         char * id = yytext + namespace_yyleng_;
1252         /* Depending on which state mark is used, we must skip different number of bytes. */
1253         if( *id == '#' )
1254                 {
1255                         id += 1;
1256                 }
1257         else /* The state mark is '•' */
1258                 {
1259                         id += 3;
1260                 }
1261         shapeslval.ident = prependNamespace( id );
1262         BEGIN( INITIAL );
1263         return T_state_identifier;
1266 {DynamicMark}{StateMark}{SimpleIdentifier} {
1267         const char * id = yytext + 1; /* The dynamic mark is allways 1 byte. */
1268         /* Depending on which state mark is used, we must skip different number of bytes. */
1269         if( *id == '#' )
1270                 {
1271                         id += 1;
1272                 }
1273         else /* The state mark is '•' */
1274                 {
1275                         id += 3;
1276                 }
1277         shapeslval.ident = simpleIdentifier( id );
1278         return T_dynamic_state_identifier;
1280 <NamespacePrefix>{DynamicMark}{StateMark}{SimpleIdentifier} {
1281         char * id = yytext + namespace_yyleng_ + 1; /* The dynamic mark is allways 1 byte. */
1282         /* Depending on which state mark is used, we must skip different number of bytes. */
1283         if( *id == '#' )
1284                 {
1285                         id += 1;
1286                 }
1287         else /* The state mark is '•' */
1288                 {
1289                         id += 3;
1290                 }
1291         shapeslval.ident = prependNamespace( id );
1292         BEGIN( INITIAL );
1293         return T_dynamic_state_identifier;
1296 <NamespacePrefix>. {
1297         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected identifier following namespace path." ) ) );
1298         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
1301 . {
1302         Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( ( std::string( "Scanner found unrecognized token: " ) + yytext ).c_str( ) ) ) );
1303         BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
1307 /* The closing %% above marks the end of the Rules section and the beginning
1308  * of the User Subroutines section. All text from here to the end of the
1309  * file is copied verbatim to the end of the generated lex.pdf.c file.
1310  * This section is where you put definitions of helper functions.
1311  */
1313 double
1314 shapes_strtod( char * str, char ** end )
1316         char termTmp;
1317         char * term = str;
1318         for( ; *term != '\0'; ++term )
1319                 {
1320                         switch( *term )
1321                                 {
1322                                 case '0':
1323                                 case '1':
1324                                 case '2':
1325                                 case '3':
1326                                 case '4':
1327                                 case '5':
1328                                 case '6':
1329                                 case '7':
1330                                 case '8':
1331                                 case '9':
1332                                 case '.':
1333                                         continue;
1334                                 case '~':
1335                                         *term = '-';
1336                                         continue;
1337                                 case '*':
1338                                         /* We replace the "*^" by something in the notation of strtod */
1339                                         *term = 'e';
1340                                         if( *(term+2) == '~' )
1341                                                 {
1342                                                         *(term+1) = '-';
1343                                                         *(term+2) = '0';
1344                                                         term += 3;
1345                                                 }
1346                                         else
1347                                                 {
1348                                                         *(term+1) = '0';
1349                                                         term += 2;
1350                                                 }
1351                                         continue;
1352                                 }
1353                         break;
1354                 }
1355         termTmp = *term;
1356         *term = '\0';
1357         double val = strtod( str, end );
1358         *term = termTmp;
1359         return val;
1362 char
1363 shapes_hexToChar( char c1, char c2 )
1365         return
1366                 static_cast< char >
1367                 ( 16 * ( ( c1 < 'A' ) ? static_cast< unsigned char >( c1 - '0' ) : static_cast< unsigned char >( c1 - 'A' + 10 ) )
1368                         +
1369                         ( ( c2 < 'A' ) ? static_cast< unsigned char >( c2 - '0' ) : static_cast< unsigned char >( c2 - 'A' + 10 ) ) );
1372 void
1373 ShapesScanner::start( )
1375         static const Ast::FileID * START_NULL_FILE = Ast::FileID::build_internal( "<start-null>" );
1376         inPrelude_ = true;
1377         if( ! interactive_ )
1378                 {
1379                         loader_.pushPreludeFiles( & loadStack_ );
1380                 }
1381         std::istream * iFile = new std::istringstream( "" ); /* This will result in EOF immediately, and then we turn to the first real file. */
1382         yy_switch_to_buffer( yy_create_buffer( iFile, YY_BUF_SIZE ) );
1383         shapeslloc.file_ = START_NULL_FILE;
1386 void
1387 ShapesScanner::endOfLine( )
1389         shapeslloc.firstLine = shapeslloc.lastLine + 1;
1390         shapeslloc.lastLine = shapeslloc.firstLine;
1391         shapeslloc.lastColumn = 0;
1394 void
1395 ShapesScanner::doInclusion( )
1397         const Ast::FileID * fileID = NULL;
1398         std::ifstream * iFile = NULL;
1399         RefCountPtr< const Ast::NamespacePath > lexicalPath = searchContext_->lexicalPath( );
1401         if( ! currentNeedFile.empty( ) ){
1403                 if( currentNeedHasNamespace ) {
1405                         if( currentNeedIsNeed ) {
1406                                 lexicalPath = resolvedNamespace( );
1407                                 fileID = loader_.resolveSingleFile( *lexicalPath, currentNeedFile + ".shext", shapeslloc );
1408                         }else{
1409                                 throw Exceptions::InternalError( shapeslloc, "Unexpected namespace form of unconditional file inclusion." );
1410                         }
1412                 }else{
1414                 std::string path;
1415                         if( currentNeedIsNeed )
1416                                 path = searchFile( currentNeedFile + ".shext" );
1417                         else
1418                                 path = searchFile( currentNeedFile + ".shape" );
1420                         struct stat theStat;
1421                         if( stat( path.c_str( ), & theStat ) != 0 )
1422                                 {
1423                                         throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( path.c_str( ) ), 0, 0, Exceptions::FileReadOpenError::STAT );
1424                                 }
1425                         fileID = Ast::FileID::build_stat( theStat, path );
1427                 }
1429                 if( currentNeedIsNeed )
1430                         {
1431                                 NeededFile neededFile( lexicalPath, fileID );
1432                                 if( neededFiles_.find( neededFile ) != neededFiles_.end( ) )
1433                                         {
1434                                                 shapeslloc.firstLine = shapeslloc.lastLine + 1;
1435                                                 shapeslloc.lastLine = shapeslloc.firstLine;
1436                                                 shapeslloc.lastColumn = 0;
1437                                                 BEGIN( INITIAL );
1438                                                 return;
1439                                         }
1440                                 neededFiles_.insert( neededFile );
1441                         }
1443                 iFile = new std::ifstream( fileID->name( ) );
1444                 if( ! iFile->good( ) )
1445                         {
1446                                 delete iFile;
1447                                 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( fileID->name( ) ), 0, 0 );
1448                         }
1450         }else{
1452                 loadStackSizeStack_.push( loadStack_.size( ) );
1453                 stateStackSizeStack_.push( stateStack_.size( ) + 1 ); /* 1 for the current state which is about to be pushed. */
1454                 loader_.pushNamespaceFiles( *resolvedNamespace( ), & loadStack_ );
1455                 while( loadStack_.size( ) > loadStackSizeStack_.top( ) ){
1456                         fileID = loadStack_.topFileID( );
1457                         lexicalPath = loadStack_.topNamespace( );
1458                         loadStack_.pop( );
1459                         NeededFile neededFile( lexicalPath, fileID );
1460                         if( neededFiles_.find( neededFile ) != neededFiles_.end( ) )
1461                                 continue;
1462                         neededFiles_.insert( neededFile );
1463                         iFile = new std::ifstream( fileID->name( ) );
1464                         if( ! iFile->good( ) )
1465                                 {
1466                                         delete iFile;
1467                                         throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( fileID->name( ) ), NULL, NULL );
1468                                 }
1469                         break;
1470                 }
1471                 if( iFile == NULL ){
1472                         /* All of the files pushed to the loadStack were already needed. */
1473                         loadStackSizeStack_.pop( );
1474                         stateStackSizeStack_.pop( );
1475                         shapeslloc.firstLine = shapeslloc.lastLine + 1;
1476                         shapeslloc.lastLine = shapeslloc.firstLine;
1477                         shapeslloc.lastColumn = 0;
1478                         BEGIN( INITIAL );
1479                         return;
1480                 }
1481         }
1483         shapeslloc.firstLine = shapeslloc.lastLine + 1;
1484         shapeslloc.lastLine = shapeslloc.firstLine;
1485         shapeslloc.lastColumn = 0;
1487   Ast::SourceLocation * locPtr = new Ast::SourceLocation( fileID );
1488   locPtr->swap( & shapeslloc );
1489   locStack_.push( locPtr );
1490         stateStack_.push( YY_CURRENT_BUFFER );
1491         yy_switch_to_buffer( yy_create_buffer( iFile, YY_BUF_SIZE ) );
1492         pathCountStack_.push( currentNeedPushCount );
1493         namespaceLimits_.push( searchContext_->lexicalPath( )->size( ) );
1495         /* Prevent look-in stack to be carried over to the new file by setting up a new search context.
1496          */
1497         searchContextStack_.push( searchContext_ );
1498         RefCountPtr< const Shapes::Ast::NamespacePath > encapsulationPath( ( ( ! currentNeedHasNamespace ) || namespace_.base( ) != Ast::NamespaceReference::ABSOLUTE ) ? searchContext_->encapsulationPath( ) : Ast::THE_EMPTY_NAMESPACE_PATH );
1499         searchContext_ = RefCountPtr< const Ast::SearchContext >( new Ast::SearchContext( lexicalPath, encapsulationPath, RefCountPtr< const Ast::LookinPathStack >( NullPtr< const Ast::LookinPathStack >( ) ), newPrivateName( ) ) );
1501         BEGIN( INITIAL );
1504 void
1505 ShapesScanner::queueStream( std::istream * is, const Ast::FileID * yyinFile )
1507         yyinQueue_.push_back( std::pair< std::istream * , const Ast::FileID * >( is, yyinFile ) );