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

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: ""}))