#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>
#include "debug.h"
#include "lex.h"
int
linit(Lexer *l, int fd, State state)
{
if((l->c=chancreate(sizeof(Tok), 2)) == nil)
return Leof;
if((l->bp = malloc(sizeof(Biobuf))) == nil){
chanfree(l->c);
return Loverflow;
}
if(Binit(l->bp, fd, OREAD) == Beof){
free(l->bp);
chanfree(l->c);
return Leof;
}
l->start = l->pos = 0;
l->cur = l->b;
l->state = state;
return 0;
}
void
lterm(Lexer *l)
{
chanfree(l->c);
Bterm(l->bp);
free(l->bp);
}
long
lnext(Lexer *l)
{
long c;
if(l->pos-l->start > Ltoksize) return Loverflow;
if((c = Bgetrune(l->bp)) == Beof) return Leof;
l->pos++;
*l->cur++ = c;
return c;
}
void
lbackup(Lexer *l)
{
if(l->pos <= l->start) return;
Bungetrune(l->bp);
l->pos--;
l->cur--;
}
long
lpeek(Lexer *l)
{
long c;
c = lnext(l);
lbackup(l);
return c;
}
void
lignore(Lexer *l)
{
l->start = l->pos;
l->cur = l->b;
}
int
laccept(Lexer *l, Rune *s)
{
long c;
if((c = lnext(l)) < 0) return 0;
if(runestrchr(s, c) != nil) return 1;
lbackup(l);
return 0;
}
long
lacceptrun(Lexer *l, Rune *s)
{
long c;
int p, done;
p = l->pos;
while((c = lnext(l)) >= 0 && !(done = !runestrchr(s, c)));
if(done) lbackup(l);
return done ? l->pos-p : Loverflow;
}
long
lacceptuntil(Lexer *l, Rune *s)
{
long c;
int p, done;
p = l->pos;
while((c = lnext(l)) >= 0 && !(done = !!runestrchr(s, c)));
if(done) lbackup(l);
return done ? l->pos-p : Loverflow;
}
void
lemit(Lexer *l, int typ)
{
Tok t;
t.typ = typ;
runestrncpy(t.str, l->b, l->pos-l->start);
t.str[l->pos-l->start] = L'\0';
lignore(l);
send(l->c, &t);
}
Tok
lnexttok(Lexer *l)
{
Tok t;
while(!nbrecv(l->c, &t)) l->state = l->state.fun(l, l->state.aux);
return t;
}
long
llen(Lexer *l)
{
long len;
len = l->pos - l->start;
return len >= 0 && len < Ltoksize ? len : Loverflow;
}
Rune*
lestr(Lexer *l){
Rune *s;
long len;
len = llen(l);
if(len < 0) return nil;
if((s=malloc((len+1)*sizeof(Rune))) == nil) return nil;
runestrncpy(s, l->b, len);
s[len] = L'\0';
return s;
}
|