%{
/*
 * Copyright (C) 1991-1999 Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de)
 *
 * This file is part of NASE A60.
 * 
 * NASE A60 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, or (at your option)
 * any later version.
 *
 * NASE A60 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 NASE A60; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * a60-lex.l:					aug '90
 *
 * Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de)
 *
 * this part is obsolete and replaced by a60-scan.[ch]
 * if you like to use this, complete the keyword scanning (only
 * 'begin' and 'end' are enclosed)
 */

/*
 * special for including "comm.h" :
 */
#define THIS_IS_A60_LEX
#include "comm.h"
#undef THIS_IS_A60_LEX

#include "a60.h"
#include "util.h"
/*
 * this should be ``a60-parse.tab.h'' but there are some systems ...
 * so the names are still short...
 */
#include "a60-ptab.h"


/*
 * better use ctype.h ...
 */
#define misupper(c)	((c) >= 'A' && (c) <= 'Z')
#define mtolower(c)	((c) - 'A' + 'a')

/* current line number. */
int lineno;

/*
 * flex vs. lex:
 */
#ifdef FLEX_SCANNER

/* forwards: */
static int input();
extern FILE *yyin;

#else /* ! FLEX_SCANNER */

/* forwards: */
static int yywrap ();

#endif /* ! FLEX_SCANNER */


#ifdef lint
/* if they use it - i'll provide it: */
extern _flsbuf ();
#endif


/*
 * initalize lex-module.
 */
void
init_lex ()
{
	lineno = 1;

	yyin = infile;
}


/*
 * scan the real number from the buffer and return them.
 */

static double
scan_real (s)
char *s;
{
	char *fmt = "%le";
	double x;

#ifdef pyr
        fmt = "%lf";
#endif

        if (sscanf (s, fmt, &x) < 1) {
		a60_error (infname, lineno,
		   "INTERNAL: cannot scan from `%s'\n", s);
		xabort ("INTERNAL ERROR");
	}

	if (do_debug)
		printf ("** do_scan_real: `%s' -> %.12g\n", s, x);

	return x;
}


/*
 * convert the scanned string from c-like notation.
 */

static char *
scan_string (s)
char *s;
{
	int i, len;
	char *tmp, *ptr;

	len = strlen(s);
	tmp = NTALLOC(len - 1, char);

	if (*s == '\'')
		s += 2, len -= 4;

	for (i=1, ptr=tmp; i < len-1; i++, ptr++) {
		if (s[i] == '\\') {
			i++;
			if (s[i] == 'n')
				*ptr = '\n';
			else if (s[i] == '\\')
				*ptr = '\\';
			else if (s[i] == '\0')
				break;
			else
				*ptr = s[i];
		}
		else
			*ptr = s[i];
	}
	*ptr = '\0';

	return tmp;
}


/*
 * handle this unknown char; skip input til end-of-line.
 */

void
handle_unknown (ch)
int ch;
{
	static int last_line = -1;
	
	if (last_line == lineno)
		return;
	else
		last_line = lineno;

	if (ch >= ' ' && ch <= 'Z')
		 a60_error (infname, lineno,
		    "unknown char `%c' found - skipping to next line\n",
			    ch);
	else
		a60_error (infname, lineno,
		   "unknown char 0x%02x found - skipping to next line\n",
			   ch);
	nerrors++;

	do {
		ch = input();
	} while (ch && ch != '\n');

	lineno++;
}

/* onk. */

%}

%e 2000
%p 3000

word		[a-zA-Z][a-zA-Z0-9 ]*

string		`[^']*'|"'('"[^']*"')'"|\"[^"]*\"

uint		[0-9][0-9]*

ureal		{uint}"."{uint}|"."{uint}

white		" "|"\t"|"\f"|"\r"|"\n"

single		"+"|"-"|"*"|"/"|","|"."|";"|"("|")"

%%

'begin'				return TBEGIN;
'10'				return TTEN;

'end'				return TEND;

{single}			return *yytext;

":"|".."			return ':';
";"|".,"			return ';';
"["|"(/"			return '[';
"]"|"/)"			return ']';
"**"				return TPOW;
":="|".="			return TASSIGN;

"<" 				return TLESS;
">" 				return TGREATER;
"="				return TEQUAL;
"<=" 				return TNOTGREATER;
">="				return TNOTLESS;

{white}*			{ char *s = (char *) yytext;
				  for (; *s; s++)
					  lineno += (*s == '\n');
			  	}

{string}			{ yylval.str = scan_string (yytext);
                                  return STRING;
				}

{ureal}				{  yylval.rtype = scan_real (yytext);
				   return RNUM;
				}

{uint}				{ extern long atol ();
				  yylval.itype = atol (yytext);
				  return INUM;
				}

{word}				{ char *str = xstrdup ((char *) yytext);
				  yylval.str = str;
				  return NAME;
				}

^#!.*				{ if (lineno != 1)
					  yywarning ("directive ignored");
			        }

.				handle_unknown (*yytext & 0xff);

%%


/*
 * error reporting:
 */

void
yyerror(s)
char *s;
{
	nerrors++;
	/*
	 * if there is a ``parse error'' or a ``syntax error''
	 * reported from the skeleton, print the scanned string too.
	 */
	if (! strcmp (s, "parse error")
	    || ! strcmp (s, "syntax error")) {
		a60_error (infname, lineno, "%s (scanned `%s')\n",
			   s, (yytext && *yytext) ? (char *) yytext : "EOF");
		return;
	}
	a60_error (infname, lineno, "%s\n", s);
}

void
yywarning(s)
char *s;
{
	a60_error (infname, lineno, "warning: %s\n", s);
}


#ifndef FLEX_SCANNER

/*
 * EOF is real EOF.
 */
static int
yywrap()
{
	return 1;
}

#endif /* ! FLEX_SCANNER */

/* end of a60-lex.l */
