ref: 8dc7c659e34ad5d244477e01b1ebf4def63be24d
dir: /scan.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include "dat.h"
#include "fns.h"
struct {
Rune spelling;
int id;
} primspecs[] = {
L'+', PrimPlus,
L'-', PrimMinus,
};
Token *
newtok(TokenList *tokens, int tag)
{
Token *new;
tokens->count++;
tokens->tokens = allocextra(tokens, sizeof(Token) * tokens->count);
new = tokens->tokens + (tokens->count-1);
new->tag = tag;
return new;
}
TokenList *
scan(char *buf, char **errp)
{
Rune r;
int n;
TokenList *tokens = alloc(DataTokenList);
Token *tok;
char *cp = buf;
while(*cp){
n = chartorune(&r, cp);
int new = -1;
switch(r){
case L'(': new = TokLparen; break;
case L')': new = TokRparen; break;
case L'[': new = TokLbrack; break;
case L']': new = TokRbrack; break;
case L'{': new = TokLbrace; break;
case L'}': new = TokRbrace; break;
case L'\n': new = TokNewline; break;
case L'⋄': new = TokDiamond; break;
case L'∇': new = TokDel; break;
case L'←': new = TokLarrow; break;
case L';': new = TokSemi; break;
}
if(new != -1){
newtok(tokens, new);
goto next;
}
for(int i = 0; i < nelem(primspecs); i++){
if(r == primspecs[i].spelling){
tok = newtok(tokens, TokPrimitive);
tok->prim = primspecs[i].id;
tok->nameclass = NameclassFunc;
goto next;
}
}
if(isspacerune(r))
goto next;
if(isdigitrune(r)){
char *rest;
vlong num = strtoll(cp, &rest, 10);
n = rest - cp;
tok = newtok(tokens, TokNumber);
tok->num = num;
goto next;
}
if(isalpharune(r)){
char *start = cp;
do{
cp += n;
n = chartorune(&r, cp);
}while(isalpharune(r) || isdigitrune(r));
tok = newtok(tokens, TokName);
usize size = cp - start;
tok->name = malloc(size + 1);
memcpy(tok->name, start, size);
tok->name[size] = 0;
continue;
}
*errp = "scan error";
return nil;
next:
cp += n;
}
newtok(tokens, TokEnd);
return tokens;
}