spl

a Simple Programming Language
Log | Files | Refs

commit c6cc2ba557076fd1385da67a6381e3a427a2124b
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Wed, 19 Nov 2025 21:38:32 +0000

init commit

Diffstat:
A.gitignore | 2++
AMakefile | 12++++++++++++
Alexer.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alexer.h | 29+++++++++++++++++++++++++++++
Anote.md | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aspl.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 272 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +*.o +spl diff --git a/Makefile b/Makefile @@ -0,0 +1,12 @@ +CFLAGS=-ggdb + +SRC = spl.c lexer.c +OBJ = ${SRC:.c=.o} +EXEC = spl + +${EXEC}: ${OBJ} + +${OBJ}: ${SRC} + +clean: + rm -rf ${OBJ} ${EXEC} diff --git a/lexer.c b/lexer.c @@ -0,0 +1,62 @@ +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +#include "lexer.h" + +void +lexErr(lex *l) { + fprintf(stderr, "unexpected token '%c'\n", *l->ptr); + exit(1); +} + +int +lexNum(lex *l) { + int n = atoi(l->ptr); + while (isdigit(*l->ptr)) + l->ptr++; + return n; +} + +tok +next(lex *l) { + tok t = {0}; + switch (*l->ptr) { + case 0: + t.op = LEOF; + return t; + + case '\n': case ' ': case '\t': case '\v': + l->ptr++; + return next(l); + + case ADD: case SUB: case MUL: case DIV: + t.op = *l->ptr++; + return t; + } + if (isdigit(*l->ptr)) { + t.op = INT; + t.n = lexNum(l); + } + else lexErr(l); + + return t; +} + +void +printTok(tok *t) { + switch (t->op) { + case INT: printf("INT: %d\n", t->n); break; + case LEOF: printf("$\n"); break; + case ADD: printf("ADD\n"); break; + case SUB: printf("SUB\n"); break; + case MUL: printf("MUL\n"); break; + case DIV: printf("DIV\n"); break; + } +} + +lex +mklexer(char *input) { + lex l = (lex){input, input}; + return l; +} diff --git a/lexer.h b/lexer.h @@ -0,0 +1,29 @@ +#ifndef __LEXER_H_ +#define __LEXER_H_ + +enum ops { + NOP = 0, + INT = -1, + ADD = '+', + SUB = '-', + MUL = '*', + DIV = '/', + LEOF = '$', +}; + +typedef struct tok { + short op; + int n; +} tok; + +typedef struct lex { + char *input, *ptr; +} lex; + +void lexErr(lex *l); +int lexNum(lex *l); +tok next(lex *l); +void printTok(tok *t); +lex mklexer(char *input); + +#endif diff --git a/note.md b/note.md @@ -0,0 +1,99 @@ +pivot parser +============ + +a parser could work like so + +2 + 4 * 3 - 1 = 13 + +loop through all tokens and find the first token with the lowest presidence + +2 + 4 * 3 - 1 + ^ + +split the list + +2 ++ +4 * 3 - 1 + +repeat + +4 * 3 +- +1 + +4 +* +3 + +assemble the tree + + + + / \ + 2 - + / \ + * 1 + / \ + 4 3 + +2 + ((4 * 3) - 1) +2 + (12 - 1) +2 + 11 +13 + +another example + +4 * 2 + (4 - 1) = 11 + +4 * 2 ++ +(4 - 1) + +4 +* +2 + + + + / \ + * (4 - 1) + / \ + 4 2 + +4 - 1 + +4 +- +1 + + + + / \ + * \ + / \ \ + 4 2 \ + - + / \ + 4 1 + +(4 * 2) + (4 - 1) +8 + 3 +11 + + +func(a) * (10 - 4) + +func(a) +* +(10 - 4) + + * + / \ + func(a) \ + (10 - 4) + + * + / \ + func(a) - + / \ + 10 4 + +func(a) * (10 - 4) diff --git a/spl.c b/spl.c @@ -0,0 +1,68 @@ +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +#include "lexer.h" + +typedef struct rexpr { + char op; + + struct rexpr *expr[2]; + int n[2]; +} rexpr; + +void +parserErr(const char *msg) { + fprintf(stderr, "%s\n", msg); + exit(1); +} + +int +getpres(rexpr r) { + switch (r.op) { + case INT: return 0; + + case ADD: return 1; + case SUB: return 1; + + case MUL: return 2; + case DIV: return 2; + + case LEOF: return -1; + } +} + +int +isop(tok t) { + return (t.op == ADD || t.op == SUB || t.op == MUL || t.op == DIV); +} + +rexpr * +parseRexpr(lex *l) { + rexpr *e = malloc(sizeof(rexpr)), *e2; + tok t1 = next(l), t2 = next(l); + + if (t1.op != INT) + parserErr("Expected INT in rexpr"); + e->n[0] = t1.n; + if (isop(t2)) { + e->op = t2.op; + e2 = parseRexpr(l); + if (e2->op == INT) e->n[1] = e2->n[0]; + else e->expr[1] = e2; + } + else if (t2.op == LEOF) { + e->op = INT; + return e; + } + else + parserErr("Unexpected token in rexpr"); +} + +int +main() { + lex l = mklexer("5 + 2"); + + rexpr *e = parseRexpr(&l); + +}