/* (C) Copyright International Business Machines Corporation 23 January */
/* 1990.  All Rights Reserved. */
/*  */
/* See the file USERAGREEMENT distributed with this software for full */
/* terms and conditions of use. */
/* SCCS Info: @(#)asmlex.lex	1.3 3/13/90 */

%e 4000
%p 10000
%n 2000
%k 500
%a 4000
%o 5000

%{
#include "li.h"

#include "asm.h"
#include "tokens.h"

#include "interpform.cd"

#define Notprintable(c) (c < ' ' or c > '~')
#define Treturn(x) return(x)
#define DQUOTE '"'

void yy_grab_str();
void skip_comment();

char *yymembuf;

int yylineno;

%}

letter		[a-zA-Z_]
digit		[0-9]
symbol		{letter}({letter}|{digit})*
sign            [-+]
integer		{sign}?{digit}+
exponent	[Ee]{sign}?{digit}+

Ada_comment	"--"
C_comment	"/*"

squote		"'"
dquote		\"

whitespace      [ \t]+
newline		\n
error           .

%%

include(oplex.lex)
include(exceps.lex)

process		Treturn(PROCESS);
end		Treturn(END);
true		Treturn(TRUE);
false		Treturn(FALSE);
pair		Treturn(PAIR);
table		Treturn(TABLE);
typeid		Treturn(TYPENAME);
exception	Treturn(EXCEPTION);
exitid		Treturn(EXITID);
handlers	Treturn(HANDLERS);
selectarms	Treturn(SELECTARMS);
others		Treturn(OTHERS);
using		Treturn(USING);
linking		Treturn(LINKING);

{symbol}	{ yylval.string = yytext; Treturn(IDENTIFIER); }
{integer}	{ yylval.integer = atoi(yytext); Treturn(INTEGER); }
{dquote}        { yy_grab_str(yytext, YYLMAX, DQUOTE); yylval.string = yytext; 
		  Treturn(STRING); }

{Ada_comment}   { skip_comment("\n"); }
{C_comment}	{ skip_comment("*/"); }

"*"		Treturn('*');
","		Treturn(',');
";"		Treturn(';');
"!"		Treturn('!');
":"		Treturn(':');
"."		Treturn('.');
"("		Treturn('(');
")"		Treturn(')');

{whitespace}    ;
{newline}	;
{error}         Treturn(ERROR);

%%

void
lexinit()
{
    yylineno = 1;
}


/* yy_grab_str - the regular expressions used by lex are maximal.  can't
   match a delimited string with "<beginning>.*<end>" because ".*" will eat
   all the input.  this routine parses a delimited string and stops at the
   first occurrence of the end delimiter. 
*/

void
yy_grab_str(strbuf, bufsiz, delim)
char *strbuf;			/* buffer to hold string or name we grab */
int bufsiz;			/* size of largest string or name we can build */
char delim;			/* end of string or name character */
{
  char c;
  int ic;
  int chars_in_buf = 0;		/* total number of chars in buffer */


  while ((ic = input()) != EOF &&
	 chars_in_buf < bufsiz )
    {
      c = (char) ic;
      if (Notprintable(c)) {
	  yyerror("Newlines may not be imbedded in string literals");
	  /* set error flag */
      }

      if (c == delim) 
	{
	  if ((ic = input()) == EOF) /* peek ahead one char */
	    break;
	  c = (char) ic;
	  if (c == delim)	/* doubled delim?  count it as one. */
	    {
	      strbuf[chars_in_buf++] = c;
	      continue;
	    }
	  else
	    {
	      unput(c);		/* real delim.  restore peek-aboo */
              break;
	    }
	}
      strbuf[chars_in_buf++] = c;
    }
  strbuf[chars_in_buf] = '\0';
}
    


/* skip_comment - again, because lex wants maximal regular expression matches
   this routine is used to skip over contents of comments.  almost like 
   yy_grab_str but doesn't worry about doubled end of string delimiters 
   representing a single occurrence of the delimiter, etc.
*/

void
skip_comment(end_of_comment)
char *end_of_comment;
{
  char c,*ceoc;
  int ic;

  ceoc = end_of_comment;	/* points to eoc char we want to match */
  do 
      {
	if ((ic = input()) == EOF)
	  return;
	c = (char) ic;
	if (c != *ceoc++)	/* match?  if yes, look at next eoc char */
	  ceoc = end_of_comment; /* if no, abort and start from beginning */
      }
  while (*ceoc);		/* stop if we match entire eoc string */
}

