%{ /* * Lexer for states. * Copyright (c) 1997-1998 Markku Rossi. * * Author: Markku Rossi */ /* * This file is part of GNU Enscript. * * Enscript 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 3 of the License, or * (at your option) any later version. * * Enscript 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 Enscript. If not, see . */ /* * $Id: lex.l,v 1.1.1.1 2003/03/05 07:25:52 mtr Exp $ */ #include "defs.h" #include "gram.h" static void eat_comment (); static char *read_string ___P ((unsigned int *len_return)); static void read_regexp ___P ((Node *node)); %} real [+-]?[0-9]+\.[0-9]*|[+-]?\.[0-9]+ integer [+-]?[0-9]+ symbol [a-zA-Z_][a-zA-Z_0-9]*|\$. %% "/*" { eat_comment (); } [ \t\r\f] { ; } \n { linenum++; } \" { yylval.node = node_alloc (nSTRING); yylval.node->u.str.data = read_string (&yylval.node->u.str.len); return tSTRING; } '[^\\]' { yylval.node = node_alloc (nINTEGER); yylval.node->u.integer = yytext[1]; return tINTEGER; } '\\.' { yylval.node = node_alloc (nINTEGER); switch (yytext[2]) { case 'n': yylval.node->u.integer = '\n'; break; case 't': yylval.node->u.integer = '\t'; break; case 'v': yylval.node->u.integer = '\v'; break; case 'b': yylval.node->u.integer = '\b'; break; case 'r': yylval.node->u.integer = '\r'; break; case 'f': yylval.node->u.integer = '\f'; break; case 'a': yylval.node->u.integer = '\a'; break; default: yylval.node->u.integer = yytext[2]; break; } return tINTEGER; } \/ { yylval.node = node_alloc (nREGEXP); read_regexp (yylval.node); return tREGEXP; } "BEGIN" { return tBEGIN; } "END" { return tEND; } "div" { return tDIV; } "else" { return tELSE; } "extends" { return tEXTENDS; } "for" { return tFOR; } "if" { return tIF; } "local" { return tLOCAL; } "namerules" { return tNAMERULES; } "return" { return tRETURN; } "start" { return tSTART; } "startrules" { return tSTARTRULES; } "state" { return tSTATE; } "sub" { return tSUB; } "while" { return tWHILE; } "==" { return tEQ; } "!=" { return tNE; } "<=" { return tLE; } ">=" { return tGE; } "&&" { return tAND; } "||" { return tOR; } "++" { return tPLUSPLUS; } "--" { return tMINUSMINUS; } "+=" { return tADDASSIGN; } "-=" { return tSUBASSIGN; } "*=" { return tMULASSIGN; } "div=" { return tDIVASSIGN; } {real} { yylval.node = node_alloc (nREAL); yylval.node->u.real = atof (yytext); return tREAL; } {integer} { yylval.node = node_alloc (nINTEGER); yylval.node->u.integer = atoi (yytext); return tINTEGER; } {symbol} { yylval.node = node_alloc (nSYMBOL); yylval.node->u.sym = xstrdup (yytext); return tSYMBOL; } . { return yytext[0]; } %% static void eat_comment () { int c; while ((c = input ()) != EOF) { if (c == '\n') linenum++; else if (c == '*') { c = input (); if (c == '/') /* All done. */ return; if (c == EOF) { yyerror (_("error: EOF in comment")); break; } unput (c); } } yyerror (_("error: EOF in comment")); } int yywrap () { return 1; } static char * read_string (len_return) unsigned int *len_return; { char *buf = NULL; char *buf2; int buflen = 0; int bufpos = 0; int ch; int done = 0; while (!done) { ch = input (); if (ch == '\n') linenum++; switch (ch) { case EOF: unexpected_eof: yyerror (_("error: EOF in string constant")); done = 1; break; case '"': done = 1; break; case '\\': ch = input (); switch (ch) { case 'n': ch = '\n'; break; case 't': ch = '\t'; break; case 'v': ch = '\v'; break; case 'b': ch = '\b'; break; case 'r': ch = '\r'; break; case 'f': ch = '\f'; break; case 'a': ch = '\a'; break; case EOF: goto unexpected_eof; break; default: if (ch == '0') { int i; int val = 0; for (i = 0; i < 3; i++) { ch = input (); if ('0' <= ch && ch <= '7') val = val * 8 + ch - '0'; else { unput (ch); break; } } ch = val; } break; } /* FALLTHROUGH */ default: if (bufpos >= buflen) { buflen += 1024; buf = (char *) xrealloc (buf, buflen); } buf[bufpos++] = ch; break; } } buf2 = (char *) xmalloc (bufpos + 1); memcpy (buf2, buf, bufpos); buf2[bufpos] = '\0'; xfree (buf); *len_return = bufpos; return buf2; } static void read_regexp (node) Node *node; { char *buf = NULL; char *buf2; int buflen = 0; int bufpos = 0; int ch; int done = 0; while (!done) { ch = input (); switch (ch) { case EOF: unexpected_eof: yyerror (_("error: EOF in regular expression")); done = 1; break; case '/': done = 1; break; case '\\': ch = input (); switch (ch) { case '\n': /* Line break. */ linenum++; continue; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 'f': ch = '\f'; break; case 't': ch = '\t'; break; case '/': case '\\': /* Quote these. */ break; case EOF: goto unexpected_eof; break; default: if (ch == '0') { int i; int val = 0; for (i = 0; i < 3; i++) { ch = input (); if ('0' <= ch && ch <= '7') val = val * 8 + ch - '0'; else { unput (ch); break; } } ch = val; } else { /* Pass it through. */ unput (ch); ch = '\\'; } break; } /* FALLTHROUGH */ default: if (bufpos >= buflen) { buflen += 1024; buf = (char *) xrealloc (buf, buflen); } buf[bufpos++] = ch; break; } } /* Possible options. */ done = 0; while (!done) { ch = input (); switch (ch) { case 'i': /* Case-insensitive regular expression. */ node->u.re.flags |= fRE_CASE_INSENSITIVE; break; default: /* Unknown option => this belongs to the next token. */ unput (ch); done = 1; break; } } buf2 = (char *) xmalloc (bufpos + 1); memcpy (buf2, buf, bufpos); buf2[bufpos] = '\0'; xfree (buf); node->u.re.data = buf2; node->u.re.len = bufpos; } /* Local variables: mode: c End: */