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 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.h"
44 #define YY_USER_ACTION doBeforeEachAction( );
45 #define YY_EXIT_FAILURE Shapes::Interaction::EXIT_INTERNAL_ERROR
47 double shapes_strtod( char * str, char ** end );
48 char shapes_hexToChar( char c1, char c2 );
54 Float [~]?[0-9]+([.][0-9]*)?("*^"[~]?[0-9]+)?
55 Greek "α"|"β"|"γ"|"Γ"|"δ"|"Δ"|"ε"|"ζ"|"η"|"Θ"|"ι"|"κ"|"λ"|"Λ"|"μ"|"ν"|"χ"|"Ξ"|"π"|"Π"|"ρ"|"σ"|"Σ"|"τ"|"ϕ"|"ω"|"Ω"
56 LowerCaseLetter [a-z_?]
58 Letter {LowerCaseLetter}|{UpperCaseLetter}|{Greek}
59 Identifier {Letter}({Letter}|[0-9])*
69 %option prefix="shapes"
70 %option yyclass="ShapesScanner"
72 %x DiscardRestOfLineAndBEGIN_INITIAL
96 ^"##classoption"[ \t]+ { BEGIN( LaTeXOption ); }
97 ^"##documentclass"[ \t]+ { BEGIN( LaTeXClass ); }
98 ^"##preamble"[ \t] { BEGIN( LaTeXPreamble ); }
99 ^"##documenttop"[ \t] { BEGIN( LaTeXDocumentTop ); }
100 ^"##no-lmodernT1"[\n] { Kernel::theTeXLabelManager.setlmodernT1( shapeslloc, false ); }
101 ^"##no-utf8"[\n] { Kernel::theTeXLabelManager.setutf8( shapeslloc, false ); }
102 ^"##seed"[ \t]+ { BEGIN( RandSeed ); }
103 ^"##unit"[ \t]+ { BEGIN( NewUnitName ); }
104 ^"##include"[ \t]+ { BEGIN( Incl ); return T_srcLoc; }
105 ^"##needs"[ \t]+ { BEGIN( Needs ); return T_srcLoc; }
106 ^"##echo"[ \t] { BEGIN( Echo ); }
107 ^"##author"[ \t] { BEGIN( Author ); }
109 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "All lines beginning with ## must be scanner specials. Please use a leading horizontal whitespace if this is not what is intended." ) ) );
112 <DiscardRestOfLineAndBEGIN_INITIAL>.* {
116 <LaTeXOption>[^,\n]+ { Kernel::theTeXLabelManager.addDocumentOption( shapeslloc, yytext ); }
118 shapeslloc.firstLine = shapeslloc.lastLine + 1;
119 shapeslloc.lastLine = shapeslloc.firstLine;
120 shapeslloc.lastColumn = 0;
124 <LaTeXClass>.+ { Kernel::theTeXLabelManager.setDocumentClass( shapeslloc, yytext ); }
126 shapeslloc.firstLine = shapeslloc.lastLine + 1;
127 shapeslloc.lastLine = shapeslloc.firstLine;
128 shapeslloc.lastColumn = 0;
132 <LaTeXPreamble>.* { Kernel::theTeXLabelManager.addPreambleLine( shapeslloc, yytext ); }
133 <LaTeXPreamble>[\n] {
134 shapeslloc.firstLine = shapeslloc.lastLine + 1;
135 shapeslloc.lastLine = shapeslloc.firstLine;
136 shapeslloc.lastColumn = 0;
140 <LaTeXDocumentTop>.* { Kernel::theTeXLabelManager.addDocumentTopLine( shapeslloc, yytext ); }
141 <LaTeXDocumentTop>[\n] {
142 shapeslloc.firstLine = shapeslloc.lastLine + 1;
143 shapeslloc.lastLine = shapeslloc.firstLine;
144 shapeslloc.lastColumn = 0;
150 long int s = strtol( yytext, & end, 10 );
153 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Failed to scan integer." ) ) );
159 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Random nuber generator seed must not be negative." ) ) );
168 shapeslloc.firstLine = shapeslloc.lastLine + 1;
169 shapeslloc.lastLine = shapeslloc.firstLine;
170 shapeslloc.lastColumn = 0;
174 <NewUnitName>{Identifier} {
175 newUnitName = strdup( yytext );
176 BEGIN( NewUnitEqual );
179 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected identifier." ) ) );
180 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
182 <NewUnitEqual>[ \t]*"="[ \t]* { BEGIN( NewUnitValue ); }
184 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected '='." ) ) );
185 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
187 <NewUnitValue>{Float}"bp" {
189 double newUnitValue = shapes_strtod( yytext, & end );
190 typedef typeof unitTable MapType;
191 MapType::const_iterator i = unitTable.find( newUnitName );
192 if( i != unitTable.end( ) )
194 if( i->second != newUnitValue )
196 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName ) ) );
201 unitTable[ newUnitName ] = newUnitValue;
205 <NewUnitValue>{Float}"mm" {
207 double newUnitValue = shapes_strtod( yytext, & end ) * ( 0.1 * 72 / 2.54 );
208 typedef typeof unitTable MapType;
209 MapType::const_iterator i = unitTable.find( newUnitName );
210 if( i != unitTable.end( ) )
212 if( i->second != newUnitValue )
214 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName ) ) );
219 unitTable[ newUnitName ] = newUnitValue;
223 <NewUnitValue>{Float}"cm" {
225 double newUnitValue = shapes_strtod( yytext, & end ) * ( 72 / 2.54 );
226 typedef typeof unitTable MapType;
227 MapType::const_iterator i = unitTable.find( newUnitName );
228 if( i != unitTable.end( ) )
230 if( i->second != newUnitValue )
232 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName ) ) );
237 unitTable[ newUnitName ] = newUnitValue;
241 <NewUnitValue>{Float}"m" {
243 double newUnitValue = shapes_strtod( yytext, & end ) * ( 100 * 72 / 2.54 );
244 typedef typeof unitTable MapType;
245 MapType::const_iterator i = unitTable.find( newUnitName );
246 if( i != unitTable.end( ) )
248 if( i->second != newUnitValue )
250 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName ) ) );
255 unitTable[ newUnitName ] = newUnitValue;
259 <NewUnitValue>{Float}"in" {
261 double newUnitValue = shapes_strtod( yytext, & end ) * 72;
262 typedef typeof unitTable MapType;
263 MapType::const_iterator i = unitTable.find( newUnitName );
264 if( i != unitTable.end( ) )
266 if( i->second != newUnitValue )
268 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName ) ) );
273 unitTable[ newUnitName ] = newUnitValue;
277 <NewUnitValue>{Float}{Identifier} {
279 double val = shapes_strtod( yytext, & end );
281 typedef typeof unitTable MapType;
282 MapType::const_iterator i = unitTable.find( end );
283 if( i == unitTable.end( ) )
285 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknownUnit( shapeslloc, strrefdup( end ) ) );
289 double newUnitValue = val * i->second;
291 i = unitTable.find( newUnitName );
292 if( i != unitTable.end( ) )
294 if( i->second != newUnitValue )
296 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExistingUnit( shapeslloc, strrefdup( newUnitName ) ) );
301 unitTable[ newUnitName ] = newUnitValue;
307 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Expected a length." ) ) );
308 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
316 shapeslval.floatVal = M_PI / 180 * shapes_strtod( yytext, & end );
322 shapeslval.floatVal = shapes_strtod( yytext, & end );
328 shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 0.1 * 72 / 2.54 );
334 shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 72 / 2.54 );
340 shapeslval.floatVal = shapes_strtod( yytext, & end ) * ( 100 * 72 / 2.54 );
346 shapeslval.floatVal = shapes_strtod( yytext, & end ) * 72;
350 {Float}{Identifier} {
352 double val = shapes_strtod( yytext, & end );
354 typedef typeof unitTable MapType;
355 MapType::const_iterator i = unitTable.find( end );
356 if( i == unitTable.end( ) )
358 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknownUnit( shapeslloc, strrefdup( end ) ) );
362 shapeslval.floatVal = val * i->second;
369 double val = shapes_strtod( yytext, & end );
370 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST );
371 return T_speciallength;
376 double val = shapes_strtod( yytext, & end );
377 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC );
378 return T_speciallength;
383 double val = shapes_strtod( yytext, & end );
384 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CORR );
385 return T_speciallength;
390 double val = shapes_strtod( yytext, & end );
391 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC | Computation::SPECIALU_CORR );
392 return T_speciallength;
397 double val = shapes_strtod( yytext, & end );
398 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_NOINFLEX );
399 return T_speciallength;
404 double val = shapes_strtod( yytext, & end );
405 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC | Computation::SPECIALU_NOINFLEX );
406 return T_speciallength;
411 double val = shapes_strtod( yytext, & end );
412 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CORR | Computation::SPECIALU_NOINFLEX );
413 return T_speciallength;
418 double val = shapes_strtod( yytext, & end );
419 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_DIST | Computation::SPECIALU_CIRC | Computation::SPECIALU_CORR | Computation::SPECIALU_NOINFLEX );
420 return T_speciallength;
425 double val = shapes_strtod( yytext, & end );
426 shapeslval.expr = new Ast::SpecialLength( shapeslloc, val, Computation::SPECIALU_NOINFLEX );
427 return T_speciallength;
433 shapeslval.floatVal = shapes_strtod( yytext, & end );
438 const char * src = yytext + 1;
439 bool negative = false;
446 int absval = strtol( src, & end, 10 );
449 shapeslval.intVal = - absval;
453 shapeslval.intVal = absval;
460 shapeslval.intVal = strtol( yytext + 3, & end, 16 );
466 shapeslval.intVal = strtol( yytext + 3, & end, 2 );
471 shapeslval.floatVal = HUGE_VAL;
476 shapeslval.boolVal = true;
481 shapeslval.boolVal = false;
485 "--" { return T_minusminus; }
486 "++" { return T_plusplus; }
487 ".." { return T_ddot; }
488 "..." { return T_dddot; }
490 "::" { return T_declaretype; }
491 ":=" { return T_assign; }
492 "=" { return T_eqeq; }
493 "/="|"≠" { return T_eqneq; }
495 "->"|"→" { return T_mapsto; }
496 "../" { return T_surrounding; }
497 "[]" { return T_emptybrackets; }
498 "[...]" { return T_dddotbrackets; }
499 "()"|"⊙" { return T_compose; }
501 "(>" { return T_unionLeft; }
502 "<)" { return T_unionRight; }
503 "<>" { return T_split; }
504 "(<" { return T_splitLeft; }
505 ">)" { return T_splitRight; }
506 "(|" { return T_absLeft; }
507 "|)" { return T_absRight; }
509 [\{\}\(\)\[\]\<\>] { return yytext[0]; }
510 [\.\,\;\:\_\@\!\#\%\&\|\^\-\+\'\"\\] { return yytext[0]; }
511 [*/~=] { return yytext[0]; }
513 "*/"|"∥" { return T_projection; }
514 "/_"|"∠" { return T_angle; }
515 "&|" { return T_ampersandMore; }
517 "<="|"≤" { return T_lesseq; }
518 ">="|"≥" { return T_greatereq; }
520 "<<"|"≪" { return T_llthan; }
521 ">>"|"≫" { return T_ggthan; }
523 "@@" { return T_atat; }
525 "and"|"⋀" { return T_and; }
526 "or"|"⋁" { return T_or; }
527 "xor"|"⊻" { return T_xor; }
528 "not"|"¬" { return T_not; }
530 "dynamic" { return T_dynamic; }
532 "cycle" { return T_cycle; }
534 "TeX" { return T_tex; }
536 "indexof" { return T_indexof; }
537 "depthof" { return T_depthof; }
538 "VARNAME" { return T_variableName; }
540 "continuation" { return T_continuation; /* Reserved for future use */ }
541 "continue" { return T_continue; /* Reserved for future use */ }
542 "escape_continuation" { return T_esc_continuation; }
543 "escape_continue" { return T_esc_continue; }
544 "escape_backtrace" { return T_esc_backtrace; }
546 "class" { return T_class; }
547 "__members__" { return T_members; }
548 "__prepare__" { return T_prepare; }
549 "__abstract__" { return T_abstract; }
550 "__overrides<" { return T_overrides; }
551 ">__" { return T_gr__; }
555 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Illegal use of reserved tab character." ) ) );
559 shapeslloc.firstLine = shapeslloc.lastLine + 1;
560 shapeslloc.lastLine = shapeslloc.firstLine;
561 shapeslloc.lastColumn = 0;
564 <INITIAL>"|**".*[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; }
565 <INITIAL>"/**" { quoteDepth = 1; BEGIN( Comment ); }
566 <INITIAL>"**/" { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found closing comment delimiter outside comment." ) ); }
567 <Comment>"/**" { ++quoteDepth; more( ); }
570 if( quoteDepth == 0 )
580 <Comment>[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; }
582 /* It seems like YY_USER_ACTION is not invoked at EOF, so we do this manually,
583 * however ignornig yyleng (which has the value 1).
585 shapeslloc.firstColumn = shapeslloc.lastColumn;
586 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found EOF while scanning comment." ) );
592 ++shapeslloc.lastLine;
593 shapeslloc.lastColumn = 0;
598 <INITIAL>"´" { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found closing quote outside string." ) ); }
599 <String>"`" { ++quoteDepth; more( ); }
602 if( quoteDepth == 0 )
604 yytext[ yyleng - 2 ] = '\0';
606 --shapeslloc.firstColumn;
613 yymore( ); // The purpose of this line is only to let flex know that we use yy_more_flag
617 <String,PoorMansString>[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; more( ); }
618 <String,PoorMansString>. { more( ); }
619 <String,PoorMansString><<EOF>> {
620 /* It seems like YY_USER_ACTION is not invoked at EOF, so we do this manually,
621 * however ignornig yyleng (which has the value 1).
623 shapeslloc.firstColumn = shapeslloc.lastColumn;
624 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found EOF while scanning string." ) );
627 <INITIAL>"(\""[\n]? {
630 ++shapeslloc.lastLine;
631 shapeslloc.lastColumn = 0;
634 BEGIN( PoorMansString );
636 <INITIAL>"\")" { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Found closing poor man's quote outside string." ) ); }
637 <PoorMansString>"\")" {
638 yytext[ yyleng - 2 ] = '\0';
640 --shapeslloc.firstColumn;
646 while( ! dataStringChunks_.empty( ) )
648 delete dataStringChunks_.back( ).first;
649 dataStringChunks_.pop_back( );
651 dataStringTotalLength_ = 0;
652 BEGIN( DataStringHex );
654 <DataStringPlain,DataStringHex>[\n] { ++shapeslloc.lastLine; shapeslloc.lastColumn = 0; }
655 <DataStringPlain>[ -z]+ {
656 dataStringChunks_.push_back( std::pair< char *, size_t >( strdup( yytext ), yyleng ) );
657 dataStringTotalLength_ += yyleng;
659 <DataStringHex>[ \t]+ { }
660 <DataStringHex>(([A-F0-9]{2})|[a-z])+ {
661 char * res = new char[ yyleng + 1 ];
663 for( const char * src = yytext; *src != '\0'; ++dst )
665 if( 'a' <= *src && *src <= 'z' )
677 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( std::string( "Invalid character name in escape mode: " ) + *src ) ) );
683 *dst = shapes_hexToChar( src[0], src[1] );
687 dataStringChunks_.push_back( std::pair< char *, size_t >( res, dst - res ) );
688 dataStringTotalLength_ += dst - res;
690 <DataStringHex>[{] { BEGIN( DataStringPlain ); }
691 <DataStringPlain>[}] { BEGIN( DataStringHex ); }
693 concatenateDataString( );
697 <DataStringPlain,DataStringHex>. {
698 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Stray character in \"{...} string." ) );
702 currentNeedFile = yytext;
703 currentNeedPushCount = 0;
704 currentNeedIsNeed = false;
709 currentNeedFile = yytext;
710 currentNeedPushCount = 0;
711 currentNeedIsNeed = true;
716 <InclFrom>[\n] { doInclusion( ); }
717 <InclFrom>":"[ \t]+ { BEGIN( InclPath ); }
718 <InclFrom>":". { throw Exceptions::ScannerError( shapeslloc, strrefdup( "The \":\" must be followed by whitespace." ) ); }
719 <InclFrom>. { throw Exceptions::ScannerError( shapeslloc, strrefdup( "Expected \":\"." ) ); }
722 <InclPath>[^ \t\n]+ {
723 push_frontNeedPath( yytext );
724 ++currentNeedPushCount;
727 if( currentNeedPushCount == 0 )
729 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Missing paths after \"from\"." ) );
735 std::cerr << yytext << std::endl ;
740 if( ! stateStack.empty( ) )
742 Kernel::theDocInfo.addExtensionAuthorString( shapeslloc.file_->name( ) + std::string( " by " ) + yytext );
746 if( ! Kernel::theDocInfo.addInfo( "Author", SimplePDF::newString( yytext ) ) )
748 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( "Multiply specified #author." ) ) );
756 /* It seems like YY_USER_ACTION is not invoked at EOF, so we do this manually,
757 * however ignornig yyleng (which has the value 1).
759 shapeslloc.firstColumn = shapeslloc.lastColumn;
761 if( stateStack.empty( ) )
766 for( ; preludeIterator_ != needSearchPath.end( ); ++preludeIterator_ )
768 std::string filename = needpathWithSuffix( *preludeIterator_, "Shapes-Prelude" );
769 struct stat theStatDummy;
770 if( stat( filename.c_str( ), & theStatDummy ) == 0 )
772 preludeFile_ = new std::ifstream( filename.c_str( ) );
773 yy_switch_to_buffer( yy_create_buffer( preludeFile_, YY_BUF_SIZE ) );
774 shapeslloc = Ast::SourceLocation( Ast::FileID::build_stat( theStatDummy, filename ) );
779 if( preludeIterator_ == needSearchPath.end( ) )
788 if( ! yyinQueue_.empty( ) )
790 yy_switch_to_buffer( yy_create_buffer( yyinQueue_.front( ).first, YY_BUF_SIZE ) );
791 shapeslloc = Ast::SourceLocation( yyinQueue_.front( ).second );
792 yyinQueue_.pop_front( );
798 return T_interactiveMark;
806 else if( inPrelude_ )
816 ++preludeIterator_; /* We do this here instead of before the "goto done;", so we get something to jump to.*/
820 yy_delete_buffer( YY_CURRENT_BUFFER );
821 yy_switch_to_buffer( stateStack.top( ) );
823 shapeslloc = locStack.top( );
825 for( size_t tmp = pathCountStack.top( ); tmp > 0; --tmp )
827 pop_frontNeedPath( );
829 pathCountStack.pop( );
834 shapeslval.char_p = strdup( yytext );
837 {TypeMark}{Identifier} {
838 const char * id = yytext + 2; // The type mark is allways 2 bytes.
839 shapeslval.char_p = strdup( id );
843 {DynamicMark}{Identifier} {
844 shapeslval.char_p = strdup( yytext + 1 );
845 return T_dynamic_identifier;
847 {StateMark}{Identifier} {
848 const char * id = yytext;
849 // Depending on which state mark is used, we must skip different number of bytes.
854 else // The state mark is '•'
858 shapeslval.char_p = strdup( id );
859 return T_state_identifier;
861 {DynamicMark}{StateMark}{Identifier} {
862 const char * id = yytext + 1; // The dynamic mark is allways 1 byte.
863 // Depending on which state mark is used, we must skip different number of bytes.
868 else // The state mark is '•'
872 shapeslval.char_p = strdup( id );
873 return T_dynamic_state_identifier;
877 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( shapeslloc, strrefdup( ( std::string( "Scanner found unrecognized token: " ) + yytext ).c_str( ) ) ) );
878 BEGIN( DiscardRestOfLineAndBEGIN_INITIAL );
882 /* The closing %% above marks the end of the Rules section and the beginning
883 * of the User Subroutines section. All text from here to the end of the
884 * file is copied verbatim to the end of the generated lex.pdf.c file.
885 * This section is where you put definitions of helper functions.
889 shapes_strtod( char * str, char ** end )
893 for( ; *term != '\0'; ++term )
913 // We replace the "*^" by something in the notation of strtod
915 if( *(term+2) == '~' )
932 double val = strtod( str, end );
938 shapes_hexToChar( char c1, char c2 )
942 ( 16 * ( ( c1 < 'A' ) ? static_cast< unsigned char >( c1 - '0' ) : static_cast< unsigned char >( c1 - 'A' + 10 ) )
944 ( ( c2 < 'A' ) ? static_cast< unsigned char >( c2 - '0' ) : static_cast< unsigned char >( c2 - 'A' + 10 ) ) );
948 ShapesScanner::start( )
950 static const Ast::FileID * START_NULL_FILE = Ast::FileID::build_internal( "<start-null>" );
954 preludeIterator_ = needSearchPath.end( );
958 preludeIterator_ = needSearchPath.begin( );
960 preludeFile_ = new std::istringstream( "" ); /* This will result in EOF immediately, and then we turn to the first real file. */
961 yy_switch_to_buffer( yy_create_buffer( preludeFile_, YY_BUF_SIZE ) );
962 shapeslloc.file_ = START_NULL_FILE;
966 ShapesScanner::doInclusion( )
969 if( currentNeedIsNeed )
971 path = searchFile( currentNeedFile + ".shext" );
975 path = searchFile( currentNeedFile + ".shape" );
979 if( stat( path.c_str( ), & theStat ) != 0 )
981 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( path.c_str( ) ), 0, 0, Exceptions::FileReadOpenError::STAT );
983 const Ast::FileID * fileID = Ast::FileID::build_stat( theStat, path );
984 if( currentNeedIsNeed )
986 if( neededFiles.find( fileID ) != neededFiles.end( ) )
988 shapeslloc.firstLine = shapeslloc.lastLine + 1;
989 shapeslloc.lastLine = shapeslloc.firstLine;
990 shapeslloc.lastColumn = 0;
994 neededFiles.insert( fileID );
997 std::ifstream * iFile = new std::ifstream( path.c_str( ) );
998 if( ! iFile->good( ) )
1000 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( path.c_str( ) ), 0, 0 );
1003 shapeslloc.firstLine = shapeslloc.lastLine + 1;
1004 shapeslloc.lastLine = shapeslloc.firstLine;
1005 shapeslloc.lastColumn = 0;
1007 locStack.push( shapeslloc );
1008 shapeslloc = Ast::SourceLocation( fileID );
1009 stateStack.push( YY_CURRENT_BUFFER );
1010 yy_switch_to_buffer( yy_create_buffer( iFile, YY_BUF_SIZE ) );
1011 pathCountStack.push( currentNeedPushCount );
1017 ShapesScanner::queueStream( std::istream * is, const Ast::FileID * yyinFile )
1019 yyinQueue_.push_back( std::pair< std::istream * , const Ast::FileID * >( is, yyinFile ) );