Skip to content

Commit

Permalink
Feat (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
wcho21 authored Jan 31, 2024
1 parent 9d8f8c3 commit 8952a68
Show file tree
Hide file tree
Showing 11 changed files with 1,901 additions and 46 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
],
"devDependencies": {
"@types/jest": "^29.5.10",
"@types/node": "^20.11.6",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"typescript": "^5.3.2",
Expand Down
65 changes: 34 additions & 31 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions src/parser/binding-power.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
export type BindingPower = number;

export type BindingPowerEntry = { left: BindingPower, right: BindingPower };
export type BindingPowers = { [key: string]: BindingPowerEntry };

export const bindingPowers: BindingPowers = {
lowest: { left: 0, right: 1 },
assignment: { left: 31, right: 30 },
comparison: { left: 41, right: 40 },
summative: { left: 50, right: 51 },
productive: { left: 60, right: 61 },
prefix: { left: 70, right: 71 },
call: { left: 80, right: 81 },
};

export const getInfixBindingPower = (infix: string): BindingPowerEntry => {
switch (infix) {
case "=":
return bindingPowers.assignment;

case "==":
case "!=":
case ">":
case "<":
case ">=":
case "<=":
return bindingPowers.comparison;

case "+":
case "-":
return bindingPowers.summative;

case "*":
case "/":
return bindingPowers.productive;

// for function call, it behaves an infix operator which lies between
// function expression and parameter list, e.g, print("hello")
case "(":
return bindingPowers.call;

default:
return bindingPowers.lowest;
}
};
1 change: 1 addition & 0 deletions src/parser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const getBindingPower = (infix: string): BindingPower => {
}
};

/** @deprecated */
export default class Parser {
private buffer: TokenReader;

Expand Down
38 changes: 25 additions & 13 deletions src/parser/syntax-node/base/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
import type Position from "../../../util/position";

export interface Range {
readonly begin: Position,
readonly end: Position,
};

export interface SyntaxNodeBase<T extends string = string, F extends {} = {}> {
type: T,
range: {
begin: Position,
end: Position,
},
fields: F,
readonly type: T,
readonly range: Range,
readonly fields: F,
};

export function createNodeCreator<N extends SyntaxNodeBase>(type: N["type"]) {
function createNode(fields: N["fields"], rangeBegin: Position, rangeEnd: Position) {
const range = {
begin: rangeBegin,
end: rangeEnd,
};
type Node = { type: N["type"], range: N["range"], fields: N["fields"] };

function createNode(fields: N["fields"], range: Range): Node;
function createNode(fields: N["fields"], rangeBegin: Position, rangeEnd: Position): Node;
function createNode(fields: N["fields"], arg1: Range | Position, rangeEnd?: Position): Node {
if (rangeEnd !== undefined) {
const range = {
begin: arg1 as Position,
end: rangeEnd,
};

return { type, range, fields };
}

return { type, range, fields };
return { type, range: arg1 as Range, fields };
};

return createNode;
};

export type CreateNode<N extends SyntaxNodeBase> = (fields: N["fields"], rangeBegin: Position, rangeEnd: Position) => N;
declare function createNode<N extends SyntaxNodeBase>(fields: N["fields"], range: Range): N;
declare function createNode<N extends SyntaxNodeBase>(fields: N["fields"], rangeBegin: Position, rangeEnd: Position): N;
export type CreateNode<N extends SyntaxNodeBase> = typeof createNode<N>;
1 change: 1 addition & 0 deletions src/parser/syntax-node/expression/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface AssignmentNode extends SyntaxNodeBase<"assignment", { left: Ide

export const createIdentifierNode: CreateNode<IdentifierNode> = createNodeCreator<IdentifierNode>("identifier");
export const createNumberNode: CreateNode<NumberNode> = createNodeCreator<NumberNode>("number");
export const createBooleanNode: CreateNode<BooleanNode> = createNodeCreator<BooleanNode>("boolean");
export const createStringNode: CreateNode<StringNode> = createNodeCreator<StringNode>("string");
export const createPrefixNode: CreateNode<PrefixNode> = createNodeCreator<PrefixNode>("prefix");
export const createInfixNode: CreateNode<InfixNode> = createNodeCreator<InfixNode>("infix");
Expand Down
Loading

0 comments on commit 8952a68

Please sign in to comment.