Files
helmetc/libxtools/cllexer.c
Олег Бородин dfd504328d work in progess
2025-10-16 16:09:55 +02:00

172 lines
5.8 KiB
C

/*
*
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
*
*/
#include <string.h>
#include <stdio.h>
#include <cllexer.h>
#define LTYPE_LETTER 1
#define LTYPE_PREFIX 2
#define LTYPE_DELIM 3
#define LTYPE_EOF 4
#define LCONTEXT_START 1
#define LCONTEXT_WORD 2
#define LCONTEXT_DELIM 3
#define LCONTEXT_PREFIX 4
#define LCONTEXT_ENDFL 5
#define LCONTEXT_UNDEF 7
static int get_ltype(char newletter) {
switch (newletter) {
case '-':
case '+':
return LTYPE_PREFIX;
case '=':
return LTYPE_DELIM;
case EOF:
return LTYPE_EOF;
}
return LTYPE_LETTER;
}
void cllexer_init(cllexer_t * lexer, char* arg) {
lexer->arg = arg;
lexer->rpos = 0;
lexer->tpos = 0;
lexer->currcontext = LCONTEXT_START;
lexer->newletter = '\0';
}
static void cllexer_getletter(cllexer_t * lexer, char* arg, int size) {
lexer->newletter = EOF;
if (lexer->rpos < size) {
lexer->newletter = arg[lexer->rpos++];
}
}
int cllexer_gettok(cllexer_t * lexer, char* token) {
char* arg = lexer->arg;
size_t size = strlen(arg);
if (lexer->currcontext == LCONTEXT_START) {
lexer->newletter = arg[lexer->rpos++];
int ltype = get_ltype(lexer->newletter);
int newcontext = LCONTEXT_ENDFL;
switch (ltype) {
case LTYPE_PREFIX:{
newcontext = LCONTEXT_PREFIX;
break;
}
case LTYPE_DELIM:{
newcontext = LCONTEXT_DELIM;
break;
}
case LTYPE_LETTER:{
newcontext = LCONTEXT_WORD;
break;
}
case LTYPE_EOF:{
newcontext = LCONTEXT_ENDFL;
break;
}
}
lexer->currcontext = newcontext;
}
while (lexer->currcontext != LCONTEXT_ENDFL) {
int ltype = get_ltype(lexer->newletter);
switch (lexer->currcontext) {
case LCONTEXT_ENDFL:{
lexer->currcontext = LCONTEXT_ENDFL;
break;
}
case LCONTEXT_DELIM:{
int newcontext = lexer->currcontext;
switch (ltype) {
case LTYPE_PREFIX:
case LTYPE_LETTER:{
newcontext = LCONTEXT_WORD;
break;
}
case LTYPE_EOF:{
newcontext = LCONTEXT_ENDFL;
break;
}
}
if (newcontext != lexer->currcontext) {
lexer->currcontext = newcontext;
token[lexer->tpos] = '\0';
lexer->tpos = 0;
return TOKEN_DELIM;
}
break;
}
case LCONTEXT_PREFIX:{
int newcontext = lexer->currcontext;
switch (ltype) {
case LTYPE_DELIM:{
newcontext = LCONTEXT_DELIM;
break;
}
case LTYPE_LETTER:{
newcontext = LCONTEXT_WORD;
break;
}
case LTYPE_EOF:{
newcontext = LCONTEXT_ENDFL;
break;
}
}
if (newcontext != lexer->currcontext) {
lexer->currcontext = newcontext;
token[lexer->tpos++] = '\0';
lexer->tpos = 0;
return TOKEN_PREF;
}
break;
}
case LCONTEXT_WORD:{
int newcontext = lexer->currcontext;
switch (ltype) {
case LTYPE_DELIM:{
newcontext = LCONTEXT_DELIM;
break;
}
case LTYPE_EOF:{
newcontext = LCONTEXT_ENDFL;
break;
}
}
if (newcontext != lexer->currcontext) {
lexer->currcontext = newcontext;
token[lexer->tpos] = '\0';
lexer->tpos = 0;
return TOKEN_WORD;
}
break;
}
}
token[lexer->tpos++] = lexer->newletter;
cllexer_getletter(lexer, arg, size);
}
lexer->currcontext = LCONTEXT_ENDFL;
lexer->tpos = 0;
token[lexer->tpos] = '\0';
strcpy(token, "EOF");
return TOKEN_ENDF;
}