Added qlang's lexer to parse tokens, not hooked up yet
This commit is contained in:
parent
69baa26d9b
commit
990391144c
3
Makefile
3
Makefile
@ -131,6 +131,9 @@ obj/%.asm.o: %.asm Makefile
|
|||||||
mkdir -p "$(dir $@)"
|
mkdir -p "$(dir $@)"
|
||||||
nasm $(NASMFLAGS) $< -o $@
|
nasm $(NASMFLAGS) $< -o $@
|
||||||
|
|
||||||
|
usb: all
|
||||||
|
sudo dd if=image.hdd of=/dev/sda bs=4M oflag=sync status=progress
|
||||||
|
|
||||||
# Remove object files and the final executable.
|
# Remove object files and the final executable.
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
BIN
obj/src/int.c.o
BIN
obj/src/int.c.o
Binary file not shown.
@ -1,6 +1,9 @@
|
|||||||
obj/src/main.c.o: src/main.c src/../include/limine.h src/acpi.h \
|
obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \
|
||||||
src/common.h src/alloc.h src/apic.h src/map.h src/print.h
|
src/prompt/file.h src/acpi.h src/common.h src/alloc.h src/apic.h \
|
||||||
|
src/map.h src/print.h
|
||||||
src/../include/limine.h:
|
src/../include/limine.h:
|
||||||
|
src/prompt/lex.h:
|
||||||
|
src/prompt/file.h:
|
||||||
src/acpi.h:
|
src/acpi.h:
|
||||||
src/common.h:
|
src/common.h:
|
||||||
src/alloc.h:
|
src/alloc.h:
|
||||||
|
|||||||
BIN
obj/src/main.c.o
BIN
obj/src/main.c.o
Binary file not shown.
@ -66,7 +66,7 @@ void alloc_init() {
|
|||||||
|
|
||||||
for (size_t i = 0; i < mem_req.response->entry_count; i++) {
|
for (size_t i = 0; i < mem_req.response->entry_count; i++) {
|
||||||
struct limine_memmap_entry *entry = mem_req.response->entries[i];
|
struct limine_memmap_entry *entry = mem_req.response->entries[i];
|
||||||
print_memmap_entry(entry);
|
//print_memmap_entry(entry);
|
||||||
|
|
||||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
||||||
if (entry->length > largest_size) {
|
if (entry->length > largest_size) {
|
||||||
|
|||||||
31
src/apic.c
31
src/apic.c
@ -105,15 +105,8 @@ void apic_enable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
volatile u32 *spurious = apic_reg(0xF0);
|
volatile u32 *spurious = apic_reg(0xF0);
|
||||||
print("Reg 0xF0 at 0x");
|
|
||||||
print64((u64)spurious);
|
|
||||||
print("\nSpurious: ");
|
|
||||||
print32(*spurious);
|
|
||||||
// set enable flag
|
// set enable flag
|
||||||
*spurious |= 0x100;
|
*spurious |= 0x100;
|
||||||
print(" after flag: ");
|
|
||||||
print32(*spurious);
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
// TPR = 0 (accept all interrupts)
|
// TPR = 0 (accept all interrupts)
|
||||||
volatile u32 *tpr = apic_reg(0x80);
|
volatile u32 *tpr = apic_reg(0x80);
|
||||||
@ -173,34 +166,10 @@ void ioapic_init() {
|
|||||||
u32 low = ioapic_read(IOAPIC_REG_REDIR(irq));
|
u32 low = ioapic_read(IOAPIC_REG_REDIR(irq));
|
||||||
u32 high = ioapic_read(IOAPIC_REG_REDIR(irq) + 1);
|
u32 high = ioapic_read(IOAPIC_REG_REDIR(irq) + 1);
|
||||||
|
|
||||||
print("Current redirection for IRQ");
|
|
||||||
print8(irq);
|
|
||||||
print(": ");
|
|
||||||
print32(low);
|
|
||||||
print(" ");
|
|
||||||
print32(high);
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
// Configure keyboard - UNMASKED (no IOAPIC_MASKED bit!)
|
// Configure keyboard - UNMASKED (no IOAPIC_MASKED bit!)
|
||||||
low = vect | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG | IOAPIC_ACTIVE_HIGH;
|
low = vect | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG | IOAPIC_ACTIVE_HIGH;
|
||||||
high = (cpu << 24);
|
high = (cpu << 24);
|
||||||
|
|
||||||
ioapic_write(IOAPIC_REG_REDIR(irq), low);
|
ioapic_write(IOAPIC_REG_REDIR(irq), low);
|
||||||
ioapic_write(IOAPIC_REG_REDIR(irq) + 1, high);
|
ioapic_write(IOAPIC_REG_REDIR(irq) + 1, high);
|
||||||
|
|
||||||
low = ioapic_read(IOAPIC_REG_REDIR(irq));
|
|
||||||
high = ioapic_read(IOAPIC_REG_REDIR(irq) + 1);
|
|
||||||
// Verify it worked
|
|
||||||
print("Current redirection for IRQ");
|
|
||||||
print8(irq);
|
|
||||||
print(": ");
|
|
||||||
print32(low);
|
|
||||||
print(" ");
|
|
||||||
print32(high);
|
|
||||||
print("\n");
|
|
||||||
if (low & IOAPIC_MASKED) {
|
|
||||||
print(" [STILL MASKED (BAD)]\n");
|
|
||||||
} else {
|
|
||||||
print(" [UNMASKED (GOOD)]\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,14 +74,16 @@ struct cpu_ctx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cpu_ctx *interrupt_dispatch(struct cpu_ctx *ctx) {
|
struct cpu_ctx *interrupt_dispatch(struct cpu_ctx *ctx) {
|
||||||
|
if(ctx->vect = 0x21) {
|
||||||
|
kbd_handler();
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
print("\n[IRQ ");
|
print("\n[IRQ ");
|
||||||
print8(ctx->vect);
|
print8(ctx->vect);
|
||||||
print("] with message: ");
|
print("] with message: ");
|
||||||
print64(dbg_var);
|
print64(dbg_var);
|
||||||
print("\n");
|
print("\n");
|
||||||
if(ctx->vect == 0x21) {
|
|
||||||
kbd_handler();
|
|
||||||
}
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
src/kbd.c
10
src/kbd.c
@ -73,18 +73,9 @@ char kbd_buffer_getc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void kbd_handler() {
|
void kbd_handler() {
|
||||||
print("KBD HANDLER CALLED: scancode: ");
|
|
||||||
|
|
||||||
u8 scancode = inb(PS2_DATA_PORT);
|
u8 scancode = inb(PS2_DATA_PORT);
|
||||||
|
|
||||||
|
|
||||||
print8(scancode);
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
bool released = (scancode & 0x80);
|
bool released = (scancode & 0x80);
|
||||||
scancode &= 0x7F;
|
scancode &= 0x7F;
|
||||||
|
|
||||||
|
|
||||||
switch(scancode) {
|
switch(scancode) {
|
||||||
case 0x2A:
|
case 0x2A:
|
||||||
case 0x36:
|
case 0x36:
|
||||||
@ -124,7 +115,6 @@ void kbd_handler() {
|
|||||||
kbd_buffer_putc(c);
|
kbd_buffer_putc(c);
|
||||||
}
|
}
|
||||||
printn(&c, 1);
|
printn(&c, 1);
|
||||||
print("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
80
src/main.c
80
src/main.c
@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
#include "../include/limine.h"
|
#include "../include/limine.h"
|
||||||
|
|
||||||
|
#include "prompt/lex.h"
|
||||||
|
#include "prompt/file.h"
|
||||||
|
void print_tok(struct token* tok);
|
||||||
|
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
@ -193,61 +197,41 @@ void kmain() {
|
|||||||
apic_enable();
|
apic_enable();
|
||||||
print("APIC Enabled\n");
|
print("APIC Enabled\n");
|
||||||
ioapic_init();
|
ioapic_init();
|
||||||
|
const char* src[] = {
|
||||||
|
"u8 main(u32 x) {\n",
|
||||||
|
" u16 y = x + 16;\n",
|
||||||
|
" u8 z = x * y;\n",
|
||||||
|
" return z; }\n"
|
||||||
|
};
|
||||||
|
|
||||||
if (!test_if_mapped((u64)apic_reg(0))) {
|
const char* name = "prompt> ";
|
||||||
print("Mapping APIC registers failed :(\n");
|
struct file input = {
|
||||||
|
.row = 0,
|
||||||
|
.col = 0,
|
||||||
|
.rows = 4,
|
||||||
|
.lines = (char**)src,
|
||||||
|
.name = name,
|
||||||
|
.tokens = NULL,
|
||||||
|
.tail = &input.tokens,
|
||||||
|
};
|
||||||
|
|
||||||
|
int res = lex(&input);
|
||||||
|
|
||||||
|
print("Result from lexing: ");
|
||||||
|
print8(res);
|
||||||
|
|
||||||
|
if(res != 0) {
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 id = *apic_reg(0x20);
|
struct token* token = input.tokens;
|
||||||
print("LAPIC ID: ");
|
|
||||||
print32(id);
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
print("Enabling keyboard\n");
|
for(;token; token = token->next) {
|
||||||
enable_ps2_keyboard_interrupts();
|
print_tok(token);
|
||||||
|
}
|
||||||
|
|
||||||
outb(0x64, 0x20); // Read config
|
|
||||||
while (!(inb(0x64) & 0x01))
|
|
||||||
;
|
|
||||||
u8 config = inb(0x60);
|
|
||||||
|
|
||||||
|
|
||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
print("Press a key NOW...\n");
|
|
||||||
|
|
||||||
volatile u32 *tpr = apic_reg(0x80);
|
|
||||||
print("TPR: 0x");
|
|
||||||
print32(*tpr);
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
print("PS/2 config: 0x");
|
|
||||||
print8(config);
|
|
||||||
if (!(config & 0x01)) {
|
|
||||||
print("\nProblem: Bit 0 is 0 (interrupt disabled)\n");
|
|
||||||
} else {
|
|
||||||
print("\nOK: Bit 0 is 1 (interrupt enabled)\n");
|
|
||||||
}
|
|
||||||
print("Press keys (polling test)...\n");
|
|
||||||
while (1) {
|
|
||||||
if (inb(0x64) & 0x01) { // Data available
|
|
||||||
u8 code = inb(0x60);
|
|
||||||
print("Scan code: 0x");
|
|
||||||
print8(code);
|
|
||||||
print("\n");
|
|
||||||
volatile u32 *irr = apic_reg(0x210);
|
|
||||||
print32(*irr);
|
|
||||||
irr = apic_reg(0x200); // IRR bits 31:0
|
|
||||||
u32 *isr = apic_reg(0x100); // ISR bits 31:0
|
|
||||||
|
|
||||||
print("IRR: ");
|
|
||||||
print32(*irr);
|
|
||||||
print(" ISR: ");
|
|
||||||
print32(*isr);
|
|
||||||
print("\n");
|
|
||||||
if (code == 0x01)
|
|
||||||
break; // ESC
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/prompt/file.h
Normal file
16
src/prompt/file.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef FILE_H_
|
||||||
|
#define FILE_H_
|
||||||
|
|
||||||
|
struct token;
|
||||||
|
|
||||||
|
struct file {
|
||||||
|
int row;
|
||||||
|
int col;
|
||||||
|
int rows;
|
||||||
|
char** lines;
|
||||||
|
const char* name;
|
||||||
|
struct token* tokens;
|
||||||
|
struct token** tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
43
src/prompt/iden.c
Normal file
43
src/prompt/iden.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../print.h"
|
||||||
|
#include "iden.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct iden identbl[MAX_IDEN];
|
||||||
|
|
||||||
|
static size_t identbl_len = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static bool strneq(const char* l, const char* r, size_t n) {
|
||||||
|
for(size_t i = 0; i < n; i++) {
|
||||||
|
if(r[i] != l[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t register_iden(const char* data, size_t len, uint64_t hash) {
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < identbl_len; i++) {
|
||||||
|
if(hash == identbl[i].hash &&
|
||||||
|
identbl[i].len == len &&
|
||||||
|
strneq(data, identbl[i].data, len)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(identbl_len >= MAX_IDEN) {
|
||||||
|
print("Out of space for identifiers!");
|
||||||
|
hang();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
identbl_len++;
|
||||||
|
identbl[i].hash = hash;
|
||||||
|
identbl[i].len = len;
|
||||||
|
memcpy(identbl[i].data, data, len);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
20
src/prompt/iden.h
Normal file
20
src/prompt/iden.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef IDEN_H_
|
||||||
|
#define IDEN_H_
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAX_IDEN_SIZE 240
|
||||||
|
#define MAX_IDEN (1024*4)
|
||||||
|
struct iden {
|
||||||
|
size_t len;
|
||||||
|
u64 hash;
|
||||||
|
char* data[MAX_IDEN_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct iden identbl[MAX_IDEN];
|
||||||
|
|
||||||
|
size_t register_iden(const char* data, size_t len, uint64_t hash);
|
||||||
|
|
||||||
|
#endif
|
||||||
251
src/prompt/lex.c
Normal file
251
src/prompt/lex.c
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "iden.h"
|
||||||
|
#include "lex.h"
|
||||||
|
#include "../print.h"
|
||||||
|
|
||||||
|
static int lex_error(struct file* state, const char* err) {
|
||||||
|
print(state->name);
|
||||||
|
print16(state->row+1);
|
||||||
|
print16(state->col+1);
|
||||||
|
print(err);
|
||||||
|
print("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t strlen(const char* str) {
|
||||||
|
size_t len = 0;
|
||||||
|
while(*(str++))
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool strneq(const char* l, const char* r, size_t n) {
|
||||||
|
for(size_t i = 0; i < n; i++) {
|
||||||
|
if(r[i] != l[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* index(char* str, int ch) {
|
||||||
|
for(;*str && *str != ch; str++)
|
||||||
|
;
|
||||||
|
return *str?str : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_TOK (1024*1024)
|
||||||
|
struct token token_pool[MAX_TOK];
|
||||||
|
size_t token_next = 0;
|
||||||
|
|
||||||
|
static struct token* tok(enum tokentype type, struct file* state, int col, void* val) {
|
||||||
|
struct token* ret = &token_pool[token_next];
|
||||||
|
if(++token_next >= MAX_TOK) {
|
||||||
|
print("OUT OF TOKENS!!!!");
|
||||||
|
hang();
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->type = type;
|
||||||
|
ret->row = state->row;
|
||||||
|
ret->col = col;
|
||||||
|
ret->file = state;
|
||||||
|
ret->next = NULL;
|
||||||
|
ret->len = state->col-col;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case TOK_OP:
|
||||||
|
ret->op = *(enum op*)val;
|
||||||
|
break;
|
||||||
|
case TOK_KEYWORD:
|
||||||
|
ret->keyword = *(enum keyword*)val;
|
||||||
|
break;
|
||||||
|
case TOK_NUM:
|
||||||
|
ret->num = *(int64_t*)val;
|
||||||
|
break;
|
||||||
|
case TOK_IDEN:
|
||||||
|
ret->iden = *(size_t*)val;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isdigit(int ch) {
|
||||||
|
return (ch <= '9' && ch >= '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isxdigit(int ch) {
|
||||||
|
return ((ch <= '9' && ch >= '0') || (ch <= 'F' && ch >= 'A') || (ch <= 'F' && ch >= 'A'));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isalpha(int ch) {
|
||||||
|
return (ch <= 'z' && ch >= 'a')
|
||||||
|
|| (ch <= 'Z' && ch >= 'A');
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isalnum(int ch) {
|
||||||
|
return isdigit(ch) || isalpha(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int toupper(int ch) {
|
||||||
|
if(ch >= 'a' && ch <= 'z')
|
||||||
|
ch += 'A'-'a';
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tolower(int ch) {
|
||||||
|
if(ch >= 'A' && ch <= 'Z')
|
||||||
|
ch += 'a'-'A';
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cribbed from musl
|
||||||
|
static bool isspace(int ch) {
|
||||||
|
return ch == ' ' || (unsigned)ch-'\t' < 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_num(struct file* state, int save, int sign) {
|
||||||
|
int64_t num = 0;
|
||||||
|
int ch = state->lines[state->row][state->col];
|
||||||
|
if(ch == '0' && state->lines[state->row][state->col+1] == 'x') {
|
||||||
|
state->col+=2;
|
||||||
|
if(!isdigit(state->lines[state->row][state->col])) {
|
||||||
|
lex_error(state, "expected hexadecimal digits in hex literal");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
while(isxdigit(state->lines[state->row][state->col])) {
|
||||||
|
num <<= 4;
|
||||||
|
ch = toupper(state->lines[state->row][state->col]);
|
||||||
|
|
||||||
|
if(ch <= '9') {
|
||||||
|
num += (ch - '0');
|
||||||
|
} else {
|
||||||
|
num += (ch - 'A' + 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while(isdigit(state->lines[state->row][state->col])) {
|
||||||
|
num *= 10;
|
||||||
|
num += state->lines[state->row][state->col] - '0';
|
||||||
|
state->col++;
|
||||||
|
}
|
||||||
|
if(isalpha(state->lines[state->row][state->col])) {
|
||||||
|
lex_error(state, "invalid decimal digit in decimal literal");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
num *= sign;
|
||||||
|
*state->tail = tok(TOK_NUM, state, save, &num);
|
||||||
|
state->tail = &((*state->tail)->next);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lexing
|
||||||
|
number :- [0-9]+ | 0x[0-9A-Fa-f]+
|
||||||
|
keyword :- 'if' | 'else'
|
||||||
|
identifier :- [A-z_][0-9A-z_]*
|
||||||
|
operator :- .....
|
||||||
|
*/
|
||||||
|
int lex(struct file* state) {
|
||||||
|
if(state->row >= state->rows)
|
||||||
|
return 0;
|
||||||
|
while(isspace(state->lines[state->row][state->col])) {
|
||||||
|
if(state->lines[state->row][state->col] == '\n') {
|
||||||
|
state->col = 0;
|
||||||
|
state->row++;
|
||||||
|
if(state->row >= state->rows)
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
state->col++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state->lines[state->row][state->col] == '/' && state->lines[state->row][state->col+1] == '*') {
|
||||||
|
state->col += 2;
|
||||||
|
while(!(state->lines[state->row][state->col] == '*' && state->lines[state->row][state->col+1] == '/')) {
|
||||||
|
if(state->lines[state->row][state->col] == '\n') {
|
||||||
|
state->col = -1;
|
||||||
|
state->row++;
|
||||||
|
if(state->row >= state->rows)
|
||||||
|
return lex_error(state, "unexpected EOF, comment not closed");
|
||||||
|
}
|
||||||
|
state->col++;
|
||||||
|
}
|
||||||
|
state->col += 2;
|
||||||
|
if(state->lines[state->row][state->col] == '\n') {
|
||||||
|
state->row++;
|
||||||
|
state->col = 0;
|
||||||
|
}
|
||||||
|
return lex(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ch = state->lines[state->row][state->col];
|
||||||
|
int nextch = state->lines[state->row][state->col+1];
|
||||||
|
|
||||||
|
/* single line comment */
|
||||||
|
if(ch == nextch && ch == '/') {
|
||||||
|
state->row++;
|
||||||
|
state->col = 0;
|
||||||
|
return lex(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int save = state->col;
|
||||||
|
|
||||||
|
if(ch == '-' && isdigit(state->lines[state->row][state->col+1])) {
|
||||||
|
state->col++;
|
||||||
|
int e = parse_num(state, save, -1);
|
||||||
|
return e + lex(state);
|
||||||
|
} else if(isdigit(ch)) {
|
||||||
|
int e = parse_num(state, save, 1);
|
||||||
|
return e + lex(state);
|
||||||
|
} else if(isalpha(ch) || ch == '_') {
|
||||||
|
size_t len = 0;
|
||||||
|
char* str = &state->lines[state->row][state->col];
|
||||||
|
u64 hash = 0xcbf29ce484222325;
|
||||||
|
while(state->lines[state->row][state->col] == '_' || isalnum(state->lines[state->row][state->col])) {
|
||||||
|
hash = (hash ^ state->lines[state->row][state->col]) * 0x100000001b3;
|
||||||
|
len++;
|
||||||
|
state->col++;
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < sizeof(keywords)/sizeof(char*); i++) {
|
||||||
|
if(strlen(keywords[i]) == len && strneq(keywords[i], str, len)) {
|
||||||
|
*state->tail = tok(TOK_KEYWORD, state, save, &i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!*state->tail) {
|
||||||
|
size_t idx = register_iden(str, len, hash);
|
||||||
|
*state->tail = tok(TOK_IDEN, state, save, &idx);
|
||||||
|
}
|
||||||
|
} else if(index("+-/%*|&^~><=!",state->lines[state->row][state->col])) {
|
||||||
|
for(int i = 0; (size_t)i < sizeof(ops)/sizeof(char*); i++) {
|
||||||
|
if(strneq(&state->lines[state->row][state->col], ops[i], strlen(ops[i]))) {
|
||||||
|
state->col += strlen(ops[i]);
|
||||||
|
*state->tail = tok(TOK_OP, state, save, &i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(index("[({,;})]", state->lines[state->row][state->col])) {
|
||||||
|
state->col++;
|
||||||
|
*state->tail = tok(state->lines[state->row][state->col-1], state, save, NULL);
|
||||||
|
} else {
|
||||||
|
lex_error(state, "unrecognized character");
|
||||||
|
print("Character: (0x");
|
||||||
|
u8 ch = state->lines[state->row][state->col];
|
||||||
|
print8(ch);
|
||||||
|
print(") '");
|
||||||
|
printn(&ch,1);
|
||||||
|
print("\n");
|
||||||
|
state->col++;
|
||||||
|
return 1 + lex(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
state->tail = &(*state->tail)->next;
|
||||||
|
|
||||||
|
return lex(state);
|
||||||
|
}
|
||||||
143
src/prompt/lex.h
Normal file
143
src/prompt/lex.h
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#ifndef LEX_H_
|
||||||
|
#define LEX_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
enum tokentype {
|
||||||
|
TOK_NUM,
|
||||||
|
TOK_IDEN,
|
||||||
|
TOK_KEYWORD,
|
||||||
|
TOK_OP,
|
||||||
|
TOK_SEMICOLON = ';',
|
||||||
|
TOK_COMMA = ',',
|
||||||
|
TOK_LBRACKET = '[',
|
||||||
|
TOK_RBRACKET = ']',
|
||||||
|
TOK_LPAREN = '(',
|
||||||
|
TOK_RPAREN = ')',
|
||||||
|
TOK_LBRACE = '{',
|
||||||
|
TOK_RBRACE = '}',
|
||||||
|
};
|
||||||
|
|
||||||
|
enum keyword {
|
||||||
|
KEY_VOID,
|
||||||
|
KEY_U8,
|
||||||
|
KEY_I8,
|
||||||
|
KEY_U16,
|
||||||
|
KEY_I16,
|
||||||
|
KEY_U32,
|
||||||
|
KEY_I32,
|
||||||
|
KEY_U64,
|
||||||
|
KEY_I64,
|
||||||
|
KEY_IF,
|
||||||
|
KEY_ELSE,
|
||||||
|
KEY_WHILE,
|
||||||
|
KEY_FOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* keywords[] = {
|
||||||
|
"void",
|
||||||
|
"u8",
|
||||||
|
"i8",
|
||||||
|
"u16",
|
||||||
|
"i16",
|
||||||
|
"u32",
|
||||||
|
"i32",
|
||||||
|
"u64",
|
||||||
|
"i64",
|
||||||
|
"if",
|
||||||
|
"else",
|
||||||
|
"while",
|
||||||
|
"for"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* ops[] = {
|
||||||
|
"==",
|
||||||
|
"=",
|
||||||
|
"!=",
|
||||||
|
"!",
|
||||||
|
"+=",
|
||||||
|
"+",
|
||||||
|
"-=",
|
||||||
|
"-",
|
||||||
|
"*=",
|
||||||
|
"*",
|
||||||
|
"/=",
|
||||||
|
"/",
|
||||||
|
"%=",
|
||||||
|
"%",
|
||||||
|
"<<=",
|
||||||
|
"<<",
|
||||||
|
">>=",
|
||||||
|
">>",
|
||||||
|
"<=",
|
||||||
|
">=",
|
||||||
|
"<",
|
||||||
|
">",
|
||||||
|
"~",
|
||||||
|
"&&",
|
||||||
|
"&=",
|
||||||
|
"&",
|
||||||
|
"||",
|
||||||
|
"|=",
|
||||||
|
"|",
|
||||||
|
"^=",
|
||||||
|
"^"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum op {
|
||||||
|
OP_EQ,
|
||||||
|
OP_ASSGN,
|
||||||
|
OP_NOTEQ,
|
||||||
|
OP_LNOT,
|
||||||
|
OP_ADDASSGN,
|
||||||
|
OP_ADD,
|
||||||
|
OP_SUBASSGN,
|
||||||
|
OP_MINUS,
|
||||||
|
OP_MULASSGN,
|
||||||
|
OP_STAR,
|
||||||
|
OP_DIVASSGN,
|
||||||
|
OP_DIV,
|
||||||
|
OP_MODASSGN,
|
||||||
|
OP_MOD,
|
||||||
|
OP_LSHIFTASSGN,
|
||||||
|
OP_LSHIFT,
|
||||||
|
OP_RSHIFTASSGN,
|
||||||
|
OP_RSHIFT,
|
||||||
|
OP_LESSEQ,
|
||||||
|
OP_MOREEQ,
|
||||||
|
OP_LESS,
|
||||||
|
OP_MORE,
|
||||||
|
OP_BNOT,
|
||||||
|
OP_LAND,
|
||||||
|
OP_BANDASSGN,
|
||||||
|
OP_BAND,
|
||||||
|
OP_LOR,
|
||||||
|
OP_BORASSGN,
|
||||||
|
OP_BOR,
|
||||||
|
OP_XORASSGN,
|
||||||
|
OP_XOR
|
||||||
|
};
|
||||||
|
|
||||||
|
/* base token type */
|
||||||
|
struct token {
|
||||||
|
struct token* next;
|
||||||
|
/* location information */
|
||||||
|
int row;
|
||||||
|
int col;
|
||||||
|
size_t len;
|
||||||
|
struct file* file;
|
||||||
|
/* token type and union */
|
||||||
|
enum tokentype type;
|
||||||
|
union {
|
||||||
|
int64_t num;
|
||||||
|
size_t iden;
|
||||||
|
enum op op;
|
||||||
|
enum keyword keyword;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int lex(struct file* state);
|
||||||
|
|
||||||
|
#endif
|
||||||
138
src/prompt/print.c
Normal file
138
src/prompt/print.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include "iden.h"
|
||||||
|
#include "lex.h"
|
||||||
|
#include "../print.h"
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
static size_t strlen(const char* str) {
|
||||||
|
size_t len = 0;
|
||||||
|
while(*(str++))
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern u32 fg, bg;
|
||||||
|
|
||||||
|
void print_tok(struct token* tok) {
|
||||||
|
/* header: [file:row:col] */
|
||||||
|
print("[");
|
||||||
|
print(tok->file->name);
|
||||||
|
print(":");
|
||||||
|
if(tok->row + 1 < (1 << 16)) {
|
||||||
|
print16(tok->row + 1);
|
||||||
|
print(":");
|
||||||
|
print16(tok->col + 1);
|
||||||
|
} else {
|
||||||
|
print32(tok->row + 1);
|
||||||
|
print(":");
|
||||||
|
print32(tok->col + 1);
|
||||||
|
}
|
||||||
|
print("] ");
|
||||||
|
|
||||||
|
switch (tok->type) {
|
||||||
|
case TOK_KEYWORD:
|
||||||
|
print("keyword: ");
|
||||||
|
print(keywords[tok->keyword]);
|
||||||
|
print("\n");
|
||||||
|
break;
|
||||||
|
case TOK_NUM:
|
||||||
|
print("number: ");
|
||||||
|
print(" (");
|
||||||
|
print64((unsigned long)tok->num);
|
||||||
|
print("):\n");
|
||||||
|
break;
|
||||||
|
case TOK_IDEN: {
|
||||||
|
struct iden* id = &identbl[tok->iden];
|
||||||
|
print("iden: { .hash = 0x");
|
||||||
|
print32(id->hash);
|
||||||
|
print(", .data = \"");
|
||||||
|
print(*id->data);
|
||||||
|
print("\" (");
|
||||||
|
/* print pointer value as hex */
|
||||||
|
print("ptr"); /* pointer printing omitted; add if needed */
|
||||||
|
print("), .len = ");
|
||||||
|
print32((int)id->len);
|
||||||
|
print(" }:\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOK_OP: {
|
||||||
|
print("operator: ");
|
||||||
|
print(ops[tok->op]);
|
||||||
|
print(" (#");
|
||||||
|
print32(tok->op);
|
||||||
|
print("):\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
/* print single char and hex */
|
||||||
|
char c[2] = { (char)tok->type, 0 };
|
||||||
|
print(c);
|
||||||
|
print(" (0x");
|
||||||
|
print32((unsigned char)tok->type);
|
||||||
|
print("):\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* line with number and separator: "\t%4d | " */
|
||||||
|
print("\t");
|
||||||
|
/* pad row number to width 4 */
|
||||||
|
{
|
||||||
|
char numbuf[8];
|
||||||
|
int len = 0;
|
||||||
|
long r = tok->row + 1;
|
||||||
|
if (r == 0) {
|
||||||
|
numbuf[len++] = '0';
|
||||||
|
} else {
|
||||||
|
long tmp = r;
|
||||||
|
char rev[8];
|
||||||
|
int rp = 0;
|
||||||
|
while (tmp) {
|
||||||
|
rev[rp++] = '0' + (tmp % 10);
|
||||||
|
tmp /= 10;
|
||||||
|
}
|
||||||
|
while (rp--) numbuf[len++] = rev[rp];
|
||||||
|
}
|
||||||
|
/* left pad with spaces to width 4 */
|
||||||
|
for (int i = 0; i < 4 - len; ++i) print(" ");
|
||||||
|
/* print number */
|
||||||
|
for (int i = 0; i < len; ++i) {
|
||||||
|
char s[2] = { numbuf[i], 0 };
|
||||||
|
print(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print(" | ");
|
||||||
|
|
||||||
|
/* print text before token */
|
||||||
|
if (tok->col > 0)
|
||||||
|
printn(tok->file->lines[tok->row], tok->col);
|
||||||
|
|
||||||
|
/* print token text */
|
||||||
|
if (tok->len > 0)
|
||||||
|
printn(tok->file->lines[tok->row] + tok->col, tok->len);
|
||||||
|
|
||||||
|
/* print rest of line after token */
|
||||||
|
printn(tok->file->lines[tok->row] + tok->col + tok->len,
|
||||||
|
strlen(tok->file->lines[tok->row] + tok->col + tok->len));
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
/* caret line */
|
||||||
|
print("\t | ");
|
||||||
|
for (int i = 0; i < tok->col; i++) {
|
||||||
|
if (tok->file->lines[tok->row][i] == '\t') {
|
||||||
|
print("\t");
|
||||||
|
} else {
|
||||||
|
print(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u32 savebg = bg, savefg = fg;
|
||||||
|
fg = bg;
|
||||||
|
bg = ~fg;
|
||||||
|
print("^");
|
||||||
|
fg = savefg;
|
||||||
|
bg = savebg;
|
||||||
|
for (size_t i = 1; i < tok->len; i++) print("~");
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user