fix ident problem

This commit is contained in:
Michael Zhang 2024-09-14 01:15:42 -05:00
parent 78a29ce471
commit e65f457530
3 changed files with 42 additions and 23 deletions

12
src/main.ts Normal file
View file

@ -0,0 +1,12 @@
import { parseProgram } from "./parser";
// Main
async function main() {
const filename = Bun.argv[2];
const contents = await Bun.file(filename).text()
const programAst = parseProgram(contents);
}
main();

View file

@ -33,13 +33,22 @@ const alt = (...parsers) => (i: string) => {
return res;
};
const _: Parser = re(/\s*/) // whitespace
// whitespace
const __: Parser = re(/\s+/)
const _: Parser = re(/\s*/)
// Grammar
const ident: Parser = re(/(\_[A-Za-z0-9_]+)|([A-Za-z][A-Za-z0-9_]*)/);
const kwd = (s: string) => (i: string) => {
const res = ident(i)
if (res.status === "err") return wrapErr(`expected ${s}`, res)
if (s !== res.value) return err(`expected ${s}`)
return res
}
const ty: Parser = alt(
re(/uint/), re(/int/), re(/ptr/),
re(/str/), ident,
kwd("uint"), kwd("int"), kwd("ptr"),
kwd("str"), ident,
)
const exprL: Parser = alt(
@ -54,17 +63,17 @@ const expr2: Parser = alt(
const expr1: Parser = alt(
map(seq(expr2, _, re(/==/), _, expr2), ([left,,,,right]) => ({expr: "==", left, right})),
expr2)
const expr: Parser = expr1
export const expr: Parser = expr1
const top: Parser = alt(
map(seq(re(/extern/), _, ident), (([, name]) => ({type: "extern", name}))),
seq(re(/struct/), _, ident, _, re(/:/)),
map(seq(re(/fn/), _, ident, _, re(/:/)), (([,, name]) => ({type: "func", name}))),
export const top: Parser = alt(
map(seq(kwd("extern"), _, ident), (([, name]) => ({type: "extern", name}))),
seq(kwd("struct"), _, ident, _, re(/:/)),
map(seq(kwd("fn"), _, ident, _, re(/:/)), (([,, name]) => ({type: "func", name}))),
)
const stmt: Parser = alt(
map(seq(re(/let/), _, ident, _, re(/=/), _, (i) => expr(i)),
export const stmt: Parser = alt(
map(seq(kwd("let"), _, ident, _, re(/=/), _, (i) => expr(i)),
([,, name,,,, value]) => ({stmt: "let",name, value})),
map(seq(re(/if/), _, (i) => expr(i), _, re(/:/)), ([,, cond]) => ({stmt: "if", cond})),
map(seq(kwd("if"), _, (i) => expr(i), _, re(/:/)), ([,, cond]) => ({stmt: "if", cond})),
map((i) => expr(i), (expr) => ({stmt:"expr", expr})),
)
@ -75,7 +84,7 @@ interface Program {
functions: object[]
}
function parseProgram(input: string): Program {
export function parseProgram(input: string): Program {
let currentFunc: string | null = null;
let indentStack = [0];
let expectIndent = false;
@ -124,14 +133,4 @@ function parseProgram(input: string): Program {
}
}
// Codegen
// Main
async function main() {
const filename = Bun.argv[2];
const contents = await Bun.file(filename).text()
const programAst = parseProgram(contents);
}
main();
// Codegen

8
test/parser.test.ts Normal file
View file

@ -0,0 +1,8 @@
import {test,expect} from "bun:test"
import { stmt } from "../src/parser"
test("ifx", () => expect(stmt("ifx")).toMatchObject({status:"ok", value: {expr: {}}, remain: ""}))
test("ifx:", () => expect(stmt("ifx:")).toMatchObject({status:"ok", value: {expr: {}}, remain: ":"}))
test("if x:", () => expect(stmt("if x:")).toMatchObject({status:"ok", value: {stmt: "if"}, remain: ""}))
test("if(x):", () => expect(stmt("if(x):")).toMatchObject({status:"ok", value: {stmt: "if"}, remain: ""}))
test("let let = let", () => expect(stmt("let let = let")).toMatchObject({status:"ok", value: {stmt: "let"}, remain: ""}))