%{
/*
 * OpenComal -- a free Comal implementation
 *
 * This file is part of the OpenComal package.
 * (c) Copyright 1992-2024 Jos Visser <josvisser66@gmail.com>
 *
 * The OpenComal package is covered by the GNU General Public
 * License. See doc/LICENSE for more information.
 */


/********** LEXICAL ANALYSIS for OpenComal **********/

#include "pdcglob.h"
#include "pdclexs.h"
#include "pdcparss.h"
#include "pdcmisc.h"

#include <string.h>

/* #define PDCLEX_DEBUG 1 */

PRIVATE char *curline;
PRIVATE int curline_len;
PRIVATE int curline_ptr;

#undef YY_INPUT
#define YY_INPUT(buf, result, maxsize) { \
    int size = maxsize > curline_len - curline_ptr ? curline_len - curline_ptr : maxsize; \
    if (curline_len == curline_ptr) { \
        result = YY_NULL; \
    } else { \
      strncpy(buf, curline + curline_ptr, size); \
      curline_ptr += size; \
      result = size; \
		} \
}


#ifdef PDCLEX_DEBUG
#define RETURN(x) { int i=x; printf("FLEX RETURNS:%d (%s)\n",i,yytext); return i; }
/* #define RETURN(x) { extern void sys_log(char *); sys_log(yytext); return x; } */
#else
#define RETURN(x) return x
#endif

%}

A                       [Aa]
B                       [Bb]
C                       [Cc]
D                       [Dd]
E                       [Ee]
F                       [Ff]
G                       [Gg]
H                       [Hh]
I                       [Ii]
J                       [Jj]
K                       [Kk]
L                       [Ll]
M                       [Mm]
N                       [Nn]
O                       [Oo]
P                       [Pp]
Q                       [Qq]
R                       [Rr]
S                       [Ss]
T                       [Tt]
U                       [Uu]
V                       [Vv]
W                       [Ww]
X                       [Xx]
Y                       [Yy]

number                  [0-9]
letter                  [A-Za-z'_]
netter                  [A-Za-z'_0-9]
exp                     [Ee][\-\+]?{number}+

%%
[ \t]+                                          ;
<<EOF>>                                         RETURN(eolnSYM);
\r?\n                                           RETURN(eolnSYM);
{R}{E}{A}{D}[ \t]+{O}{N}{L}{Y}                  RETURN(read_onlySYM);
{S}{E}{L}{E}{C}{T}[ \t]+{O}{U}{T}{P}{U}{T}      RETURN(select_outputSYM);
{S}{E}{L}{E}{C}{T}[ \t]+{I}{N}{P}{U}{T}         RETURN(select_inputSYM);
{A}{N}{D}[ \t]+{T}{H}{E}{N}                     RETURN(andthenSYM);
{O}{R}[ \t]+{T}{H}{E}{N}                        RETURN(orthenSYM);
\-                                              RETURN(minusSYM);
\*                                              RETURN(timesSYM);
\+                                              RETURN(plusSYM);
\/                                              RETURN(divideSYM);
\^                                              RETURN(powerSYM);
\(                                              RETURN(lparenSYM);
\)                                              RETURN(rparenSYM);
\?                                              RETURN(printSYM);
\=                                              RETURN(eqlSYM);
\:=                                             RETURN(becomesSYM);
\:\+                                            RETURN(becplusSYM);
\:\-                                            RETURN(becminusSYM);
\<                                              RETURN(lssSYM);
\<=                                             RETURN(leqSYM);
\<>                                             RETURN(neqSYM);
!=                                              RETURN(neqSYM);
\>                                              RETURN(gtrSYM);
\>=                                             RETURN(geqSYM);
\:                                              RETURN(colonSYM);
\;                                              RETURN(semicolonSYM);
\,                                              RETURN(commaSYM);
\#                                              RETURN(fileSYM);
\/\/.*                                          RETURN(lex_rem());
\"(\"\"|\\\"|[^\"\n])*\"?                       RETURN(lex_string_flatten());
{letter}{netter}*                               RETURN(lex_id(idSYM));
{letter}{netter}*\#                             RETURN(lex_id(intidSYM));
{letter}{netter}*\$                             RETURN(lex_id(stringidSYM));
{number}+                                       RETURN(lex_intnum());
{number}+{exp}                                  RETURN(lex_floatnum());
{number}+\.{number}+({exp})?                    RETURN(lex_floatnum());
.                                               pars_error("Unexpected character 0x%02x",*yytext);
%%

/* Always returns 1 to indicate that there is not other file to read from */
PUBLIC int yywrap() {
    return 1;
}

PUBLIC int lex_pos() {
    return curline_ptr + yyleng;
}

PUBLIC void lex_setinput(char *line) {
    yyrestart(NULL);

    if (curline) free(curline);

    curline = strdup(line);
    curline_ptr = 0;
    curline_len = strlen(line);
}
