scl/src/lexer.c
2025-01-11 10:53:49 -05:00

119 lines
2.5 KiB
C

#include <complex.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include "include/dstr.h"
#include "include/util.h"
#include "include/lexer.h"
ArgArr* argarr_init() {
ArgArr* argarr = malloc(sizeof(ArgArr));
argarr->sz = ARLN * sizeof(AST*);
argarr->ln = 0;
argarr->buf = malloc(argarr->sz);
return argarr;
}
void argarr_destroy(ArgArr* argarr) {
free(argarr->buf);
free(argarr);
}
void argarr_add(ArgArr* argarr, AST* arg) {
if ((argarr->ln + 1) * argarr->sz > argarr->sz) {
argarr->sz *= 2;
argarr->buf = realloc(argarr->buf, argarr->sz);
log_dbgf(
"ArgArr @ %p doubled from %ld to %ld",
argarr,
argarr->sz/2,
argarr->sz
);
}
argarr->buf[argarr->ln++] = arg;
}
int acc_int(int c) {
int value = c - '0';
while (isdigit(*inp)) {
value = value * 10 + (*inp - '0'); // Accumulate value.
inp++;
}
return value;
}
double acc_float(int c) {
int dplaces = 0;
double value = (double)(c - '0');
// Grab everything prior to '.'.
while (isdigit(*inp)) {
value = value * 10 + (*inp - '0'); // Accumulate value.
inp++;
}
if (*inp == '.') {
inp++;
while (isdigit(*inp)) {
value = value * 10 + (*inp - '0'); // Accumulate value.
dplaces++;
inp++;
}
value = value / pow(10, dplaces);
}
return value;
}
char* acc_word(int c) {
Dstr* val = dstr_init();
do {
dstr_appendch(val, *(inp - 1));
inp++;
} while (isalpha(*inp));
dstr_appendch(val, *(inp - 1));
return val->buf;
}
int yylex() {
if (*inp == '\0') return YYEOF;
// Skip all whitespace.
while (*inp == ' ' || *inp == '\t') { inp++; }
// Assign & consume current character.
int c = *inp++;
// Check for NUM.
if (isdigit(c)) {
yylval.fval = acc_float(c); // Set the token value.
return NUM;
}
if (isalpha(c)) {
yylval.strval = acc_word(c);
return CALL;
}
switch (c) {
case '+': return PLUS;
case '\n': return NL;
case '-': return SUB;
case '*': return MULT;
case '/': return DIV;
case '(': return LGROUP;
case ')': return RGROUP;
case ',': return SEP;
default: fprintf(stderr, "Unexpected character: %c\n", c);
}
return 0;
}
void yyerror(char const* s) { fprintf(stderr, "Parse error: %s\n", s); }