Skip to content

Commit

Permalink
feat: parser init
Browse files Browse the repository at this point in the history
  • Loading branch information
thutasann committed May 20, 2024
1 parent 783bd15 commit 1d5ab73
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 11 deletions.
91 changes: 90 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1 +1,90 @@
{}
{
"vscode_custom_css.imports": [
"file:///Users/thutasann/.vscode/extensions/codevars.outrun-meets-synthwave-0.0.1/synthWaveStyles.css"
],
"eslint.workingDirectories": [{ "mode": "auto" }],
"editor.fontLigatures": true,
"workbench.tree.indent": 20,
"editor.fontSize": 13,
"editor.fontFamily": "\"Fira Code\",\"mononoki Nerd Font\", Menlo, Monaco, 'Courier New', monospace",
"editor.cursorSmoothCaretAnimation": "on",
"editor.cursorBlinking": "expand",
"editor.lineHeight": 2,
"editor.fontWeight": "normal",
"editor.cursorStyle": "block-outline",
"terminal.external.linuxExec": "iterm",
"terminal.integrated.fontSize": 14,
"workbench.iconTheme": "bearded-icons",
"editor.wordWrap": "on",
"prettier.configPath": ".prettierrc",
"editor.formatOnSave": true,
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"reactSnippets.settings.prettierEnabled": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "never"
},
"eslint.options": {
"extensions": [".js", ".jsx", ".md", ".mdx", ".ts", ".tsx"]
},
"eslint.validate": ["markdown", "mdx", "javascript", "javascriptreact", "typescript", "typescriptreact"],
"files.associations": {
"*.mdx": "mdx",
"*.jade": "jade"
},
"redhat.telemetry.enabled": true,
"security.workspace.trust.untrustedFiles": "open",
"css.lint.unknownAtRules": "ignore",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"typescript.tsdk": "./node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"git.enableSmartCommit": true,
"git.confirmSync": false,
"typescript.updateImportsOnFileMove.enabled": "never",
"emmet.includeLanguages": {
"javascript": "javascriptreact"
},
"[source.css.styled]": {
"editor.tabSize": 2,
"editor.wordWrap": "on",
"editor.autoClosingBrackets": "always",
"editor.autoClosingQuotes": "always"
},
"editor.quickSuggestions": {
"other": true,
"comments": false,
"strings": true
},
"javascript.updateImportsOnFileMove.enabled": "always",
"liveshare.accessibility.soundsEnabled": true,
"extensions.autoUpdate": "onlySelectedExtensions",
"angular.experimental-ivy": true,
"angular.forceStrictTemplates": true,
"editor.unicodeHighlight.invisibleCharacters": false,
"editor.unicodeHighlight.ambiguousCharacters": false,
"svg.preview.boundingBox": true,
"svg.preview.transparencyGrid": true,
"go.toolsManagement.autoUpdate": true,
"git.openRepositoryInParentFolders": "always",
"nxConsole.showNodeVersionOnStartup": false,
"editor.largeFileOptimizations": false,
"prettier.documentSelectors": [".cs"],
"gitlens.graph.minimap.enabled": false,
"[csharp]": {
"editor.defaultFormatter": "ms-dotnettools.csharp"
},
"editor.minimap.renderCharacters": false,
"workbench.colorTheme": "Outrun Electric Meets Synthwave",
"workbench.tree.enableStickyScroll": false,
"editor.stickyScroll.enabled": true,
"workbench.editorAssociations": {
"*.dll": "default"
}
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ Files with `.lang` extensions are Custom scripting language files.
cd <folder>
ts-node <file>.test.ts
```

## Sources

- https://astexplorer.net/
8 changes: 5 additions & 3 deletions src/ast/ast.interface.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
/** Abstract Syntax Tree Node Types (Expressions)
* @description
* - expressionis not a statement
* - expression is not a statement
* - expression example -> 5 * 10
* - assignment expression example -> x = 45
* - statements will not return a value
* - statement example -> let x = 45
*/
export type NodeType = 'Program' | 'NumericLiteral' | 'Identifier' | 'BinaryExpr'

/** Abstract Statement Interface */
/** Abstract Statement Interface that include statement kind */
export interface IStatement {
kind: NodeType
}

/** Program Node Type */
export interface IProgram extends IStatement {
/** kind of the program */
kind: 'Program'
/** array of the statements */
body: IStatement[]
}

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

/** Binary Expression Node Type
Expand Down
62 changes: 62 additions & 0 deletions src/ast/parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
IStatement,
IProgram,
IExpression,
IBinaryExpression,
INumericLiteral,
IIdentifierExpression,
} from './ast.interface'
import { Lexer } from '../lexer/lexer'
import { TokenType, IToken } from '../lexer/lexer.interface'

/**
* Parser Object
* @description
* - the job of the parser is to take in our tokens that we created from our `tokenizer`
*/
export class Parser {
private readonly _lexer: Lexer
private tokens: IToken[] = []

constructor(lexer: Lexer) {
this._lexer = lexer
}

/**
* produce AST fnc
*/
public produceAST(sourceCode: string): IProgram {
this.tokens = this._lexer.tokenize(sourceCode)

const program: IProgram = {
kind: 'Program',
body: [],
}

// parse until end of the file
while (this.notEOF()) {
program.body.push(this.parseSTMT())
}

return program
}

/** check token is EOF or not */
private notEOF(): boolean {
return this.tokens[0].type !== TokenType.EOF
}

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

private parseExpr(): IExpression {
return { kind: 'BinaryExpr' }
}

private parsePrimaryExpr(): IExpression {
return { kind: 'Identifier' }
}
}
4 changes: 3 additions & 1 deletion src/lexer/lexer.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ export enum TokenType {
BinaryOperator,
/** let to declare variable */
Let,
/** signified the end of file */
EOF,
}

/**
* Token interface that include value and TokenType
*/
export interface Token {
export interface IToken {
value: string
type: TokenType
}
Expand Down
17 changes: 11 additions & 6 deletions src/lexer/lexer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { KEYWORDS, Token, TokenType } from './lexer.interface'
import { KEYWORDS, IToken, TokenType } from './lexer.interface'

/**
* Lexer Object
*/
export class Lexer {
/**
* Tokenize function
* tokenizer fnc
* @param sourceCode - source code string
* @returns tokens array
*/
public tokenize(sourceCode: string): Token[] {
const tokens = new Array<Token>()
public tokenize(sourceCode: string): IToken[] {
/** tokens to store splited source code strings */
const tokens = new Array<IToken>()
const src: string[] = sourceCode.split('')

// build each token until end of file
Expand Down Expand Up @@ -49,11 +54,11 @@ export class Lexer {
}
}
}

tokens.push({ value: 'EndOfFile', type: TokenType.EOF })
return tokens
}

private token(value: string = '', type: TokenType): Token {
private token(value: string = '', type: TokenType): IToken {
return { value, type }
}

Expand Down

0 comments on commit 1d5ab73

Please sign in to comment.