Skip to content

Commit

Permalink
complete rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianschubek committed May 31, 2024
1 parent 1928672 commit cdffbca
Show file tree
Hide file tree
Showing 16 changed files with 1,578 additions and 504 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,14 @@
- Start a supervisor service conditionally using docker run arguments.
- Use different compile commands based on user's current architecture
- and many more...


<!--
nodemon --ext 'txt,ts' out/index.js -p tests/loop.txt
wie latex multi-pass erst loops -> ...
add latex syntax
- allow custom prefix instead of `\` allow e.g. `##`
TODO: add loops (polyfill using rewriting)
TODO: allow nesting
-->
Binary file removed docs/static/img/docusaurus-social-card.jpg
Binary file not shown.
Binary file removed docs/static/img/docusaurus.png
Binary file not shown.
1 change: 0 additions & 1 deletion docs/static/img/logo.svg

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "utpp",
"version": "0.5.0",
"version": "0.6.0",
"description": "Universal Text Pre-Processor",
"main": "bin/index.js",
"bin": "bin/npx.js",
Expand Down
170 changes: 170 additions & 0 deletions src/ast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { ASTNodeType } from "./common";

export abstract class ASTNode {
type: ASTNodeType;
constructor(type: ASTNodeType) {
this.type = type;
}
visit(): void {
// check for interrupt
}
}
export class Program extends ASTNode {
body: ASTNode[];
constructor(body: ASTNode[]) {
super(ASTNodeType.PROG);
this.body = body;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
export class Raw extends ASTNode {
value: string;
constructor(value: string) {
super(ASTNodeType.RAW);
this.value = value;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
/**
* \foobar[...]{...}...
* Not a built-in function
*/
export class FunctionCall extends ASTNode {
name: string;
params: Params;
args: ASTNode[];
constructor(name: string, params?: Params, args?: ASTNode[]) {
super(ASTNodeType.F_CALL);
this.name = name;
this.params = params ?? new Params({});
this.args = args ?? [];
}

visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
/**
* \fn[x,y]{add}{\${x + y}}
* x und y sind automatisch verfügbar in JS eval
*/
export class FunctionDefinition extends ASTNode {
name: ASTNode;
// arguments [x,y] only key is relevant maybe later use =string =int for type checking
fnArgs: Params;
body: ASTNode;
constructor(name: ASTNode, fnArgs: Params, body: ASTNode) {
super(ASTNodeType.F_DEF);
this.name = name;
this.fnArgs = fnArgs;
this.body = body;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
/**
* [a=b,c=d,...] and [arg1,arg2,..]
*/
export class Params extends ASTNode {
kv: { [key: string]: ASTNode | null };
constructor(kv: { [key: string]: ASTNode | null }) {
super(ASTNodeType.PARAMS);
this.kv = kv;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
export class IfStatement extends ASTNode {
condition: ASTNode;
trueBranch: ASTNode;
falseBranch: ASTNode;
constructor(condition: ASTNode, trueBranch: ASTNode, falseBranch: ASTNode) {
super(ASTNodeType._IF);
this.condition = condition;
this.trueBranch = trueBranch;
this.falseBranch = falseBranch;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
export class LoopStatement extends ASTNode {
init: ASTNode;
condition: ASTNode;
increment: ASTNode;
body: ASTNode;
constructor(init: ASTNode, condition: ASTNode, increment: ASTNode, body: ASTNode) {
super(ASTNodeType._LOOP);
this.init = init;
this.condition = condition;
this.increment = increment;
this.body = body;
}
}
export class URLStatement extends ASTNode {
url: ASTNode;
constructor(url: ASTNode) {
super(ASTNodeType._URL);
this.url = url;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
export class FileStatement extends ASTNode {
path: ASTNode;
constructor(path: ASTNode) {
super(ASTNodeType._FILE);
this.path = path;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
export class UseStatement extends ASTNode {
code: ASTNode;
constructor(code: ASTNode) {
super(ASTNodeType._USE);
this.code = code;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
export class EvalExpr extends ASTNode {
expr: string;
constructor(expr: string) {
super(ASTNodeType.EVAL);
this.expr = expr;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
export class Comment extends ASTNode {
value: string;
constructor(value: string) {
super(ASTNodeType.COMMENT);
this.value = value;
}
visit(): void {
super.visit();
throw new Error("Method not implemented.");
}
}
83 changes: 83 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import chalk from "chalk";

export enum TokenType {
T_RAW = "T_RAW",
T_PREFIX = "T_PREFIX",
T_CMD = "T_CMD",
T_ARG = "T_ARG",
T_ARG_START = "T_ARG_START",
T_ARG_END = "T_ARG_END",

T_PARAM_START = "T_PARAM_START",
T_PARAM_END = "T_PARAM_END",
T_PARAM_SEP = "T_PARAM_SEP",
T_PARAM_ASSIGN = "T_PARAM_ASSIGN",
T_PARAM_KEY = "T_PARAM_KEY",
T_EVAL = "T_EVAL",
}

export enum ASTNodeType {
PROG = "PROG",
RAW = "RAW",
F_CALL = "F_CALL" /* custom function call */,
F_DEF = "F_DEF" /* custom function definition */,
PARAMS = "PARAMS",
_IF = "_IF" /* built-in function if */,
COMMENT = "COMMENT",
EVAL = "EVAL",
_LOOP = "_LOOP",
_URL = "_URL",
_FILE = "_FILE",
_USE = "_USE" /* imports. must be top level. parse file then interpret */,
}

export enum BuiltInFunction {
LOOP = "loop",
IF = "if",
EVAL = "$",
ENV = "env",
F = "f" /* fucntion definition */,
COMMENT = "#",
URL = "url",
FILE = "file",
USE = "use",
}

export interface Token {
type: TokenType;
value: string;
row: number;
col: number;
}

export function err(msg: string, row?: number, col?: number): never {
if (row === undefined || col === undefined) throw new Error(msg);
throw new Error(chalk.red(`${msg} on line ${row}:${col}.`));
}

export function assertCount<T>(text: string, details: string, thisToken: Token, count: number, args?: T[]) {
let actual = args?.length ?? 0;
if (actual !== count) {
err(
`Expected ${chalk.redBright(count)} ${text} but got ${chalk.redBright(actual === 0 ? "none" : actual)} ${details}`,
thisToken.row,
thisToken.col
);
}
}
export function assertRange<T>(text: string, details: string, thisToken: Token, min: number, max: number, args?: T[]) {
let actual = args?.length ?? 0;
if (actual < min || actual > max) {
err(
`Expected ${chalk.redBright(min)} to ${chalk.redBright(max)} ${text} but got ${chalk.redBright(actual === 0 ? "none" : actual)} ${details}`,
thisToken.row,
thisToken.col
);
}
}

export function assertType<T>(details: string, thisToken: Token, expected: T, actual: T) {
if (actual !== expected) {
err(`Expected ${chalk.redBright(expected)} but got ${chalk.redBright(actual)} ${details}`, thisToken.row, thisToken.col);
}
}
Loading

0 comments on commit cdffbca

Please sign in to comment.