From 56040f3ff85e77311f0c864a89afd63fcf1bdb50 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Mon, 3 Nov 2025 23:40:02 -0800 Subject: add js-lang, refactor some ts-lang stuff --- src/ts-lang/core/parser.ts | 165 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/ts-lang/core/parser.ts (limited to 'src/ts-lang/core/parser.ts') diff --git a/src/ts-lang/core/parser.ts b/src/ts-lang/core/parser.ts new file mode 100644 index 0000000..db6f3aa --- /dev/null +++ b/src/ts-lang/core/parser.ts @@ -0,0 +1,165 @@ +import { ASTNode, NodeType, ParserCtx, Token, TokenType } from "./common"; + +export type Error = ASTNode< + NodeType.PARSER_ERROR, + "Error", + T, + [] +>; + +export type PushChild = { + type: Node["type"]; + value: Node["value"]; + name: Node["name"]; + children: [...Node["children"], Child]; +}; + +export type PushChildToLastElementOfStack< + Stack extends ParserCtx["stack"], + Child extends ASTNode +> = Stack extends [...infer Head, infer Tail extends ASTNode] + ? [...Head, PushChild] + : Stack extends [infer Only extends ASTNode] + ? [PushChild] + : never; + +export type PushChildToSecondLastElementOfStack< + Stack extends ParserCtx["stack"], + Child extends ASTNode +> = Stack extends [ + ...infer Head, + infer Tail extends ASTNode, + infer Final extends ASTNode +] + ? [...Head, PushChild, Final] + : Stack extends [infer Only extends ASTNode, infer Final extends ASTNode] + ? [PushChild, Final] + : never; + +export type GetLastOnStack = Stack extends [ + ...infer Head, + infer Tail extends ASTNode +] + ? Tail + : Stack extends [infer Only extends ASTNode] + ? Only + : never; + +export type StackWithoutLast = Stack extends [ + ...infer Head extends ASTNode[], + infer Tail +] + ? [...Head] + : Stack extends [infer Only extends ASTNode] + ? [] + : never; + +type NULL_SENTINEL = { + NULL: true; +}; + +export type ParseNumberLiteral = + T extends `${infer Inner extends number}` ? Inner : NULL_SENTINEL; + +export type ParseStringLiteral = + T extends `"${infer Inner extends string}"` ? Inner : NULL_SENTINEL; + +export type ResolveNodeFromToken<_Token extends Token> = ParseNumberLiteral< + _Token["name"] +> extends number + ? ASTNode, []> + : ParseStringLiteral<_Token["name"]> extends string + ? ASTNode, []> + : ASTNode; + +export type _Parse = Ctx["remainingTokens"] extends [ + infer Head extends Token, + ...infer Tail extends readonly Token[] +] + ? Ctx["lastToken"] extends Token + ? Head["type"] extends TokenType.NAME + ? // we already have a lastToken + // mutate last element of stack to push lastToken as child + // lastToken = nextToken + // goto start + _Parse<{ + lastToken: Head; + remainingTokens: Tail; + stack: PushChildToLastElementOfStack< + Ctx["stack"], + ResolveNodeFromToken + >; + }> + : //nextToken is openParen or close paren + Head["type"] extends TokenType.CLOSE_PAREN + ? // handle lastToken + // set last element of stack as child of prev element on stack + // pop stack + // [stack[last - 1].children.push(stack.pop) + // goto start + _Parse<{ + 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 + // then remove the top + stack: StackWithoutLast< + PushChildToSecondLastElementOfStack< + Ctx["stack"], + PushChild< + GetLastOnStack, + ResolveNodeFromToken + > + > + >; + }> + : Head["type"] extends TokenType.OPEN_PAREN + ? // push lastToken onto stack + // goto start + _Parse<{ + lastToken: null; + remainingTokens: Tail; + stack: [...Ctx["stack"], ResolveNodeFromToken]; + }> + : Ctx & Error<`Was not expecting ${Head["type"]}`> + : // expect nextToken to be a name or close paren + Head["type"] extends TokenType.NAME + ? // lastToken = nextToken + // goto start + _Parse<{ + lastToken: Head; + remainingTokens: Tail; + stack: Ctx["stack"]; + }> + : Head["type"] extends TokenType.CLOSE_PAREN + ? _Parse<{ + lastToken: null; + remainingTokens: Tail; + // push the top onto the children of the next + // then remove the top + stack: StackWithoutLast< + PushChildToSecondLastElementOfStack< + Ctx["stack"], + GetLastOnStack + > + >; + }> + : Ctx & + Error<`Expected nextToken to be a name or close paren at ${Head["type"]}`> + : Ctx["lastToken"] extends Token + ? // case where we ended with a name + _Parse<{ + lastToken: null; + remainingTokens: []; + stack: PushChildToLastElementOfStack< + Ctx["stack"], + ResolveNodeFromToken + >; + }> + : Ctx["stack"][0]; + +export type Parse = _Parse<{ + lastToken: null; + remainingTokens: Raw; + stack: [ASTNode]; +}>; -- cgit v1.2.3-70-g09d2