omi-eikyo/src/m_tokbuf.c

125 lines
2.4 KiB
C

// Copyright © 2017 Project Golan, all rights reserved.
// See COPYING for more information.
#include "m_tokbuf.h"
#include <string.h>
#include <stdlib.h>
// Static Functions ----------------------------------------------------------|
//
// M_TokBuf_tokProcess
//
static enum M_tkprc M_TokBuf_tokProcess(M_token *tok, void *udata)
{
switch(tok->type) {
default: return tokproc_next;
case tok_eof: return tokproc_done;
case tok_lnend:
case tok_cmtlin: return tokproc_skip;
}
}
//
// M_TokBuf_print
//
static void M_TokBuf_print(M_tkbuf *tb)
{
for(int i = 0; i < tb->tend; i++)
printf("[%i]%i: %p %s%s\n", i, tb->toks[i].type, tb->toks[i].textV,
tb->toks[i].textV, i == tb->tpos ? " <-- cursor is here" : "");
printf("---\n");
}
// Extern Functions ----------------------------------------------------------|
//
// M_TokBuf_Ctor
//
void M_TokBuf_Ctor(M_tkbuf *tb)
{
tb->toks = calloc(tb->bend, sizeof(M_token));
if(!tb->tokProcess) tb->tokProcess = M_TokBuf_tokProcess;
}
//
// M_TokBuf_Dtor
//
void M_TokBuf_Dtor(M_tkbuf *tb)
{
if(tb->toks)
for(int i = 0; i < tb->bend; i++)
M_Vec_clear(tb->toks[i].text);
free(tb->toks);
}
//
// M_TokBuf_Get
//
M_token *M_TokBuf_Get(M_tkbuf *tb)
{
if(++tb->tpos < tb->tend)
return &tb->toks[tb->tpos];
// Free beginning of buffer.
for(int i = 0; i < tb->bbeg; i++) {
M_Vec_clear(tb->toks[i].text);
tb->toks[i] = (M_token){0};
}
// Move end of buffer to beginning.
if(tb->tend)
for(int i = tb->tend - tb->bbeg, j = 0; i < tb->tend; i++, j++)
{
tb->toks[j] = tb->toks[i];
tb->toks[i] = (M_token){0};
}
// Get new tokens.
for(tb->tpos = tb->tend = tb->bbeg; tb->tend < tb->bend; tb->tend++)
{
skip:
M_Tk_Parse(tb->fp, &tb->toks[tb->tend]);
switch(tb->tokProcess(&tb->toks[tb->tend], tb->udata)) {
case tokproc_next: break;
case tokproc_done: goto done;
case tokproc_skip: goto skip;
}
}
done:
return &tb->toks[tb->tpos];
}
//
// M_TokBuf_UnGet
//
M_token *M_TokBuf_UnGet(M_tkbuf *tb)
{
return &tb->toks[tb->tpos--];
}
//
// M_TokBuf_ReGet
//
M_token *M_TokBuf_ReGet(M_tkbuf *tb)
{
return &tb->toks[tb->tpos];
}
//
// M_TokBuf_Drop
//
bool M_TokBuf_Drop(M_tkbuf *tb, M_tokty t)
{
if(M_TokBuf_Get(tb)->type != t)
{M_TokBuf_UnGet(tb); return false;}
else
return true;
}
// EOF