-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1928672
commit cdffbca
Showing
16 changed files
with
1,578 additions
and
504 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.