1 /* This file is part of Shapes.
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
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.
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/>.
16 * Copyright 2008, 2010, 2013, 2014 Henrik Tidefelt
23 #include "shapesscanner.h"
24 #include "shapesvalue.h"
25 #include "shapestypes.h"
29 #include "shapesexceptions.h"
30 #include "texlabelmanager.h"
32 #include "exitcodes.h"
34 using namespace Shapes;
36 #include "shapesparser.hh"
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 );
56 LexDirPrefix ^[ \t]*"##"
57 Float [~]?[0-9]+([.][0-9]*)?("*^"[~]?[0-9]+)?
58 Greek "α"|"β"|"γ"|"Γ"|"δ"|"Δ"|"ε"|"ζ"|"η"|"Θ"|"ι"|"κ"|"λ"|"Λ"|"μ"|"ν"|"χ"|"Ξ"|"π"|"Π"|"ρ"|"σ"|"Σ"|"τ"|"ϕ"|"ω"|"Ω"
59 LowerCaseLetter [a-z_?]
61 Letter {LowerCaseLetter}|{UpperCaseLetter}|{Greek}
62 SimpleIdentifier {Letter}({Letter}|[0-9])*
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])
76 %option prefix="shapes"
77 %option yyclass="ShapesScanner"
79 %x DiscardRestOfLineAndBEGIN_INITIAL
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 ); }
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>.* {
136 <DiscardRestOfLineAndBEGIN_INITIAL>[\n] {
141 <LaTeXOption>[^,\n]+ { Kernel::theTeXLabelManager.addDocumentOption( shapeslloc, yytext ); }
147 <LaTeXClass>.+ { Kernel::theTeXLabelManager.setDocumentClass( shapeslloc, yytext ); }
153 <LaTeXPreamble>.* { Kernel::theTeXLabelManager.addPreambleLine( shapeslloc, yytext ); }
154 <LaTeXPreamble>[\n] {
159 <LaTeXDocumentTop>.* { Kernel::theTeXLabelManager.addDocumentTopLine( shapeslloc, yytext ); }
160 <LaTeXDocumentTop>[\n] {
167 long int s = strtol( yytext, & end, 10 );
170 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Failed to scan integer." ) ) );
176 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Random nuber generator seed must not be negative." ) ) );
189 <NewUnitName>{SimpleIdentifier} {
190 newUnitName_ = strdup( yytext );
191 BEGIN( NewUnitEqual );
194 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected identifier." ) ) );
195 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
197 <NewUnitEqual>[ \t]*"="[ \t]* { BEGIN( NewUnitValue ); }
199 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected '='." ) ) );
200 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
202 <NewUnitValue>{Float}{SimpleIdentifier} {
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( ) )
210 double newUnitValue = val * i->second;
212 if( ( i = lengthUnits_.find( newUnitName_ ) ) != lengthUnits_.end( ) )
214 if( i->second != newUnitValue )
216 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
219 else if( ( i = angleUnits_.find( newUnitName_ ) ) != angleUnits_.end( ) )
221 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
225 lengthUnits_[ newUnitName_ ] = newUnitValue;
228 else if( ( i = angleUnits_.find( end ) ) != angleUnits_.end( ) )
230 double newUnitValue = val * i->second;
232 if( ( i = angleUnits_.find( newUnitName_ ) ) != angleUnits_.end( ) )
234 if( i->second != newUnitValue )
236 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
239 else if( ( i = lengthUnits_.find( newUnitName_ ) ) != lengthUnits_.end( ) )
241 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
245 angleUnits_[ newUnitName_ ] = newUnitValue;
250 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknownUnit( shapeslloc, strrefdup( end ) ) );
255 <NewUnitValue>{Float}"°" {
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( ) )
266 if( i->second != newUnitValue )
268 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
271 else if( ( i = lengthUnits_.find( newUnitName_ ) ) != lengthUnits_.end( ) )
273 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName_ ) ) );
277 angleUnits_[ newUnitName_ ] = newUnitValue;
283 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected a length." ) ) );
284 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
290 shapeslval.floatVal = shapes_strtod( yytext, & end );
297 shapeslval.floatVal = M_PI / 180 * shapes_strtod( yytext, & end );
303 shapeslval.floatVal = M_PI / 200 * shapes_strtod( yytext, & end );
309 shapeslval.floatVal = shapes_strtod( yytext, & end );
315 shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 0.1 * 72 / 2.54 );
321 shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 72 / 2.54 );
327 shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 100 * 72 / 2.54 );
333 shapeslval.floatVal = shapes_strtod( yytext, & end ) * 72;
337 {Float}{SimpleIdentifier} {
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( ) )
345 shapeslval.floatVal = val * i->second;
348 if( ( i = angleUnits_.find( end ) ) != angleUnits_.end( ) )
350 shapeslval.floatVal = val * i->second;
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. */
360 double val = shapes_strtod( yytext, & end );
361 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST );
362 return T_speciallength;
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;
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;
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;
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;
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;
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;
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;
416 double val = shapes_strtod( yytext, & end );
417 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_NOINFLEX );
418 return T_speciallength;
424 shapeslval.floatVal = shapes_strtod( yytext, & end );
429 const char * src = yytext + 1;
430 bool negative = false;
437 int absval = strtol( src, & end, 10 );
440 shapeslval.intVal = - absval;
444 shapeslval.intVal = absval;
451 shapeslval.intVal = strtol( yytext + 3, & end, 16 );
457 shapeslval.intVal = strtol( yytext + 3, & end, 2 );
462 const char * src = yytext + 2;
465 shapeslval.uintVal = *src;
469 switch( 0xF0 & *src )
472 shapeslval.uintVal = *src & 0x0F;
473 shapeslval.uintVal *= 0x40;
475 shapeslval.uintVal += *src & 0x3F;
476 shapeslval.uintVal *= 0x40;
478 shapeslval.uintVal += *src & 0x3F;
481 shapeslval.uintVal = *src & 0x07;
482 shapeslval.uintVal *= 0x40;
484 shapeslval.uintVal += *src & 0x3F;
485 shapeslval.uintVal *= 0x40;
487 shapeslval.uintVal += *src & 0x3F;
488 shapeslval.uintVal *= 0x40;
490 shapeslval.uintVal += *src & 0x3F;
493 shapeslval.uintVal = *src & 0x1F;
494 shapeslval.uintVal *= 0x40;
496 shapeslval.uintVal += *src & 0x3F;
503 "\'&U+"[0-9A-F]+";" {
505 int absval = strtol( yytext + 4, & end, 16 );
508 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Malformed hexadecimal number in character literal." ) ) );
510 shapeslval.uintVal = absval;
514 "\'&G+"{SimpleIdentifier}";" {
515 yytext[ yyleng - 1 ] = '\0'; /* Cut away the terminating ';' */
516 shapeslval.uintVal = unicodeFromGlyphname( yytext + 4 );
521 shapeslval.floatVal = HUGE_VAL;
526 shapeslval.boolVal = true;
531 shapeslval.boolVal = false;
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]; }
572 namespaceLimits_.push( searchContext_->lexicalPath( )->size( ) );
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.
581 if( ! namespaceLimits_.empty( ) )
582 namespaceLimits_.pop( );
583 /* Likewise, we let the parser report the error in case of an unbalanced closing brace.
585 if( bracketDepth_ > 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; }
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.
605 shapeslval.placedIdent = placedIdentifier( yytext );
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__; }
640 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal use of reserved tab character." ) ) );
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( ); }
653 if( quoteDepth_ == 0 )
663 <Comment>[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; }
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).
668 shapeslloc.firstColumn = shapeslloc.lastColumn;
669 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found EOF while scanning comment." ) );
675 ++shapeslloc.lastLine;
676 shapeslloc.lastColumn = 0;
681 <INITIAL>"´" { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found closing quote outside string." ) ); }
682 <String>"`" { ++quoteDepth_; more( ); }
685 if( quoteDepth_ == 0 )
687 yytext[ yyleng - 2 ] = '\0';
689 --shapeslloc.firstColumn;
696 yymore( ); /* The purpose of this line is only to let flex know that we use yy_more_flag */
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).
706 shapeslloc.firstColumn = shapeslloc.lastColumn;
707 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found EOF while scanning string." ) );
710 <INITIAL>"(\""[\n]? {
713 ++shapeslloc.lastLine;
714 shapeslloc.lastColumn = 0;
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';
723 --shapeslloc.firstColumn;
729 while( ! dataStringChunks_.empty( ) )
731 delete dataStringChunks_.back( ).first;
732 dataStringChunks_.pop_back( );
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 ];
746 for( const char * src = yytext; *src != '\0'; ++dst )
748 if( 'a' <= *src && *src <= 'z' )
760 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( std::string( "Invalid character name in escape mode: " ) + *src ) ) );
766 *dst = shapes_hexToChar( src[0], src[1] );
770 dataStringChunks_.push_back( std::pair< char *, size_t >( res, dst - res ) );
771 dataStringTotalLength_ += dst - res;
773 <DataStringHex>[{] { BEGIN( DataStringPlain ); }
774 <DataStringPlain>[}] { BEGIN( DataStringHex ); }
776 concatenateDataString( );
780 <DataStringPlain,DataStringHex>. {
781 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Stray character in \"{...} string." ) );
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.
790 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
792 currentNeedFile = yytext;
793 currentNeedPushCount = 0;
794 currentNeedIsNeed = false;
795 currentNeedHasNamespace = false;
799 <Needs>[^ \t\n]+".shext" {
800 yytext[ yyleng - 6 ] = '\0'; /* Drop the filename suffix. */
801 if( searchContext_->insidePrivateNamespace( ) ){
802 /* See comment for <Incl>.
804 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
806 if( bracketDepth_ > 0 ){
807 /* Report error, but still do the inclusion to avoid introducing additional errors.
809 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "##needs is only allowed in the global scope." ) ) );
812 currentNeedFile = yytext;
813 currentNeedPushCount = 0;
814 currentNeedIsNeed = true;
815 currentNeedHasNamespace = false;
818 <Needs>{NonEmptyNamespacePath} {
819 setNamespace( yytext );
820 if( searchContext_->insidePrivateNamespace( ) ){
821 /* See comment for <Incl>.
823 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
825 if( bracketDepth_ > 0 ){
826 /* Report error, but still do the inclusion to avoid introducing additional errors.
828 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "##needs is only allowed in the global scope." ) ) );
831 currentNeedPushCount = 0;
832 currentNeedIsNeed = true;
833 currentNeedHasNamespace = true;
834 currentNeedFile = "";
835 BEGIN( InclOptFile );
838 namespace_ = Ast::NamespaceReference( Ast::NamespaceReference::RELATIVE, Ast::THE_EMPTY_NAMESPACE_PATH );
839 if( searchContext_->insidePrivateNamespace( ) ){
840 /* See comment for <Incl>.
842 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal to include files from within private namespace." ) ) );
844 if( bracketDepth_ > 0 ){
845 /* Report error, but still do the inclusion to avoid introducing additional errors.
847 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "##needs is only allowed in the global scope." ) ) );
850 currentNeedPushCount = 0;
851 currentNeedIsNeed = true;
852 currentNeedHasNamespace = true;
853 currentNeedFile = "";
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 \"/\"." ) ); }
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 \":\"." ) ); }
878 push_frontNeedPath( yytext );
879 ++currentNeedPushCount;
882 if( currentNeedPushCount == 0 )
884 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Missing path after \":\"." ) );
890 std::cerr << yytext << std::endl ;
895 if( ! stateStack_.empty( ) )
897 Kernel::theDocInfo.addExtensionAuthorString( shapeslloc.file_->name( ) + std::string( " by " ) + yytext );
901 if( ! Kernel::theDocInfo.addInfo( "Author", SimplePDF::newString( yytext ) ) )
903 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Multiply specified ##author." ) ) );
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." ) ) );
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 ) );
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 ) );
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." ) ) );
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 ) );
942 return T_namespaceSpecial;
945 if( searchContext_->insidePrivateNamespace( ) ){
946 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Cannot push inside private namespace." ) ) );
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 >( ) ) ) );
955 return T_namespaceSpecial;
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." ) ) );
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 ){
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 ){
990 std::ostringstream oss;
991 oss << "Namespace stack mismatched pop; expected " ;
993 while( ! revStack.empty( ) ){
997 oss << Interaction::NAMESPACE_SEPARATOR ;
999 oss << revStack.top( ) ;
1002 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( oss ) ) );
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 ) ) );
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." ) ) );
1025 searchContext_ = searchContextStack_.top( );
1026 searchContextStack_.pop( );
1029 return T_namespaceSpecial;
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." ) ) );
1040 searchContext_ = searchContextStack_.top( );
1041 searchContextStack_.pop( );
1044 return T_namespaceSpecial;
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." ) ) );
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( ) ) );
1060 return T_namespaceSpecial;
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_ );
1087 <TreeNamespaceOriginal>. {
1088 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected namespace path." ) ) );
1089 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
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).
1096 shapeslloc.firstColumn = shapeslloc.lastColumn;
1100 if( stateStack_.size( ) > stateStackSizeStack_.top( ) ){
1101 yy_delete_buffer( YY_CURRENT_BUFFER );
1102 yy_switch_to_buffer( stateStack_.top( ) );
1104 shapeslloc.swap( locStack_.top( ) );
1105 delete locStack_.top( );
1107 for( size_t tmp = pathCountStack_.top( ); tmp > 0; --tmp )
1109 pop_frontNeedPath( );
1111 pathCountStack_.pop( );
1112 namespaceLimits_.pop( );
1113 searchContext_ = searchContextStack_.top( );
1114 searchContextStack_.pop( );
1118 while( loadStack_.size( ) > loadStackSizeStack_.top( ) )
1120 const Ast::FileID *fileID = loadStack_.topFileID( );
1121 RefCountPtr< const Ast::NamespacePath > lexicalPath = loadStack_.topNamespace( );
1123 NeededFile neededFile( lexicalPath, fileID );
1124 if( neededFiles_.find( neededFile ) != neededFiles_.end( ) )
1126 neededFiles_.insert( neededFile );
1127 std::ifstream * iFile = new std::ifstream( fileID->name( ) );
1128 if( ! iFile->good( ) )
1131 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( fileID->name( ) ), NULL, NULL );
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( ) ) );
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( );
1148 if( ! yyinQueue_.empty( ) )
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( );
1159 return T_interactiveMark;
1161 return T_preludesep;
1165 else if( inPrelude_ )
1168 return T_preludesep;
1179 {NonEmptyNamespacePath}{NamespaceSep} {
1180 setNamespace( yytext );
1181 BEGIN( NamespacePrefix );
1182 namespace_yyleng_ = yyleng;
1186 setNamespace( yytext );
1187 BEGIN( NamespacePrefix );
1188 namespace_yyleng_ = yyleng;
1192 setNamespace( yytext );
1193 BEGIN( NamespacePrefix );
1194 namespace_yyleng_ = yyleng;
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 );
1210 <NamespacePrefix>{SimpleIdentifier} {
1211 shapeslval.ident = prependNamespace( yytext + namespace_yyleng_ );
1213 return T_pathed_identifier;
1216 {TypeMark}{SimpleIdentifier} {
1217 shapeslval.ident = simpleIdentifier( yytext + 2 ); /* The type mark is allways 2 bytes. */
1220 <NamespacePrefix>{TypeMark}{SimpleIdentifier} {
1221 shapeslval.ident = prependNamespace( yytext + namespace_yyleng_ + 2 ); /* The type mark is allways 2 bytes. */
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 );
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. */
1243 else /* The state mark is '•' */
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. */
1257 else /* The state mark is '•' */
1261 shapeslval.ident = prependNamespace( id );
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. */
1273 else /* The state mark is '•' */
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. */
1287 else /* The state mark is '•' */
1291 shapeslval.ident = prependNamespace( id );
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 );
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.
1314 shapes_strtod( char * str, char ** end )
1318 for( ; *term != '\0'; ++term )
1338 /* We replace the "*^" by something in the notation of strtod */
1340 if( *(term+2) == '~' )
1357 double val = strtod( str, end );
1363 shapes_hexToChar( char c1, char c2 )
1367 ( 16 * ( ( c1 < 'A' ) ? static_cast< unsigned char >( c1 - '0' ) : static_cast< unsigned char >( c1 - 'A' + 10 ) )
1369 ( ( c2 < 'A' ) ? static_cast< unsigned char >( c2 - '0' ) : static_cast< unsigned char >( c2 - 'A' + 10 ) ) );
1373 ShapesScanner::start( )
1375 static const Ast::FileID * START_NULL_FILE = Ast::FileID::build_internal( "<start-null>" );
1377 if( ! interactive_ )
1379 loader_.pushPreludeFiles( & loadStack_ );
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;
1387 ShapesScanner::endOfLine( )
1389 shapeslloc.firstLine = shapeslloc.lastLine + 1;
1390 shapeslloc.lastLine = shapeslloc.firstLine;
1391 shapeslloc.lastColumn = 0;
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 );
1409 throw Exceptions::InternalError( shapeslloc, "Unexpected namespace form of unconditional file inclusion." );
1415 if( currentNeedIsNeed )
1416 path = searchFile( currentNeedFile + ".shext" );
1418 path = searchFile( currentNeedFile + ".shape" );
1420 struct stat theStat;
1421 if( stat( path.c_str( ), & theStat ) != 0 )
1423 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( path.c_str( ) ), 0, 0, Exceptions::FileReadOpenError::STAT );
1425 fileID = Ast::FileID::build_stat( theStat, path );
1429 if( currentNeedIsNeed )
1431 NeededFile neededFile( lexicalPath, fileID );
1432 if( neededFiles_.find( neededFile ) != neededFiles_.end( ) )
1434 shapeslloc.firstLine = shapeslloc.lastLine + 1;
1435 shapeslloc.lastLine = shapeslloc.firstLine;
1436 shapeslloc.lastColumn = 0;
1440 neededFiles_.insert( neededFile );
1443 iFile = new std::ifstream( fileID->name( ) );
1444 if( ! iFile->good( ) )
1447 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( fileID->name( ) ), 0, 0 );
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( );
1459 NeededFile neededFile( lexicalPath, fileID );
1460 if( neededFiles_.find( neededFile ) != neededFiles_.end( ) )
1462 neededFiles_.insert( neededFile );
1463 iFile = new std::ifstream( fileID->name( ) );
1464 if( ! iFile->good( ) )
1467 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( fileID->name( ) ), NULL, NULL );
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;
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.
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( ) ) );
1505 ShapesScanner::queueStream( std::istream * is, const Ast::FileID * yyinFile )
1507 yyinQueue_.push_back( std::pair< std::istream * , const Ast::FileID * >( is, yyinFile ) );