Skip to content

Commit

Permalink
new tokenizer
Browse files Browse the repository at this point in the history
  • Loading branch information
JairusSW committed Nov 8, 2024
1 parent ad795cf commit ea58ebf
Show file tree
Hide file tree
Showing 16 changed files with 797 additions and 391 deletions.
39 changes: 39 additions & 0 deletions fact.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
(module
;; Import the external function 'env.print' (equivalent to print in the original code)
(import "env" "print" (func $print (param i32)))

;; Define the factorial function
(func $factorial (param $n i32) (result i32)
;; Local variables
(local $result i32)

;; If statement: if (n == 0)
(if (result i32)
(i32.eq (local.get $n) (i32.const 0))
;; Then block: rt 1
(then
(i32.const 1)
)
;; Else block: rt n * factorial(n - 1)
(else
;; Recursive call to factorial(n - 1)
(call $factorial (i32.sub (local.get $n) (i32.const 1)))
(local.set $result)
(i32.mul (local.get $n) (local.get $result))
)
)
)

;; Define the main function
(func $main (param $result i32)
;; Calculate factorial(5)
(i32.const 5)
(call $factorial)

;; Call print with the result
(call $print (local.get $result))
)

;; Export the main function so that it can be called externally
(export "main" (func $main))
)
6 changes: 4 additions & 2 deletions src/ast/nodes/BinaryExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export class BinaryExpression extends Expression {
export enum Operator {
Add = "+",
Sub = "-",
Assign = "=",
Mod = "%"
Mod = "%",
Equals = "=",
EqualsEquals = "==",
EqualsEqualsEquals = "===",
}
8 changes: 4 additions & 4 deletions src/ast/nodes/StructDeclaration.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Range } from "../Range";
import { Identifier } from "./Identifier";
import { Statement } from "./Statement";
import { StructMember } from "./StructMember";
import { StructFieldDeclaration } from "./StructFieldDeclaration";

export class StructDeclaration extends Statement {
public nameOf = "StructDeclaration";
public name: Identifier;
public members: StructMember[];
constructor(name: Identifier, members: StructMember[], range: Range) {
public fields: StructFieldDeclaration[];
constructor(name: Identifier, fields: StructFieldDeclaration[], range: Range) {
super();
this.name = name;
this.members = members;
this.fields = fields;
this.range = range;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@ import { Expression } from "./Expression";
import { Identifier } from "./Identifier";
import { TypeExpression } from "./TypeExpression";

export class StructFieldExpression extends Expression {
export class StructFieldDeclaration extends Expression {
public nameOf = "StructFieldExpression";
public name: Identifier;
public access: FieldAccessKind;
public type: TypeExpression;
public value: Expression | null;
constructor(name: Identifier, type: TypeExpression, value: Expression | null, range: Range) {
constructor(name: Identifier, type: TypeExpression, access: FieldAccessKind = FieldAccessKind.Private, value: Expression | null, range: Range) {
super();
this.name = name;
this.type = type;
this.access = access;
this.value = value;
this.range = range;
}
}

export enum FieldAccessKind {
Public,
Private,
Final
}
3 changes: 0 additions & 3 deletions src/ast/nodes/StructMember.ts

This file was deleted.

68 changes: 65 additions & 3 deletions src/parser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { EnumDeclaration } from "../ast/nodes/EnumDeclaration.js";
import { EnumElement } from "../ast/nodes/EnumElement.js";
import { ParenthesizedExpression } from "../ast/nodes/PathenthesizedExpression.js";
import { WhileStatement } from "../ast/nodes/WhileStatement.js";
import { StructDeclaration } from "../ast/nodes/StructDeclaration.js";
import { FieldAccessKind, StructFieldDeclaration } from "../ast/nodes/StructFieldDeclaration.js";

export class Parser {
public program: Source = new Source("test.zp");
Expand All @@ -60,9 +62,9 @@ export class Parser {
state.resume();
if ((node = this.parseVariableDeclaration(scope))) return node;
state.resume();
if ((node = this.parseEnumDeclaration(scope))) return node;
if ((node = this.parseStructDeclaration(scope))) return node;
state.resume();
if ((node = this.parseIfStatement(scope))) return node;
if ((node = this.parseEnumDeclaration(scope))) return node;
state.resume();
return null;
}
Expand Down Expand Up @@ -627,11 +629,71 @@ export class Parser {
const node = new WhileStatement(condition, body, Range.from(start, body.range));
return node;
}
parseStructDeclaration(scope: Scope): StructDeclaration | null {
if (this.tokenizer.getToken().text !== "struct") return null;
const start = this.tokenizer.position.toRange();

const nameToken = this.tokenizer.getToken();
if (!isIdentifier(nameToken)) return null;
const name = new Identifier(nameToken.text, nameToken.range);

if (this.tokenizer.getToken().text !== "{") return null;
const fields: StructFieldDeclaration[] = [];
while (true) {
const field = this.parseStructFieldExpression(scope);
if (!field) return null;
fields.push(field);
this.tokenizer.position.markPosition();
if (this.tokenizer.viewToken().text == "}") break;
}
const lastToken = this.tokenizer.getToken();

const node = new StructDeclaration(name, fields, Range.from(start, lastToken.range));
this.program.topLevelStatements.push(node);
return node;
}
parseStructFieldExpression(scope: Scope): StructFieldDeclaration | null {
const accessToken = this.tokenizer.getToken();
const start = this.tokenizer.position.toRange();

let access: FieldAccessKind | null = null;

if (accessToken.text === "public") {
access = FieldAccessKind.Public;
} else if (accessToken.text === "private") {
access = FieldAccessKind.Private;
} else if (accessToken.text === "final") {
access = FieldAccessKind.Final;
}

access = access || FieldAccessKind.Public;

const typeToken = access ? this.tokenizer.getToken() : accessToken;
if (!isIdentifier(typeToken)) return null;
const type = new TypeExpression([typeToken.text], false, typeToken.range);

const nameToken = this.tokenizer.getToken();
if (!isIdentifier(nameToken)) return null;
const name = new Identifier(nameToken.text, nameToken.range);

let value: Expression | null = null;
const state = this.tokenizer.createState();
if (this.tokenizer.getToken().text == "=") {
value = this.parseExpression(scope);
} else {
state.resume();
}

const node = new StructFieldDeclaration(name, type, access, value, Range.from(start, nameToken.range));
return node;
}
}

export function tokenToOp(tok: TokenData): Operator | null {
if (tok.token === Token.Add) return Operator.Add;
if (tok.token === Token.Sub) return Operator.Sub;
if (tok.token === Token.Equals) return Operator.Assign;
if (tok.token === Token.Equals) return Operator.Equals;
if (tok.token === Token.EqualsEquals) return Operator.EqualsEquals;
if (tok.token === Token.EqualsEqualsEquals) return Operator.EqualsEqualsEquals;
return null;
}
1 change: 1 addition & 0 deletions src/scripts/add.zp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[export]
fn add(a: i32, b: i32) -> i32 {
rt a + b
}
16 changes: 16 additions & 0 deletions src/scripts/factorial.zp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#[extern]: env.print
fn print(num: i32) -> void

fn factorial(n: i32) -> i32 {
if (n == 0) {
rt 1
} else {
rt n * factorial(n - 1)
}
}

#[export]
fn main() -> void {
i32 result = factorial(5)
print(result)
}
23 changes: 13 additions & 10 deletions src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,26 @@ const tokenizer = new Tokenizer(`
#[extern]: env.print
fn print(num: i32) -> void
#[export]
fn main(a: i32, b: i32, c: f64) -> i32 {
print(123)
if (true) {
print(12 + 3)
fn factorial(n: i32) -> i32 {
if (n == 0) {
rt 1
} else {
rt n * factorial(n - 1)
}
while (true) print("oh no")
rt a + b
}
`);
console.dir(tokenizer.getAll(), { depth: 10 });
#[export]
fn main() -> void {
i32 result = factorial(5)
print(result)
}
`);
console.dir(tokenizer.getAll(), { depth: 1 });
const parser = new Parser(tokenizer, "test.zp");
const source = parser.parseSource();
console.dir(source.topLevelStatements, { depth: 1 });

// console.log(new Parser(new Tokenizer("if (true) {}"), "test.zp").parseIfStatement(new Scope()))
// console.log(new Parser(new Tokenizer(`fn factorial(n: i32) -> i32 {}`), "test.zp").parseFunctionDeclaration(new Scope()))
const transpiled = Transpile.from(source);
console.log("Transpiled:\n" + transpiled);

Expand Down
Loading

0 comments on commit ea58ebf

Please sign in to comment.