%{
/*
    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.				*
 ************************************************************************/

# if !defined (__hpux) && !defined (__GNUC__)
# include <stdlib.h>
# else
double atof ( );
# endif
# include <string.h>
# include "problem.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.						*
 ************************************************************************/

%}
%p 4000
%a 5300
%o 9500


letter				[a-zA-Z_]
digit				[0-9]
identifier			{letter}({letter}|{digit})*
exp				([eE][+-]?{digit}+)
optws				[ \t\n]*
ws				[ \t\n]+
par				[pP][aA][rR][aA][lL][lL][eE][lL]
per				[pP][eE][rR][pP]
perp				{per}([eE][nN][dD][iI][cC][uU][lL][aA][rR])?
local				{optws}[lL][oO][cC][aA][lL]
global				{optws}[gG][lL][oO][bB][aA][lL]
fixed				{optws}[cC][ \t\n]
free				{optws}[uU][ \t\n]
hinge				{optws}[hH]([iI][nN][gG][eE])?
%%

%{
/* Assignments */
%}

title{optws}=			{return TITLE_EQ;}
nodes{optws}=			{return NODES_EQ;}
elements{optws}=		{return ELEMENTS_EQ;}
material{optws}=		{return MATERIAL_EQ;}
force{optws}=			{return FORCE_EQ;}
constraint{optws}=		{return CONSTRAINT_EQ;}
values{optws}=			{return VALUES_EQ;}
load{optws}=			{return LOAD_EQ;}
[Xx]{optws}=			{return X_EQ;}
[Yy]{optws}=			{return Y_EQ;}
[Zz]{optws}=			{return Z_EQ;}
[Ee]{optws}=			{return E_EQ;}
[Ii][Xx]{optws}=		{return IX_EQ;}
[Ii][Yy]{optws}=		{return IY_EQ;}
[Ii][Zz]{optws}=		{return IZ_EQ;}
[Aa]{optws}=			{return A_EQ;}
[Jj]{optws}=			{return J_EQ;}
[Gg]{optws}=			{return G_EQ;}
[Tt]{optws}=			{return T_EQ;}
[Kk][Aa][Pp][Pp][Aa]{optws}=	{return KAPPA_EQ;}
[Rr][Hh][Oo]{optws}=		{return RHO_EQ;}
[Nn][Uu]{optws}=		{return NU_EQ;}
[Ff][Xx]{optws}=		{return FX_EQ;}
[Ff][Yy]{optws}=		{return FY_EQ;}
[Ff][Zz]{optws}=		{return FZ_EQ;}
[Mm][Xx]{optws}=		{return MX_EQ;}
[Mm][Yy]{optws}=		{return MY_EQ;}
[Mm][Zz]{optws}=		{return MZ_EQ;}
[Tt][Xx]{optws}={fixed}		{return TX_FIXED;}
[Tt][Yy]{optws}={fixed}		{return TY_FIXED;}
[Tt][Zz]{optws}={fixed}		{return TZ_FIXED;}
[Rr][Xx]{optws}={fixed}		{return RX_FIXED;}
[Rr][Yy]{optws}={fixed}		{return RY_FIXED;}
[Rr][Zz]{optws}={fixed}		{return RZ_FIXED;}
[Tt][Xx]{optws}={free}		{return TX_FREE;}
[Tt][Yy]{optws}={free}		{return TY_FREE;}
[Tt][Zz]{optws}={free}		{return TZ_FREE;}
[Rr][Xx]{optws}={free}		{return RX_FREE;}
[Rr][Yy]{optws}={free}		{return RY_FREE;}
[Rr][Zz]{optws}={free}		{return RZ_FREE;}
[Rr][Xx]{optws}={hinge}		{return RX_HINGE;}
[Rr][Yy]{optws}={hinge}		{return RY_HINGE;}
[Rr][Zz]{optws}={hinge}		{return RZ_HINGE;}
[Tt][Xx]{optws}=		{return TX_EXPR;}
[Tt][Yy]{optws}=		{return TY_EXPR;}
[Tt][Zz]{optws}=		{return TZ_EXPR;}
[Rr][Xx]{optws}=		{return RX_EXPR;}
[Rr][Yy]{optws}=		{return RY_EXPR;}
[Rr][Zz]{optws}=		{return RZ_EXPR;}
direction{optws}={local}[xX]	{yylval.i = LocalX; return DIR_EQ;}
direction{optws}={local}[yY]	{yylval.i = LocalY; return DIR_EQ;}
direction{optws}={local}[zZ]	{yylval.i = LocalZ; return DIR_EQ;}
direction{optws}={global}[xX]	{yylval.i = GlobalX; return DIR_EQ;}
direction{optws}={global}[yY]	{yylval.i = GlobalY; return DIR_EQ;}
direction{optws}={global}[zZ]	{yylval.i = GlobalZ; return DIR_EQ;}
direction{optws}={optws}{perp}	{yylval.i = Perpendicular; return DIR_EQ;}
direction{optws}={optws}{par}	{yylval.i = Parallel; return DIR_EQ;}


%{
/* Keywords */
%}

end				{return END;}
nodes				{return NODES;}
forces				{return FORCES;}
constraints			{return CONSTRAINTS;}
problem{ws}description		{return PROBLEM;}
material{ws}properties		{return MATERIALS;}
distributed{ws}loads		{return DISTRIBUTED;}
{identifier}{ws}elements	{yylval.s = strdup (yytext); return ELEMENTS;}


%{
/* Functions */
%}

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


%{
/* 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				{problem.line ++;}
%%


/************************************************************************
 * Function:	 yyerror						*
 *									*
 * Parameters:	 msg - error message					*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 yyparse						*
 *									*
 * Global data:	 yytext and yychar are used				*
 *		 problem 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, problem.line);
    else
	error ("%s (end of input unexpected)", msg);

    problem.numerrors ++;
}


/************************************************************************
 * Function:	 RestartLexer						*
 *									*
 * Parameters:	 fp - pointer to input stream				*
 *									*
 * Return value: none							*
 *									*
 * Calls:	 none							*
 *									*
 * Called by:	 GetProblem						*
 *									*
 * Global data:	 problem 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

    problem.title = "";
    problem.numnodes = 0;
    problem.numelements = 0;
    problem.numerrors = 0;
    problem.line = 0;
    problem.nodes = NULL;
    problem.elements = NULL;
}

# undef yywrap
int yywrap ( ) {return 1;}
