summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2025-10-29 20:22:19 -0700
committerKai Stevenson <kai@kaistevenson.com>2025-10-29 20:22:19 -0700
commitc20434533887618820985cbb25081255475852f2 (patch)
tree9285eb81051be8dfba245b5a1dace38aefcba1e4 /src/lib
parent8896b33a652563d90cb211a85dd2f7213f42e5d1 (diff)
references
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/core/common.ts20
-rw-r--r--src/lib/core/eval.ts7
-rw-r--r--src/lib/core/lexer.ts33
-rw-r--r--src/lib/core/parser.ts87
-rw-r--r--src/lib/core/repl.ts3
5 files changed, 80 insertions, 70 deletions
diff --git a/src/lib/core/common.ts b/src/lib/core/common.ts
index 1283000..a17eff4 100644
--- a/src/lib/core/common.ts
+++ b/src/lib/core/common.ts
@@ -4,14 +4,22 @@ export enum TokenType {
SPACE = " ",
SEMICOLON = ";",
COMMA = ",",
- UNIQUE_SYMBOL = "UNIQUE_SYMBOL",
+ NAME = "NAME",
+}
+
+export enum TokenSubType {
+ NA = "NA",
+ LITERAL = "LITERAL",
+ REFERENCE = "REFERENCE",
}
export type Token<
Type extends TokenType = TokenType,
+ Subtype extends TokenSubType = TokenSubType,
Name extends string = string
> = {
type: Type;
+ subType: Subtype;
name: Name;
};
@@ -23,23 +31,25 @@ export type LexerCtx = {
export enum NodeType {
ROOT = "ROOT",
- LITERAL = "LITERAL",
- CALL = "CALL",
+ INT = "INT",
+ EXT = "EXT",
PARSER_ERROR = "PARSER_ERROR",
}
export type ASTNode<
Type extends NodeType = NodeType,
Name extends string = string,
- Children extends ASTNode[] = ASTNode<NodeType, string, any>[]
+ Value extends any = any,
+ Children extends ASTNode[] = ASTNode<NodeType, string, any, any>[]
> = {
type: Type;
name: Name;
+ value: Value;
children: Children;
};
export type ParserCtx = {
remainingTokens: readonly Token[];
- lastName: string | null;
+ lastToken: Token | null;
stack: readonly ASTNode[];
};
diff --git a/src/lib/core/eval.ts b/src/lib/core/eval.ts
new file mode 100644
index 0000000..779bfd9
--- /dev/null
+++ b/src/lib/core/eval.ts
@@ -0,0 +1,7 @@
+import { ASTNode } from "./common";
+import { Lex } from "./lexer";
+import { Parse } from "./parser";
+
+export type Evaluate<Node extends ASTNode> = "Not implemented";
+
+const test_result = null as unknown as Evaluate<Parse<Lex<"print(a)">>>;
diff --git a/src/lib/core/lexer.ts b/src/lib/core/lexer.ts
index 3315fb2..e9756bd 100644
--- a/src/lib/core/lexer.ts
+++ b/src/lib/core/lexer.ts
@@ -1,4 +1,4 @@
-import { LexerCtx, Token, TokenType } from "./common";
+import { LexerCtx, Token, TokenSubType, TokenType } from "./common";
export type BreakingToken =
| TokenType.OPEN_PAREN
@@ -16,7 +16,7 @@ export type IsWhitespace<T> = T extends `${TokenType.SPACE}`
: false;
export type ProcessNameCollection<
- Cur extends LexerCtx,
+ Ctx extends LexerCtx,
Tail extends string,
_Token extends Token | null
> = {
@@ -24,16 +24,29 @@ export type ProcessNameCollection<
nameCollection: "";
tokens: _Token extends null
? [
- ...Cur["tokens"],
- ...(Cur["nameCollection"] extends ""
+ ...Ctx["tokens"],
+ ...(Ctx["nameCollection"] extends ""
? []
- : [Token<TokenType.UNIQUE_SYMBOL, Cur["nameCollection"]>])
+ : [
+ Token<
+ TokenType.NAME,
+ TokenSubType.REFERENCE,
+ Ctx["nameCollection"]
+ >
+ ])
]
: [
- ...Cur["tokens"],
- ...(Cur["nameCollection"] extends ""
+ ...Ctx["tokens"],
+ ...(Ctx["nameCollection"] extends ""
? [_Token]
- : [Token<TokenType.UNIQUE_SYMBOL, Cur["nameCollection"]>, _Token])
+ : [
+ Token<
+ TokenType.NAME,
+ TokenSubType.REFERENCE,
+ Ctx["nameCollection"]
+ >,
+ _Token
+ ])
];
};
@@ -53,9 +66,7 @@ export type _Lex<Ctx extends LexerCtx> =
nameCollection: `${Ctx["nameCollection"]}${Head}`;
tokens: Ctx["tokens"];
}>
- : // : Ctx["next"] extends `${infer Head}`
- // ? _Lex<{ next: Head; tokens: Ctx["tokens"] }>
- Ctx["tokens"];
+ : Ctx["tokens"];
export type Lex<Raw extends string> = _Lex<{
next: `${Raw};`;
diff --git a/src/lib/core/parser.ts b/src/lib/core/parser.ts
index fbbbdc2..0f095fe 100644
--- a/src/lib/core/parser.ts
+++ b/src/lib/core/parser.ts
@@ -1,5 +1,12 @@
-import { ASTNode, NodeType, ParserCtx, Token, TokenType } from "./common";
-import { IsWhitespace, Lex } from "./lexer";
+import {
+ ASTNode,
+ NodeType,
+ ParserCtx,
+ Token,
+ TokenSubType,
+ TokenType,
+} from "./common";
+import { Lex } from "./lexer";
/*
start
@@ -46,10 +53,16 @@ finally:
*/
-export type Error<T extends string> = ASTNode<NodeType.PARSER_ERROR, T, []>;
+export type Error<T extends string> = ASTNode<
+ NodeType.PARSER_ERROR,
+ "Error",
+ T,
+ []
+>;
export type PushChild<Node extends ASTNode, Child extends ASTNode> = {
type: Node["type"];
+ value: Node["value"];
name: Node["name"];
children: [...Node["children"], Child];
};
@@ -94,22 +107,27 @@ export type StackWithoutLast<Stack extends ParserCtx["stack"]> = Stack extends [
? []
: never;
+export type ResolveNodeFromToken<_Token extends Token> =
+ _Token["subType"] extends TokenSubType.LITERAL
+ ? ASTNode<NodeType.INT, "UNNAMED", _Token["name"], []>
+ : ASTNode<NodeType.EXT, _Token["name"], null, []>;
+
export type _Parse<Ctx extends ParserCtx> = Ctx["remainingTokens"] extends [
infer Head extends Token,
...infer Tail extends readonly Token[]
]
- ? Ctx["lastName"] extends string
- ? Head["type"] extends TokenType.UNIQUE_SYMBOL
+ ? Ctx["lastToken"] extends Token
+ ? Head["type"] extends TokenType.NAME
? // we already have a lastName
// mutate last element of stack to push lastName as child
// lastName = nextToken
// goto start
_Parse<{
- lastName: Head["name"];
+ lastToken: Head;
remainingTokens: Tail;
stack: PushChildToLastElementOfStack<
Ctx["stack"],
- ASTNode<NodeType.LITERAL, Ctx["lastName"], []>
+ ResolveNodeFromToken<Ctx["lastToken"]>
>;
}>
: //nextToken is openParen or close paren
@@ -120,7 +138,7 @@ export type _Parse<Ctx extends ParserCtx> = Ctx["remainingTokens"] extends [
// [stack[last - 1].children.push(stack.pop)
// goto start
_Parse<{
- lastName: null;
+ lastToken: null;
remainingTokens: Tail;
// first push the last name onto the children of the top
// then push the top onto the children of the next
@@ -130,7 +148,7 @@ export type _Parse<Ctx extends ParserCtx> = Ctx["remainingTokens"] extends [
Ctx["stack"],
PushChild<
GetLastOnStack<Ctx["stack"]>,
- ASTNode<NodeType.LITERAL, Ctx["lastName"], []>
+ ResolveNodeFromToken<Ctx["lastToken"]>
>
>
>;
@@ -139,23 +157,23 @@ export type _Parse<Ctx extends ParserCtx> = Ctx["remainingTokens"] extends [
? // push lastName onto stack
// goto start
_Parse<{
- lastName: null;
+ lastToken: null;
remainingTokens: Tail;
- stack: [...Ctx["stack"], ASTNode<NodeType.CALL, Ctx["lastName"], []>];
+ stack: [...Ctx["stack"], ResolveNodeFromToken<Ctx["lastToken"]>];
}>
: Ctx & Error<`Was not expecting ${Head["type"]}`>
: // expect nextToken to be a name or close paren
- Head["type"] extends TokenType.UNIQUE_SYMBOL
+ Head["type"] extends TokenType.NAME
? // lastName = nextToken
// goto start
_Parse<{
- lastName: Head["name"];
+ lastToken: Head;
remainingTokens: Tail;
stack: Ctx["stack"];
}>
: Head["type"] extends TokenType.CLOSE_PAREN
? _Parse<{
- lastName: null;
+ lastToken: null;
remainingTokens: Tail;
// push the top onto the children of the next
// then remove the top
@@ -168,45 +186,12 @@ export type _Parse<Ctx extends ParserCtx> = Ctx["remainingTokens"] extends [
}>
: Ctx &
Error<`Expected nextToken to be a name or close paren at ${Head["type"]}`>
- : Ctx["stack"];
-
-// v1
-// ? Ctx["isCollecting"] extends true
-// ? Head["type"] extends TokenType.CLOSE_PAREN
-// ? "return"
-// : Head["type"] extends TokenType.UNIQUE_SYMBOL
-// ? _Parse<{
-// remainingTokens: Tail;
-// isCollecting: true;
-// name: Ctx["name"];
-// // fuck, how to do this without advancing seek pointer??
-// ret: [...Ctx["ret"], ASTNode;
-// }>
-// : Error<"Expected another name, or `)`">
-// : Head["type"] extends TokenType.OPEN_PAREN
-// ? _Parse<{
-// remainingTokens: Tail;
-// isCollecting: true;
-// name: Ctx["name"];
-// ret: Ctx["ret"];
-// }>
-// : Error<"Expected open paren">
-// : Ctx["ret"];
-
-//v2
-// ? Ctx["previousName"] extends null
-// ? Head["type"] extends TokenType.UNIQUE_SYMBOL
-// ? _Parse<{ remainingTokens: Tail; previousName: Head; node: Ctx["node"] }>
-// : ASTNode<NodeType.PARSER_ERROR, "Expected name", []>
-// : IsWhitespace<`${Head["type"]}`> extends true
-// ? ASTNode<NodeType.PARSER_ERROR, "1", []>
-// : ASTNode<NodeType.PARSER_ERROR, "2", []>
-// : Ctx["node"];
+ : Ctx["stack"][0];
export type Parse<Raw extends readonly Token[]> = _Parse<{
- lastName: null;
+ lastToken: null;
remainingTokens: Raw;
- stack: [ASTNode<NodeType.ROOT, "ROOT", []>];
+ stack: [ASTNode<NodeType.ROOT, "ROOT", null, []>];
}>;
-const a = "a" as any as Parse<Lex<"test(a)">>;
+const test_result = null as unknown as Parse<Lex<"test(a)">>;
diff --git a/src/lib/core/repl.ts b/src/lib/core/repl.ts
deleted file mode 100644
index 5235a64..0000000
--- a/src/lib/core/repl.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { ASTNode } from "./common";
-
-export type Evaluate<Node extends ASTNode> = "Not implemented";