/* bic_scan - scanner for bigint version of bc
**
** Copyright © 2000,2026 by Jef Poskanzer <jef@mail.acme.com>.
** All rights reserved.
**
** You may use this software however you like as long as you keep my
** name on it and don't sue me.
**
** For commentary on this license please see http://acme.com/license.html
*/

#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>

#include "liblmin.h"

#define YYSTYPE lmin_cellidx
#include "bic.h"

extern int base;
int linenum;

extern YYSTYPE prev_val;

int yylex( void );


int
yylex( void )
    {
    int c, len, i;
    char buf[10000];

    /* Skip whitespace. */
    do {
	c = getchar();
	}
    while ( c == ' ' || c == '\t' );

    if ( c == '\n' )
	{
	++linenum;
	return NEWLINE;
	}
    else if ( isdigit( c ) )
	{
	buf[0] = (char) c;
	len = 1;
	while ( len < sizeof(buf) )
	    {
	    c = getchar();
	    if ( ! isdigit( c ) )
		{
                ungetc( c, stdin );
                break;
                }
            buf[len++] = (char) c;
            }
        buf[len] = '\0';
        yylval = lmin_call( "string-tobigint", lmin_str_make( buf ), lmin_num_integer_make( base ), lmin_nil );
        return NUMBER;
        }
    else if ( isalpha( c ) )
	{
	buf[0] = (char) c;
	len = 1;
	while ( len < sizeof(buf) )
	    {
	    c = getchar();
	    if ( ! ( isalpha( c ) || c == '_' || isdigit( c ) ) )
		{
                ungetc( c, stdin );
                break;
                }
            buf[len++] = (char) c;
            }
        buf[len] = '\0';
	for ( i = 0; i < len; ++i )
	    if ( isupper( buf[i] ) )
		buf[i] = (char) tolower( buf[i] );
        if ( strcmp( buf, "sqrt" ) == 0 )
	    return SQRT;
        else if ( strcmp( buf, "gcd" ) == 0 )
	    return GCD;
        else if ( strcmp( buf, "lcm" ) == 0 )
	    return LCM;
        else if ( strcmp( buf, "modpow" ) == 0 )
	    return MODPOW;
        else if ( strcmp( buf, "modinv" ) == 0 )
	    return MODINV;
        else if ( strcmp( buf, "random" ) == 0 )
	    return RANDOM;
        else if ( strcmp( buf, "isprime" ) == 0 )
	    return ISPRIME;
        else if ( strcmp( buf, "genprime" ) == 0 )
	    return GENPRIME;
        else if ( strcmp( buf, "bits" ) == 0 )
	    return BITS;
        else if ( strcmp( buf, "bit" ) == 0 )
	    return BIT;
        else if ( strcmp( buf, "digits" ) == 0 )
	    return DIGITS;
        else if ( strcmp( buf, "modmult" ) == 0 )
	    return MODMULT;
        else if ( strcmp( buf, "square" ) == 0 )
	    return SQUARE;
        else if ( strcmp( buf, "modsquare" ) == 0 )
	    return MODSQUARE;
	else if ( len == 1 )
	    {
	    yylval = buf[0] - 'a';
	    return VAR;
	    }
	else
	    return '.';	/* junk */
        }
    else if ( c == '.' )
	{
	yylval = prev_val;
	return NUMBER;
	}
    else if ( c == EOF )
	return 0;
    else
	return c;
    }
