%{ /* ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 1, or (at your option) ** any later version. ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "common.h" #include "parser.h" // Current line number int currentLineNumber = 1; // token expected by the parser kTokens expectToken = kNone; CRevNumber revnumber; extern "C" int yywrap() { BEGIN INITIAL; return 1; } %} /* Normal state: parsing nodes. The initial start state is used */ /* only to recognize the VRML header. */ %x NODE /* Start tokens for all of the field types, */ /* except for MFNode and SFNode, which are almost completely handled */ /* by the parser: */ %x ST_STRING ST_TAG ST_REV ST_REVORNIL ST_INREV ST_INT %x ST_ANYBUTSEP ST_DATE /* positive integer */ int ([\+-]?[0-9]+) /* Whitespace. */ ws ([ \t\r\n]+) /* And the same pattern without the newline */ wsnnl ([ \t\r]) /* a string */ str ([^ \t\r\n][^\t\r\n]*) /* a tag/author/state string */ tag ([^ \t\r\n:;])+ /*revfollow (----------------------------)*/ revfollow ^(\-{28})$ /*endfollow (=============================================================================)*/ endfollow ^(\={50,})$ %% %{ /* Switch into a new start state if the parser */ /* just told us that we've read a field name */ /* and should expect a field value (or IS) */ #if qCvsDebug if (yy_flex_debug) fprintf(stderr,"LEX--> Start State %d\n", expectToken); #endif switch(expectToken) { case kNone: BEGIN NODE; break; case kString: BEGIN ST_STRING; break; case kRevnum: BEGIN ST_REV; break; case kRevnumOrNil: BEGIN ST_REVORNIL; break; case kInt: BEGIN ST_INT; break; case kDate: BEGIN ST_DATE; break; case kAnyButSep: BEGIN ST_ANYBUTSEP; break; default: yyerror("ACK: Bad expectToken"); break; } %} {ws}* { BEGIN NODE; } RCS\ file { return ID_RCS; } Working\ file { return ID_WORKING; } head { return ID_HEAD; } branch { return ID_BRANCH; } locks { return ID_LOCKS; } access\ list { return ID_ACCESS; } symbolic\ names { return ID_SYMBOLIC; } keyword\ substitution { return ID_KEYWORD; } total\ revisions { return ID_TOTREVISIONS; } selected\ revisions { return ID_SELREVISIONS; } description { return ID_DESCRIPTION; } revision { return ID_REVISION; } date { return ID_DATE; } author { return ID_AUTHOR; } state { return ID_STATE; } branches { return ID_BRANCHES; } strict { return ID_STRICT; } lines { return ID_LINES; } locked\ by { return ID_LOCKEDBY; } {revfollow} { return ID_REVFOLLOW; } {endfollow} { return ID_ENDFOLLOW; } {tag} { yylval_set(yytext); return TAG; } {revfollow} { BEGIN NODE; expectToken = kNone; return ID_REVFOLLOW; } {endfollow} { BEGIN NODE; expectToken = kNone; return ID_ENDFOLLOW; } \n { ++currentLineNumber; #if qCvsDebug if (yy_flex_debug) fprintf(stderr,"LINESEP--> %d\n", currentLineNumber); #endif yylval_set((int)(unsigned char)yytext[0]); return ID_CHAR; } . { yylval_set((int)(unsigned char)yytext[0]); return ID_CHAR; } {str} { yylval_set(yytext); BEGIN NODE; expectToken = kNone; return STRING; } {int} { int v; revnumber.reset(); if(sscanf(yytext, "%d", &v) == 1) revnumber += v; else yyerror("%s not an integer value", yytext); BEGIN ST_INREV; expectToken = kNone; } {int} { int v; revnumber.reset(); if(sscanf(yytext, "%d", &v) == 1) revnumber += v; else yyerror("%s not an integer value", yytext); BEGIN ST_INREV; expectToken = kNone; } [^ \t\r\n] { yyless(0); /* put back the spaces */ BEGIN NODE; expectToken = kNone; return REVNUM; } \.{int} { int v; if(sscanf(yytext + 1, "%d", &v) == 1) revnumber += v; else yyerror("%s not an integer value", yytext); BEGIN ST_INREV; expectToken = kNone; } . { yyless(0); /* put back the spaces */ BEGIN NODE; expectToken = kNone; yylval_set(revnumber); return REVNUM; } {int} { int v; if(sscanf(yytext, "%d", &v) == 1) revnumber += v; else yyerror("%s not an integer value", yytext); BEGIN NODE; expectToken = kNone; yylval_set(v); return INTEGER; } {int} { int v; if(sscanf(yytext, "%d", &v) == 1) revnumber += v; else yyerror("%s not an integer value", yytext); yylval_set(v); return INTEGER; } [:/] { return yytext[0]; } /* Whitespace and catch-all rules apply to all start states: */ <*>{wsnnl}+ ; /* This is also whitespace, but we'll keep track of line number */ /* to report in errors: */ <*>{wsnnl}*\n{wsnnl}* { ++currentLineNumber; #if qCvsDebug if (yy_flex_debug) fprintf(stderr,"LINE--> %d\n", currentLineNumber); #endif if(expectToken == kAnyButSep) { // strange bug, flex is sometimes getting here in // a kAnyButSep mode, while it should not yylval_set(yytext); return STRING; } } /* This catch-all rule catches anything not covered by any of */ /* the above: */ <*>. { yylval_set((int)(unsigned char)yytext[0]); return (int)(unsigned char)yytext[0]; }