%{
/*
    This file is part of the FElt finite element analysis package.
    Copyright (C) 1993 Jason I. Gobat and Darren C. Atkinson

    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 2 of the License, 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.
*/

/************************************************************************
 * File:	lexer.l							*
 *									*
 * Description:	This file contains the flex specification for the	*
 *		input file lexical analyzer.				*
 *									*
 * History:	V1.0 by Jason Gobat and Darren C. Atkinson		*
 ************************************************************************/

# include <stdlib.h>
# include <string.h>
# include "generator.h"
# include "error.h"
# include "y.tab.h"


/************************************************************************
 * Function:	 yylex							*
 *									*
 * Parameters:	 none							*
 *									*
 * Return value: next token						*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 yytext is modified					*
 *									*
 * Description:	 Yylex is the input file lexical analyzer generated	*
 *		 by flex.						*
 ************************************************************************/

%}
%a 3000
%o 4000


letter				[a-zA-Z_]
digit				[0-9]
identifier			{letter}({letter}|{digit})*
exp				([eE][+-]?{digit}+)
optws				[ \t\n]*
ws				[ \t\n]+
lin				[lL][iI][nN][eE][aA][rR]
log				[lL][oO][gG]
%%

%{
/* Assignments */
%}

lines{optws}=			{return LINES_EQ;}
grids{optws}=			{return GRIDS_EQ;}
holes{optws}=			{return HOLES_EQ;}
trimeshes{optws}=		{return TRIANGLES_EQ;}
number{optws}=			{return NUMBER_EQ;}
xnumber{optws}=			{return XNUMBER_EQ;}
ynumber{optws}=			{return YNUMBER_EQ;}
znumber{optws}=			{return ZNUMBER_EQ;}
first{optws}=			{return FIRST_EQ;}
last{optws}=			{return LAST_EQ;}
tolin{optws}=			{return TOLIN_EQ;}
angspc{optws}=			{return ANGSPC_EQ;}
angtol{optws}=			{return ANGTOL_EQ;}
kappa{optws}=			{return KAPPA_EQ;}
dmin{optws}=			{return DMIN_EQ;}
max{optws}=			{return MAX_EQ;}
min{optws}=			{return MIN_EQ;}
rule{optws}={optws}{lin}	{yylval.i = 'i'; return RULE_EQ;}
rule{optws}={optws}{log}	{yylval.i = 'o'; return RULE_EQ;}


%{
/* Keywords */
%}

end				{return END;}
lines				{return LINES;}
grids				{return GRIDS;}
triangles			{return TRIANGLE;}
boundary			{return BOUNDARY;}
hole				{return HOLE;}
generation{ws}description	{return PROBLEM;}


%{
/* Functions */
%}

sin				{return SIN;}
cos				{return COS;}
tan				{return TAN;}

%{
/* Numbers */
%}

^[ \t]*{digit}+			{yylval.i = atoi (yytext); return BOLINTEGER;}
{digit}+			{yylval.i = atoi (yytext); return INTEGER;}
{digit}+{exp}			{yylval.d = atof (yytext); return DOUBLE;}
{digit}+\.{digit}*{exp}?	{yylval.d = atof (yytext); return DOUBLE;}
{digit}*\.{digit}+{exp}?	{yylval.d = atof (yytext); return DOUBLE;}


%{
/* Comments or remaining preprocessor lines */
%}

#[^\n]*$			{}
"/*"				{char c;
			 	 while (1) {
				    while ((c = input ( )) != '*' && c > 0);
				    if (c <= 0 || (c = input ( )) == '/')
					break;
				    unput (c);
				 }}


%{
/* Strings and single characters */
%}

^[ \t]*[^- \t\n=\[\]\",+*/()#]+	{yylval.s = strdup (yytext); return BOLSTRING;}
^[ \t]*\"[^"]*\"		{yylval.s = strdup (yytext + 1);
				 yylval.s [yyleng - 2] = 0; return BOLSTRING;}

[^- \t\n=\[\]\",+*/()#]+	{yylval.s = strdup (yytext); return STRING;}
\"[^"]*\"			{yylval.s = strdup (yytext + 1);
				 yylval.s [yyleng - 2] = 0; return STRING;}

[ \t]				{}
.				{return *yytext;}
\n				{generator.line ++;}
%%


/************************************************************************
 * Function:	 yyerror						*
 *									*
 * Parameters:	 msg - error message					*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 yytext and yychar are used				*
 *		 generator is modified					*
 *									*
 * Description:	 Yyerror is used to write an error message when a	*
 *		 syntax error occurs.					*
 ************************************************************************/

void yyerror (msg)
    char *msg;
{
    extern int yychar;


    if (yychar)
	error ("%s (%s unexpected near line %d)", msg, yytext, generator.line);
    else
	error ("%s (end of input unexpected)", msg);

    generator.numerrors ++;
}


/************************************************************************
 * Function:	 RestartLexer						*
 *									*
 * Parameters:	 fp - pointer to input stream				*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 GetProblem						*
 *									*
 * Global data:	 generator is partially initialized			*
 *									*
 * Description:	 RestartLexer restarts the lexical analyzer by		*
 *		 initializing the file pointer.				*
 ************************************************************************/

void RestartLexer (fp)
    FILE *fp;
{
    static int firsttime = 1;

# ifdef FLEX_SCANNER
    if (!firsttime)
	yyrestart (fp);
    else {
	firsttime = 0;
	yyin = fp;
    }
# else
    yyin = fp;
# endif

    generator.numlines = 0;
    generator.numgrids = 0;
    generator.numtrimeshes = 0;
    generator.line = 0;
}
