Skip to content

Commit

Permalink
feat: parse binary expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
thutasann committed May 21, 2024
1 parent 8e80448 commit 56f2770
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 8 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Building Custom Scripting Language

This is the repo how Custom Scripting language is created from scratch with typescript.
This is the repo where Custom Scripting language is created from scratch with typescript.

## Topics

- Lexer
- AST Definitions
- Parser

## Scripts

Expand Down
2 changes: 1 addition & 1 deletion src/ast/compiler/ast.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface IProgram extends IStatement {
body: IStatement[]
}

/** Expression interface*/
/** Expression interface that extends `IStatement` */
export interface IExpression extends IStatement {}

/** Binary Expression Node Type
Expand Down
87 changes: 83 additions & 4 deletions src/ast/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export class Parser {
public produceAST(sourceCode: string): IProgram {
const _lexer = new Lexer()
this.tokens = _lexer.tokenize(sourceCode)
Logger.log('tokens -> ', this.tokens)

const program: IProgram = {
kind: 'Program',
Expand All @@ -43,16 +42,62 @@ export class Parser {

/** entry point of the parser*/
private parseSTMT(): IStatement {
// skip to parseExpr
return this.parseExpr()
}

/** parse expression */
private parseExpr(): IExpression {
return this.parsePrimaryExpr()
return this.parseAdditiveExpr()
}

/** parse primary expressions */
/** parse additive expression
* @description <br/>
* - Additive Expression has left <-> hand presidence
* @example
* - (10 + 5) - 5
* - (10 + (10 - fooBar)) - 5
* - 10 + 5 * 3
* - wrap with additive expression with `()`
*/
private parseAdditiveExpr(): IExpression {
let left = this.parseMultiplicitaveExpr()

while (this.at().value == '+' || this.at().value == '-') {
const operator = this.eat().value
const right = this.parseMultiplicitaveExpr()
left = {
kind: 'BinaryExpr',
left,
right,
operator,
} as IBinaryExpression
}

return left
}

/** parse multiplicative expression
* @description parse `*`, `/` and `%`
*/
private parseMultiplicitaveExpr(): IExpression {
let left = this.parsePrimaryExpr()
while (this.at().value == '*' || this.at().value == '/' || this.at().value == '%') {
const operator = this.eat().value
const right = this.parseMultiplicitaveExpr()
left = {
kind: 'BinaryExpr',
left,
right,
operator,
} as IBinaryExpression
}

return left
}

/** ### primary parse expressions fnc
* @description this is the primary fnc of parse expression
*/
private parsePrimaryExpr(): IExpression {
const tokenType = this.at().type

Expand All @@ -61,6 +106,14 @@ export class Parser {
return { kind: 'Identifier', symbol: this.eat().value } as IIdentifierExpression
case TokenType.Number:
return { kind: 'NumericLiteral', value: parseFloat(this.eat().value) } as INumericLiteral
case TokenType.OpenParen:
this.eat() // eat open paren
const value = this.parseExpr()
this.expect(
TokenType.CloseParen,
'Unexpected token found inside parenthesised expression. Expected closing parenthesis',
) // eat close paren
return value
default:
console.error('Unexpected token found during parsing :', this.at())
process.exit(1)
Expand All @@ -72,6 +125,17 @@ export class Parser {
return this.tokens[0]
}

/** expect fnc */
private expect(type: TokenType, err: any): IToken {
const prev = this.tokens.shift() as IToken
if (!prev || prev.type == type) {
Logger.error('Parse Error:\n', err, prev, ' - Expecting: ', type)
process.exit(1)
}

return prev
}

/** check token is EOF or not */
private notEOF(): boolean {
return this.tokens[0].type !== TokenType.EOF
Expand All @@ -83,3 +147,18 @@ export class Parser {
return prev as IToken
}
}

/**
* ## Orders of Prescidence
* - AssignmentExpr
* - MemberExpr
* - FunctionCall
* - LogicalExpr
* - ComparisionExpr
* - AdditiveExpr ✅
* - MultiplicationExpr
* - UnaryExpr
* - PrimaryExpr
* @description This is just the Note
*/
class OrdersOfPrescidence {}
2 changes: 1 addition & 1 deletion src/ast/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const r1 = readline.createInterface({
/** test parser */
;(async function repl() {
const parser = new Parser()
Logger.info('\nRepl v0.1')
Logger.log('Repl v0.1')

r1.question('> ', (input) => {
if (!input || input.includes('exit')) {
Expand Down
2 changes: 1 addition & 1 deletion src/lexer/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class Lexer {
tokens.push(this.token(src.shift(), TokenType.OpenParen))
} else if (src[0] == ')') {
tokens.push(this.token(src.shift(), TokenType.CloseParen))
} else if (src[0] == '+' || src[0] == '-' || src[0] == '*' || src[0] == '/') {
} else if (src[0] == '+' || src[0] == '-' || src[0] == '*' || src[0] == '/' || src[0] == '%') {
tokens.push(this.token(src.shift(), TokenType.BinaryOperator))
} else if (src[0] == '=') {
tokens.push(this.token(src.shift(), TokenType.Equals))
Expand Down

0 comments on commit 56f2770

Please sign in to comment.