├── ast-website
├── CNAME
├── website
│ ├── CACHE_BREAKER
│ ├── .npmrc
│ ├── src
│ │ ├── parsers
│ │ │ ├── regexp
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ ├── transformers
│ │ │ │ │ └── regexp-tree
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ ├── regexp-tree.js
│ │ │ │ ├── regexpp.js
│ │ │ │ └── regjsparser.js
│ │ │ ├── mathjs
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ └── mathjs.js
│ │ │ ├── lucene
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ └── lucene.js
│ │ │ ├── mdx
│ │ │ │ ├── transformers
│ │ │ │ │ └── mdx
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── mdxhast.js
│ │ │ ├── json
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ ├── json-to-ast.js
│ │ │ │ └── momoa.js
│ │ │ ├── scala
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── index.js
│ │ │ ├── handlebars
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ ├── transformers
│ │ │ │ │ ├── ember-template-recast
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── glimmer
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── glimmer-compiler
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ ├── handlebars.js
│ │ │ │ ├── ember-template-recast.js
│ │ │ │ ├── glimmer.js
│ │ │ │ └── utils
│ │ │ │ │ └── defaultHandlebarsParserInterface.js
│ │ │ ├── icu
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── index.js
│ │ │ ├── reason
│ │ │ │ ├── index.js
│ │ │ │ └── codeExample.txt
│ │ │ ├── monkey
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── monkey.js
│ │ │ ├── wat
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── wat-parser.js
│ │ │ ├── html
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ ├── transformers
│ │ │ │ │ ├── posthtml
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── svelte
│ │ │ │ │ │ └── codeExample.txt
│ │ │ │ ├── posthtml.js
│ │ │ │ └── svelte.js
│ │ │ ├── graphviz
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── redot.js
│ │ │ ├── go
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── go.js
│ │ │ ├── sql
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ └── sqlite-parser.js
│ │ │ ├── thrift
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── thrift-parser.js
│ │ │ ├── lua
│ │ │ │ ├── index.js
│ │ │ │ └── codeExample.txt
│ │ │ ├── pug
│ │ │ │ ├── index.js
│ │ │ │ └── codeExample.txt
│ │ │ ├── vue
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── vue-template-compiler.js
│ │ │ │ └── vue-compiler-dom.js
│ │ │ ├── rust
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── syn.js
│ │ │ ├── san
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ └── san-template-parser.js
│ │ │ ├── css
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── transformers
│ │ │ │ │ └── postcss
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ ├── utils
│ │ │ │ │ └── defaultCSSParserInterface.js
│ │ │ │ ├── rework.js
│ │ │ │ ├── cssom.js
│ │ │ │ └── postcss.js
│ │ │ ├── markdown
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ └── transformers
│ │ │ │ │ └── remark
│ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ └── index.js
│ │ │ ├── python
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── python.js
│ │ │ ├── js
│ │ │ │ ├── transformers
│ │ │ │ │ ├── eslint1
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ ├── loadRulesShim.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── eslint2
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── eslint3
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── babel
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── prettier
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── babel6
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── babel7
│ │ │ │ │ │ └── codeExample.txt
│ │ │ │ │ ├── recast
│ │ │ │ │ │ └── codeExample.txt
│ │ │ │ │ ├── jscodeshift
│ │ │ │ │ │ └── codeExample.txt
│ │ │ │ │ ├── eslint4
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── eslint8
│ │ │ │ │ │ ├── codeExample.txt
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── tslint
│ │ │ │ │ │ └── codeExample.txt
│ │ │ │ │ └── typescript
│ │ │ │ │ │ └── codeExample.txt
│ │ │ │ ├── index.js
│ │ │ │ ├── utils
│ │ │ │ │ └── defaultESTreeParserInterface.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── babel-eslint9.js
│ │ │ │ ├── babel-eslint.js
│ │ │ │ ├── babel-eslint8.js
│ │ │ │ ├── babel-eslint-parser.js
│ │ │ │ ├── hermes
│ │ │ │ │ └── hermes-worker.js
│ │ │ │ ├── flow.js
│ │ │ │ ├── esformatter.js
│ │ │ │ └── acorn-to-esprima.js
│ │ │ ├── php
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── php-parser.js
│ │ │ ├── yaml
│ │ │ │ ├── index.js
│ │ │ │ ├── yaml-ast-parser.js
│ │ │ │ └── yaml.js
│ │ │ ├── solididy
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ ├── solidity-parser-antlr.js
│ │ │ │ └── solidity-parser-diligence.js
│ │ │ ├── webidl
│ │ │ │ ├── index.js
│ │ │ │ └── webidl2.js
│ │ │ ├── graphql
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── graphql-js.js
│ │ │ ├── glsl
│ │ │ │ ├── index.js
│ │ │ │ └── codeExample.txt
│ │ │ ├── protobuf
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── pbkit.js
│ │ │ ├── ocaml
│ │ │ │ ├── refmt-ml.js
│ │ │ │ ├── index.js
│ │ │ │ └── codeExample.txt
│ │ │ ├── java
│ │ │ │ ├── index.js
│ │ │ │ ├── codeExample.txt
│ │ │ │ └── java-parser.js
│ │ │ ├── transpilers
│ │ │ │ ├── typescript.js
│ │ │ │ └── babel.js
│ │ │ └── utils
│ │ │ │ ├── compileModule.js
│ │ │ │ └── protectFromLoops.js
│ │ ├── shims
│ │ │ └── jest-validate.js
│ │ ├── components
│ │ │ ├── visualization
│ │ │ │ ├── index.js
│ │ │ │ ├── JSON.js
│ │ │ │ ├── css
│ │ │ │ │ └── tree.css
│ │ │ │ ├── tree
│ │ │ │ │ ├── CompactObjectView.js
│ │ │ │ │ └── CompactArrayView.js
│ │ │ │ └── SelectedNodeContext.js
│ │ │ ├── LoadingIndicator.js
│ │ │ ├── buttons
│ │ │ │ ├── NewButton.js
│ │ │ │ ├── ShareButton.js
│ │ │ │ ├── SaveButton.js
│ │ │ │ ├── PrettierButton.js
│ │ │ │ ├── ForkButton.js
│ │ │ │ └── KeyMapButton.js
│ │ │ ├── LocalStorage.js
│ │ │ ├── ErrorMessage.js
│ │ │ ├── SettingsDrawer.js
│ │ │ └── dialogs
│ │ │ │ └── ShareDialog.js
│ │ ├── storage
│ │ │ ├── api.js
│ │ │ └── index.js
│ │ ├── utils
│ │ │ ├── classnames.js
│ │ │ ├── logger.js
│ │ │ ├── debounce.js
│ │ │ ├── stringify.js
│ │ │ └── pubsub.js
│ │ ├── containers
│ │ │ ├── LoadingIndicatorContainer.js
│ │ │ ├── ASTOutputContainer.js
│ │ │ ├── PasteDropTargetContainer.js
│ │ │ ├── ErrorMessageContainer.js
│ │ │ ├── ShareDialogContainer.js
│ │ │ ├── SettingsDrawerContainer.js
│ │ │ ├── SettingsDialogContainer.js
│ │ │ ├── CodeEditorContainer.js
│ │ │ └── TransformerContainer.js
│ │ └── core
│ │ │ └── ParseResult.js
│ ├── postcss.config.js
│ ├── favicon.png
│ ├── fontcustom
│ │ ├── fontcustom_45cd59da2a1bc422647cab7f53639319.eot
│ │ ├── fontcustom_45cd59da2a1bc422647cab7f53639319.ttf
│ │ ├── fontcustom_45cd59da2a1bc422647cab7f53639319.woff
│ │ ├── fontcustom_45cd59da2a1bc422647cab7f53639319.woff2
│ │ ├── input-svg
│ │ │ ├── reason.svg
│ │ │ └── scala.svg
│ │ └── README.md
│ └── index.ejs
├── .editorconfig
├── .gitignore
├── assets
│ ├── ast.png
│ └── source.png
├── .gitpod.yml
├── scripts
│ ├── build-ci.sh
│ ├── inject-rev.sh
│ ├── deploy.sh
│ ├── check-conflicts.sh
│ └── publish-latest.sh
├── server
│ ├── constants.js
│ ├── package.json
│ ├── handlers
│ │ └── gist
│ │ │ ├── loadGist.js
│ │ │ └── index.js
│ └── index.js
├── .travis.yml
├── .github
│ └── ISSUE_TEMPLATE
│ │ └── bug_report.md
├── LICENSE.txt
└── .eslintrc
├── packages
└── playground
│ ├── .gitignore
│ ├── src
│ ├── vite-env.d.ts
│ ├── main.tsx
│ ├── index.css
│ ├── Editor.tsx
│ ├── App.css
│ └── logo.svg
│ ├── tsconfig.node.json
│ ├── index.html
│ ├── vite.config.ts
│ ├── tsconfig.json
│ └── package.json
├── rustfmt.toml
├── .prettierrc
├── wasm
├── .gitignore
├── tests
│ └── web.rs
├── src
│ ├── utils.rs
│ └── lib.rs
└── README.md
├── pnpm-workspace.yaml
├── Cargo.toml
├── .gitignore
├── lexer
├── snapshots
│ ├── lexer__lexer_test__tests__comments.snap
│ ├── lexer__lexer_test__tests__string.snap
│ ├── lexer__lexer_test__tests__array.snap
│ ├── lexer__lexer_test__tests__bool.snap
│ ├── lexer__lexer_test__tests__let.snap
│ ├── lexer__lexer_test__tests__let_with_space.snap
│ └── lexer__lexer_test__tests__comments_then_blank_line.snap
├── main.rs
├── Cargo.toml
└── README.md
├── compiler
├── lib.rs
├── frame.rs
├── symbol_table_test.rs
├── Cargo.toml
└── README.md
├── .github
├── dependabot.yml
└── workflows
│ ├── rust.yml
│ ├── prepare-release.yml
│ └── doc-publish.yml
├── parser
├── snapshots
│ ├── parser__ast_tree_test__tests__test_string.snap
│ ├── parser__ast_tree_test__tests__test_return.snap
│ ├── parser__ast_tree_test__tests__test_index.snap
│ ├── parser__ast_tree_test__tests__test_unary.snap
│ ├── parser__ast_tree_test__tests__test_array.snap
│ ├── parser__ast_tree_test__tests__test_let.snap
│ ├── parser__ast_tree_test__tests__test_hash.snap
│ ├── parser__ast_tree_test__tests__test_func_call.snap
│ └── parser__ast_tree_test__tests__test_func_declaration.snap
├── main.rs
├── Cargo.toml
├── precedences.rs
└── README.md
├── .circleci
└── config.yml
├── .gitpod.yml
├── Maintainer.md
├── object
├── Cargo.toml
├── README.md
└── environment.rs
├── interpreter
├── Cargo.toml
├── main.rs
└── README.md
├── tsconfig.json
├── examples
└── hello.monkey
├── .gitpod.Dockerfile
├── LICENSE
└── package.json
/ast-website/CNAME:
--------------------------------------------------------------------------------
1 | astexplorer.net
2 |
--------------------------------------------------------------------------------
/ast-website/website/CACHE_BREAKER:
--------------------------------------------------------------------------------
1 | 27
2 |
--------------------------------------------------------------------------------
/packages/playground/.gitignore:
--------------------------------------------------------------------------------
1 | stats.html
2 |
--------------------------------------------------------------------------------
/ast-website/website/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/ast-website/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.js]
2 | quote_type = single
3 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/regexp/codeExample.txt:
--------------------------------------------------------------------------------
1 | /[a-z]/i
--------------------------------------------------------------------------------
/rustfmt.toml:
--------------------------------------------------------------------------------
1 | struct_lit_width=100
2 | fn_call_width=100
3 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true
4 | }
5 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/mathjs/codeExample.txt:
--------------------------------------------------------------------------------
1 | (sin(2x) + e^x) / 2
2 |
--------------------------------------------------------------------------------
/ast-website/.gitignore:
--------------------------------------------------------------------------------
1 | /out
2 | node_modules
3 | .idea
4 | package-lock.json
5 |
--------------------------------------------------------------------------------
/packages/playground/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/wasm/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | **/*.rs.bk
3 | Cargo.lock
4 | bin/
5 | pkg/
6 | wasm-pack.log
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/shims/jest-validate.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | validate(){},
3 | };
4 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - packages/*
3 | - wasm/pkg
4 | - ast-website/website
5 |
--------------------------------------------------------------------------------
/ast-website/assets/ast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gengjiawen/monkey-rust/HEAD/ast-website/assets/ast.png
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/lucene/codeExample.txt:
--------------------------------------------------------------------------------
1 | name:frank OR job:engineer AND food:/marshmal+ows/
2 |
--------------------------------------------------------------------------------
/ast-website/assets/source.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gengjiawen/monkey-rust/HEAD/ast-website/assets/source.png
--------------------------------------------------------------------------------
/ast-website/website/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('autoprefixer')
4 | ]
5 | }
--------------------------------------------------------------------------------
/ast-website/website/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gengjiawen/monkey-rust/HEAD/ast-website/website/favicon.png
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/mdx/transformers/mdx/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default {
2 | mdPlugins: [],
3 | hastPlugins: [],
4 | }
5 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | "lexer",
4 | "parser",
5 | "object",
6 | "interpreter",
7 | "compiler",
8 | "wasm"
9 | ]
10 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/json/codeExample.txt:
--------------------------------------------------------------------------------
1 | {
2 | "key1": [true, false, null],
3 | "key2": {
4 | "key3": [1, 2, "3", 1e10, 1e-3]
5 | }
6 | }
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/scala/codeExample.txt:
--------------------------------------------------------------------------------
1 | object Main {
2 | def main(args: Array[String]): Unit = {
3 | println("Hello, World!")
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/codeExample.txt:
--------------------------------------------------------------------------------
1 |
2 |
{{title}}
3 |
4 | {{body}}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/visualization/index.js:
--------------------------------------------------------------------------------
1 | import JSON from './JSON';
2 | import Tree from './Tree';
3 |
4 | export default [
5 | Tree,
6 | JSON,
7 | ];
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
3 | .idea/
4 | .vscode/
5 | .theia/
6 |
7 | node_modules
8 | .DS_Store
9 | *.log
10 | dist/
11 | out/
12 |
13 | package-lock.json
14 | .pnpm-store/
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/icu/codeExample.txt:
--------------------------------------------------------------------------------
1 | On {takenDate, date, short} {name} took {numPhotos, plural,
2 | =0 {no photos.}
3 | =1 {one photo.}
4 | other {# photos.}
5 | }
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/reason/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'reason';
2 | export const displayName = 'Reason';
3 | export const mimeTypes = [];
4 | export const fileExtension = 're';
5 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/lucene/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'lucene';
2 | export const displayName = 'Lucene';
3 | export const mimeTypes = [''];
4 | export const fileExtension = 'lucene';
5 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/mdx/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'mdx';
2 | export const displayName = 'MDX';
3 | export const mimeTypes = ['text/mdx'];
4 | export const fileExtension = 'mdx';
5 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/monkey/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'monkey';
2 | export const displayName = 'Monkey';
3 | export const mimeTypes = [];
4 | export const fileExtension = 'monkey';
5 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/wat/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'wat';
2 | export const displayName = 'WAT';
3 | export const mimeTypes = ['application/wasm'];
4 | export const fileExtension = 'wat';
5 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/html/codeExample.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | My First Heading
6 | My first paragraph.
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/regexp/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'regexp';
2 | export const displayName = 'RegExp';
3 | export const mimeTypes = ['text/regexp'];
4 | export const fileExtension = 'regexp';
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/mathjs/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'mathjs';
2 | export const displayName = 'Math.js';
3 | export const mimeTypes = ['text/mathjs'];
4 | export const fileExtension = 'mathjs';
5 |
--------------------------------------------------------------------------------
/packages/playground/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gengjiawen/monkey-rust/HEAD/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.eot
--------------------------------------------------------------------------------
/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gengjiawen/monkey-rust/HEAD/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.ttf
--------------------------------------------------------------------------------
/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gengjiawen/monkey-rust/HEAD/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.woff
--------------------------------------------------------------------------------
/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gengjiawen/monkey-rust/HEAD/ast-website/website/fontcustom/fontcustom_45cd59da2a1bc422647cab7f53639319.woff2
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/graphviz/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'graphviz';
2 | export const displayName = 'Graphviz';
3 | export const mimeTypes = ['text/vnd.graphviz'];
4 | export const fileExtension = 'gv';
5 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/go/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/go/go';
2 |
3 | export const id = 'go';
4 | export const displayName = 'Go';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'go';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/sql/codeExample.txt:
--------------------------------------------------------------------------------
1 | --
2 | -- This is an example query
3 | --
4 | SELECT
5 | foo, bar as baz
6 | FROM
7 | mytable
8 | WHERE
9 | foo LIKE '%neat%'
10 | ORDER BY
11 | foo DESC
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/thrift/index.js:
--------------------------------------------------------------------------------
1 | export const id = 'thrift-idl';
2 | export const displayName = 'Thrift IDL';
3 | export const mimeTypes = ['text/x-thrift-idl'];
4 | export const fileExtension = 'thrift';
5 |
--------------------------------------------------------------------------------
/ast-website/.gitpod.yml:
--------------------------------------------------------------------------------
1 |
2 | tasks:
3 | - init: cd website && yarn
4 | command: yarn dev
5 | - init: fish
6 |
7 | ports:
8 | - port: 8080
9 | onOpen: open-preview
10 | visibility: public
11 |
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/lua/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/lua/lua';
2 |
3 | export const id = 'lua';
4 | export const displayName = 'Lua';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'lua';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/pug/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/pug/pug';
2 |
3 | export const id = 'pug';
4 | export const displayName = 'Pug';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'pug';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/vue/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/vue/vue';
2 |
3 | export const id = 'vue';
4 | export const displayName = 'Vue';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'vue';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/rust/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/rust/rust';
2 |
3 | export const id = 'rust';
4 | export const displayName = 'Rust';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'rs';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/san/codeExample.txt:
--------------------------------------------------------------------------------
1 |
2 |
{{title}}
3 |
7 |
8 |
--------------------------------------------------------------------------------
/ast-website/scripts/build-ci.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | rm -rf out/*
6 | (
7 | cd website/
8 | yarn
9 | if [ "$1" = "--dev" ]; then
10 | yarn build-dev
11 | else
12 | yarn build
13 | fi
14 | )
15 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/css/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/css/css';
2 |
3 | export const id = 'css';
4 | export const displayName = 'CSS';
5 | export const mimeTypes = ['text/css'];
6 | export const fileExtension = 'css';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/markdown/codeExample.txt:
--------------------------------------------------------------------------------
1 | # Hello
2 |
3 | Some *emphasis*, **importance**, and `code`.
4 |
5 | ---
6 |
7 | ```javascript
8 | console.log('!');
9 | ```
10 |
11 | * foo
12 | * bar
13 | * baz
14 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/thrift/codeExample.txt:
--------------------------------------------------------------------------------
1 | namespace js test
2 |
3 | const string test = 'test'
4 |
5 | struct MyStruct {
6 | 1: optional string test
7 | }
8 |
9 | service MyService {
10 | void ping()
11 | }
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/python/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/python/python';
2 |
3 | export const id = 'python';
4 | export const displayName = 'Python';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'py';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/sql/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/sql/sql';
2 |
3 | export const id = 'sql';
4 | export const displayName = 'SQL';
5 | export const mimeTypes = ['text/x-sql'];
6 | export const fileExtension = 'sql';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/storage/api.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch';
2 |
3 | const API_HOST = process.env.API_HOST || '';
4 |
5 | export default function api(path, options) {
6 | return fetch(`${API_HOST}/api/v1${path}`, options);
7 | }
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/icu/index.js:
--------------------------------------------------------------------------------
1 | // import 'codemirror/mode/html/html';
2 |
3 | export const id = 'icu';
4 | export const displayName = 'ICU';
5 | export const mimeTypes = ['text/plain'];
6 | export const fileExtension = 'txt';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint1/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function(context) {
2 | return {
3 | TemplateLiteral(node) {
4 | context.report(node, 'Do not use template literals');
5 | }
6 | };
7 | };
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint2/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function(context) {
2 | return {
3 | TemplateLiteral(node) {
4 | context.report(node, 'Do not use template literals');
5 | }
6 | };
7 | };
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint3/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function(context) {
2 | return {
3 | TemplateLiteral(node) {
4 | context.report(node, 'Do not use template literals');
5 | }
6 | };
7 | };
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/php/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/php/php';
2 |
3 | export const id = 'php';
4 | export const displayName = 'PHP';
5 | export const mimeTypes = ['application/php'];
6 | export const fileExtension = 'php';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/scala/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/clike/clike';
2 |
3 | export const id = 'text/x-scala';
4 | export const displayName = 'Scala';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'scala';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/yaml/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/yaml/yaml';
2 |
3 | export const id = 'yaml';
4 | export const displayName = 'YAML';
5 | export const mimeTypes = ['application/yaml'];
6 | export const fileExtension = 'yaml';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/solididy/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/javascript/javascript';
2 |
3 | export const id = 'solididy';
4 | export const displayName = 'Solidity';
5 | export const mimeTypes = [];
6 | export const fileExtension = 'sol';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/html/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/htmlmixed/htmlmixed';
2 |
3 | export const id = 'htmlmixed';
4 | export const displayName = 'HTML';
5 | export const mimeTypes = ['text/html'];
6 | export const fileExtension = 'html';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/json/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/javascript/javascript';
2 |
3 | export const id = 'json';
4 | export const displayName = 'JSON';
5 | export const mimeTypes = ['application/json'];
6 | export const fileExtension = 'json';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/webidl/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/webidl/webidl';
2 |
3 | export const id = 'webidl';
4 | export const displayName = 'Web IDL';
5 | export const mimeTypes = ['text/x-webidl'];
6 | export const fileExtension = 'webidl';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/graphql/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror-graphql/mode';
2 |
3 | export const id = 'graphql';
4 | export const displayName = 'GraphQL';
5 | export const mimeTypes = ['application/graphql'];
6 | export const fileExtension = 'graphql';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/markdown/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/markdown/markdown';
2 |
3 | export const id = 'markdown';
4 | export const displayName = 'Markdown';
5 | export const mimeTypes = ['text/markdown'];
6 | export const fileExtension = 'md';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/glsl/index.js:
--------------------------------------------------------------------------------
1 | import './codemirror-mode/glsl';
2 |
3 | export const id = 'glsl';
4 | export const displayName = 'GLSL';
5 | export const mimeTypes = ['x-shader/x-vertex', 'x-shader/x-fragment'];
6 | export const fileExtension = 'glsl';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/javascript/javascript';
2 |
3 | export const id = 'javascript';
4 | export const displayName = 'JavaScript';
5 | export const mimeTypes = ['text/javascript'];
6 | export const fileExtension = 'js';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/regexp/transformers/regexp-tree/codeExample.txt:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | Char({node}) {
3 | // Replace 'a' chars with 'b'.
4 | if (node.kind === 'simple' && node.value === 'a') {
5 | node.value = 'b';
6 | }
7 | }
8 | };
--------------------------------------------------------------------------------
/ast-website/website/src/utils/classnames.js:
--------------------------------------------------------------------------------
1 | export default function cx(...configs) {
2 | return configs.map(
3 | config => typeof config === 'string' ?
4 | config :
5 | Object.keys(config).filter(k => config[k]).join(' '),
6 | ).join(' ');
7 | }
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/graphviz/codeExample.txt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copy paste in a GraphViz dot file to explore the syntax tree
3 | */
4 |
5 | digraph {
6 | rankdir=LR
7 | a [fillcolor=green]
8 | c [fillcolor=red]
9 | a -> b
10 | c -> a [dir="back"]
11 | }
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/protobuf/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/protobuf/protobuf';
2 |
3 | export const id = 'protobuf';
4 | export const displayName = 'Protocol Buffers';
5 | export const mimeTypes = ['text/x-protobuf'];
6 | export const fileExtension = 'proto';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/ocaml/refmt-ml.js:
--------------------------------------------------------------------------------
1 | import config from '../reason/refmt';
2 |
3 | const ID = 'refmt-ml';
4 |
5 | export default {
6 | ...config,
7 | id: ID,
8 | parse: function(parser, code) {
9 | return parser.parseOcaml(code);
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/handlebars/handlebars';
2 |
3 | export const id = 'handlebars';
4 | export const displayName = 'Handlebars';
5 | export const mimeTypes = ['text/x-handlebars-template'];
6 | export const fileExtension = 'handlebars';
7 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/ocaml/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/mllike/mllike';
2 |
3 | export const id = 'ocaml';
4 | export const editorMode = 'text/x-ocaml';
5 | export const displayName = 'OCaml';
6 | export const mimeTypes = ['text/x-ocaml'];
7 | export const fileExtension = 'ml';
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/san/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/htmlmixed/htmlmixed';
2 |
3 | export const id = 'san';
4 | export const displayName = 'San';
5 | export const mimeTypes = ['text/html'];
6 | export const fileExtension = 'san.html';
7 | export const editorMode = 'htmlmixed';
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/utils/logger.js:
--------------------------------------------------------------------------------
1 | export function logEvent(category, action, label) {
2 | global.ga('send', 'event', category, action, label);
3 | }
4 |
5 | export function logError(message, fatal) {
6 | global.ga('send', 'exception', {exDescription: message, exFatal: fatal});
7 | }
8 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/java/index.js:
--------------------------------------------------------------------------------
1 | import 'codemirror/mode/clike/clike';
2 |
3 | export const id = 'java';
4 | export const displayName = 'Java';
5 | export const mimeTypes = ['text/x-java-source'];
6 | export const fileExtension = 'java';
7 | export const editorMode = 'text/x-java';
8 |
--------------------------------------------------------------------------------
/lexer/snapshots/lexer__lexer_test__tests__comments.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: lexer/lexer_test.rs
3 | expression: // I am comments
4 | ---
5 | [
6 | {
7 | "kind": {
8 | "type": "EOF"
9 | },
10 | "span": {
11 | "start": 16,
12 | "end": 17
13 | }
14 | }
15 | ]
16 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/transformers/ember-template-recast/codeExample.txt:
--------------------------------------------------------------------------------
1 | module.exports = function(env) {
2 | let b = env.syntax.builders;
3 |
4 | return {
5 | ElementNode(node) {
6 | node.tag = node.tag.split('').reverse().join('');
7 | }
8 | };
9 | };
10 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/solididy/codeExample.txt:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 | contract SimpleStore {
3 | function set(uint _value) public {
4 | value = _value;
5 | }
6 |
7 | function get() public constant returns (uint) {
8 | return value;
9 | }
10 |
11 | uint value;
12 | }
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/transformers/glimmer/codeExample.txt:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | return {
3 | name: 'ast-transform',
4 |
5 | visitor: {
6 | ElementNode(node) {
7 | node.tag = node.tag.split('').reverse().join('');
8 | }
9 | }
10 | };
11 | };
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/babel/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function ({Plugin, types: t}) {
2 | return new Plugin('ast-transform', {
3 | visitor: {
4 | Identifier(node) {
5 | return t.identifier(node.name.split('').reverse().join(''));
6 | }
7 | }
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/compiler/lib.rs:
--------------------------------------------------------------------------------
1 | #[macro_use]
2 | extern crate lazy_static;
3 |
4 | pub mod compiler;
5 | mod compiler_function_test;
6 | mod compiler_test;
7 | mod frame;
8 | pub mod op_code;
9 | mod op_code_test;
10 | pub mod symbol_table;
11 | mod symbol_table_test;
12 | pub mod vm;
13 | mod vm_function_test;
14 | mod vm_test;
15 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/transformers/glimmer-compiler/codeExample.txt:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | return {
3 | name: 'ast-transform',
4 |
5 | visitor: {
6 | ElementNode(node) {
7 | node.tag = node.tag.split('').reverse().join('');
8 | }
9 | }
10 | };
11 | };
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/prettier/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": false,
6 | "singleQuote": false,
7 | "trailingComma": "none",
8 | "bracketSpacing": true,
9 | "jsxBracketSameLine": false,
10 |
11 | "parser": "babel"
12 | }
13 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/html/transformers/posthtml/codeExample.txt:
--------------------------------------------------------------------------------
1 | const reverse = str =>
2 | str
3 | .split("")
4 | .reverse()
5 | .join("");
6 |
7 | export default function(tree) {
8 | tree.match({ tag: "h1" }, node => {
9 |
10 | node.content[0] = reverse(node.content[0]);
11 |
12 | return node;
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint1/loadRulesShim.js:
--------------------------------------------------------------------------------
1 | module.exports = function loadRules(/*rulesDir*/) {
2 | // By default, ESLint tries to load all available rules by looking for every
3 | // file in its "rules" directory. Since we don't care about any of the bundled
4 | // rules, just completely ignore them.
5 | return [];
6 | }
7 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: cargo
4 | directory: '/'
5 | schedule:
6 | interval: monthly
7 | time: '21:00'
8 | timezone: Asia/Shanghai
9 | open-pull-requests-limit: 10
10 | ignore:
11 | - dependency-name: wasm-bindgen-test
12 | versions:
13 | - 0.3.20
14 |
--------------------------------------------------------------------------------
/ast-website/server/constants.js:
--------------------------------------------------------------------------------
1 | if (!process.env.AUTH_TOKEN) {
2 | console.error(
3 | 'AUTH_TOKEN is not set! That will result in all gists being anonymous, ' +
4 | 'which is probably not what you want.'
5 | );
6 | process.exit(1);
7 | }
8 |
9 | module.exports = {
10 | AUTH_TOKEN: process.env.AUTH_TOKEN,
11 | SETTINGS_FORMAT: 2,
12 | };
13 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/vue/codeExample.txt:
--------------------------------------------------------------------------------
1 |
2 | {{ greeting }} World!
3 |
4 |
5 |
14 |
15 |
21 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/babel6/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function (babel) {
2 | const { types: t } = babel;
3 |
4 | return {
5 | name: "ast-transform", // not required
6 | visitor: {
7 | Identifier(path) {
8 | path.node.name = path.node.name.split('').reverse().join('');
9 | }
10 | }
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/babel7/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function (babel) {
2 | const { types: t } = babel;
3 |
4 | return {
5 | name: "ast-transform", // not required
6 | visitor: {
7 | Identifier(path) {
8 | path.node.name = path.node.name.split('').reverse().join('');
9 | }
10 | }
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/go/codeExample.txt:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | const TIPS = `
6 | Click on any AST node with a '+' to expand it
7 | Hovering over a node highlights the corresponding location in the source code
8 | Shift click on an AST node to expand the whole subtree
9 | `;
10 |
11 | func PrintTips() {
12 | fmt.Println(TIPS)
13 | }
14 |
--------------------------------------------------------------------------------
/.github/workflows/rust.yml:
--------------------------------------------------------------------------------
1 | name: Rust
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | env:
8 | CARGO_TERM_COLOR: always
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 | - run: npx envinfo
16 | - name: Build
17 | run: cargo build
18 | - name: Run tests
19 | run: cargo test
20 |
--------------------------------------------------------------------------------
/ast-website/scripts/inject-rev.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This script replaces the special character sequence @@COMMIT@@ in a file with
4 | # a link to the commit on GitHub. The file path is passed as argument but is
5 | # likely just out/index.html
6 |
7 | rev=$(git rev-parse --short HEAD)
8 | sed -i "s%@@COMMIT@@%Build: $rev%" "$1"
9 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/transpilers/typescript.js:
--------------------------------------------------------------------------------
1 | import ts from 'typescript';
2 | import protect from '../utils/protectFromLoops';
3 |
4 | let compilerOptions = { module: ts.ModuleKind.System };
5 |
6 | export default function transpile(code) {
7 | let es5Code = ts.transpileModule(code, compilerOptions).outputText;
8 | es5Code = protect(es5Code);
9 | return es5Code;
10 | }
11 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/css/codeExample.txt:
--------------------------------------------------------------------------------
1 | /**
2 | * Paste or drop some CSS here and explore
3 | * the syntax tree created by chosen parser.
4 | * Enjoy!
5 | */
6 |
7 | @media screen and (min-width: 480px) {
8 | body {
9 | background-color: lightgreen;
10 | }
11 | }
12 |
13 | #main {
14 | border: 1px solid black;
15 | }
16 |
17 | ul li {
18 | padding: 5px;
19 | }
20 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/ocaml/codeExample.txt:
--------------------------------------------------------------------------------
1 | let tips = [
2 | "Click on any AST node with a '+' to expand it";
3 |
4 | "Hovering over a node highlights the
5 | corresponding location in the source code";
6 |
7 | "Shift click on an AST node to expand the whole subtree"
8 | ]
9 |
10 | let printTips () =
11 | tips |> (List.iteri (fun i tip -> Printf.printf "Tip %d: %s\n" i tip))
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/LoadingIndicatorContainer.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'react-redux';
2 | import LoadingIndicator from '../components/LoadingIndicator';
3 | import {isLoadingSnippet} from '../store/selectors';
4 |
5 | function mapStateToProps(state) {
6 | return {
7 | visible: isLoadingSnippet(state),
8 | };
9 | }
10 |
11 | export default connect(mapStateToProps)(LoadingIndicator);
12 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/reason/codeExample.txt:
--------------------------------------------------------------------------------
1 | let tips = [
2 | "Click on any AST node with a '+' to expand it",
3 |
4 | "Hovering over a node highlights the
5 | corresponding location in the source code",
6 |
7 | "Shift click on an AST node to expand the whole subtree",
8 | ];
9 |
10 | let printTips = () =>
11 | tips |> List.iteri((i, tip) => Printf.printf("Tip %d: %s\n", i, tip));
12 |
--------------------------------------------------------------------------------
/wasm/tests/web.rs:
--------------------------------------------------------------------------------
1 | //! Test suite for the Web and headless browsers.
2 |
3 | #![cfg(target_arch = "wasm32")]
4 |
5 | extern crate wasm_bindgen_test;
6 | use monkey_wasm::parse;
7 | use wasm_bindgen_test::*;
8 |
9 | wasm_bindgen_test_configure!(run_in_browser);
10 |
11 | #[wasm_bindgen_test]
12 | fn pass() {
13 | let input = "let a = 3";
14 | let r = parse(input);
15 | println!("{}", r);
16 | }
17 |
--------------------------------------------------------------------------------
/ast-website/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "astexplorer-server",
3 | "version": "2.0.0",
4 | "main": "index.js",
5 | "private": true,
6 | "author": "Felix Kling",
7 | "dependencies": {
8 | "body-parser": "^1.15.2",
9 | "express": "^4.14.0",
10 | "github-api": "https://github.com/fkling/github.git"
11 | },
12 | "scripts": {
13 | "start": "STATIC=../out node index.js"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/playground/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import "./index.css";
5 | import { ChakraProvider } from "@chakra-ui/react";
6 |
7 | ReactDOM.createRoot(document.getElementById("root")!).render(
8 |
9 |
10 |
11 |
12 |
13 | );
14 |
--------------------------------------------------------------------------------
/ast-website/website/src/utils/debounce.js:
--------------------------------------------------------------------------------
1 | export default function debounce(f, timeout=100) {
2 | let timer;
3 | let lastArgs;
4 | let lastThis;
5 |
6 | return function(...args) {
7 | lastThis = this;
8 | lastArgs = args;
9 | if (timer) {
10 | return;
11 | }
12 | timer = setTimeout(() => {
13 | timer = null;
14 | f.apply(lastThis, lastArgs);
15 | }, timeout);
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/recast/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function transformer(code, { recast, parsers }) {
2 | const ast = recast.parse(code, { parser: parsers.esprima });
3 |
4 | recast.visit(ast, {
5 | visitIdentifier(path) {
6 | path.node.name = path.node.name.split("").reverse().join("");
7 | return false;
8 | }
9 | });
10 |
11 | return recast.print(ast).code;
12 | }
13 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/ASTOutputContainer.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'react-redux';
2 | import ASTOutput from '../components/ASTOutput';
3 | import * as selectors from '../store/selectors';
4 |
5 | function mapStateToProps(state) {
6 | return {
7 | parseResult: selectors.getParseResult(state),
8 | position: selectors.getCursor(state),
9 | };
10 | }
11 |
12 | export default connect(mapStateToProps)(ASTOutput);
13 |
--------------------------------------------------------------------------------
/packages/playground/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Monkey Language App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/utils/compileModule.js:
--------------------------------------------------------------------------------
1 | export default function compileModule(code, globals = {}) {
2 | let exports = {};
3 | let module = { exports };
4 | let globalNames = Object.keys(globals);
5 | let keys = ['module', 'exports', ...globalNames];
6 | let values = [module, exports, ...globalNames.map(key => globals[key])];
7 | new Function(keys.join(), code).apply(exports, values);
8 | return module.exports;
9 | }
10 |
--------------------------------------------------------------------------------
/lexer/snapshots/lexer__lexer_test__tests__string.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: lexer/lexer_test.rs
3 | expression: "\"a\""
4 | ---
5 | [
6 | {
7 | "kind": {
8 | "type": "STRING",
9 | "value": "a"
10 | },
11 | "span": {
12 | "start": 0,
13 | "end": 3
14 | }
15 | },
16 | {
17 | "kind": {
18 | "type": "EOF"
19 | },
20 | "span": {
21 | "start": 3,
22 | "end": 4
23 | }
24 | }
25 | ]
26 |
--------------------------------------------------------------------------------
/packages/playground/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/wat/codeExample.txt:
--------------------------------------------------------------------------------
1 | ;; This is WebAssembly Text Format (WAT).
2 | ;; Paste or drop some WAT here and explore
3 |
4 | (module
5 |
6 | ;; this is simple function that adds a couple of parameters
7 | (func (param $a i32) (param $b i32)
8 | (get_local $a)
9 | (get_local $b)
10 | (i32.add)
11 | )
12 |
13 | ;; this statement exports the function to the host environment
14 | (export "add" (func $add))
15 | )
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/java/codeExample.txt:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Example {
7 | private ArrayList names;
8 |
9 | public Example() {
10 | names = new ArrayList<>();
11 | }
12 |
13 | public void addName(String name) {
14 | names.add(name);
15 | }
16 |
17 | public List getNames() {
18 | return new ArrayList<>(names);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/mdx/codeExample.txt:
--------------------------------------------------------------------------------
1 | import MyComp from './components/MyComp'
2 |
3 | export const meta = {
4 | title: 'Page Title',
5 | description: 'This is a page description',
6 | }
7 |
8 | # Hello
9 |
10 |
11 | Component children
12 |
13 |
14 | Some *emphasis*, **importance**, and `code`.
15 |
16 | ---
17 |
18 | ```javascript
19 | console.log('!');
20 | ```
21 |
22 | * foo
23 | * bar
24 | * baz
25 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/rust/codeExample.txt:
--------------------------------------------------------------------------------
1 | const TIPS: &[&str] = &[
2 | "Click on any AST node with a '+' to expand it",
3 |
4 | "Hovering over a node highlights the \
5 | corresponding location in the source code",
6 |
7 | "Shift click on an AST node to expand the whole subtree",
8 | ];
9 |
10 | pub fn print_tips() {
11 | for (i, tip) in TIPS.iter().enumerate() {
12 | println!("Tip {}: {}.", i, tip);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ast-website/scripts/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | REMOTE=${1:-"server"}
6 | BRANCH=${2:-"master"}
7 |
8 | if ! git diff --quiet && git diff --cached --quiet; then
9 | echo >&2 "You have uncommitted changes, you probably don't want to update the server."
10 | exit 1
11 | fi
12 |
13 | for i in {5..1}; do
14 | printf "\rPushing '$BRANCH' to '$REMOTE' in $i ..." && sleep 1;
15 | done
16 |
17 | echo "\nPushing..."
18 | git push $REMOTE $BRANCH
19 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/php/codeExample.txt:
--------------------------------------------------------------------------------
1 | $tip) {
15 | echo "Tip $i: " . $tip;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_string.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: "\"jw\""
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "String",
11 | "raw": "jw",
12 | "span": {
13 | "start": 0,
14 | "end": 4
15 | }
16 | }
17 | ],
18 | "span": {
19 | "start": 0,
20 | "end": 5
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/LoadingIndicator.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 |
4 | export default function LoadingIndicator(props) {
5 | return props.visible ?
6 | :
12 | null;
13 | }
14 |
15 | LoadingIndicator.propTypes = {
16 | visible: PropTypes.bool,
17 | };
18 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/graphql/codeExample.txt:
--------------------------------------------------------------------------------
1 | # Paste or drop some GraphQL queries or schema
2 | # definitions here and explore the syntax tree
3 | # created by the GraphQL parser.
4 |
5 | query GetUser($userId: ID!) {
6 | user(id: $userId) {
7 | id,
8 | name,
9 | isViewerFriend,
10 | profilePicture(size: 50) {
11 | ...PictureFragment
12 | }
13 | }
14 | }
15 |
16 | fragment PictureFragment on Picture {
17 | uri,
18 | width,
19 | height
20 | }
21 |
--------------------------------------------------------------------------------
/wasm/src/utils.rs:
--------------------------------------------------------------------------------
1 | pub fn set_panic_hook() {
2 | // When the `console_error_panic_hook` feature is enabled, we can call the
3 | // `set_panic_hook` function at least once during initialization, and then
4 | // we will get better error messages if our code ever panics.
5 | //
6 | // For more details see
7 | // https://github.com/rustwasm/console_error_panic_hook#readme
8 | #[cfg(feature = "console_error_panic_hook")]
9 | console_error_panic_hook::set_once();
10 | }
11 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/visualization/JSON.js:
--------------------------------------------------------------------------------
1 | import JSONEditor from '../JSONEditor';
2 | import PropTypes from 'prop-types';
3 | import React from 'react';
4 |
5 | import stringify from 'json-stringify-safe';
6 |
7 | export default function JSON({parseResult}) {
8 | return (
9 |
13 | );
14 | }
15 |
16 | JSON.propTypes = {
17 | parseResult: PropTypes.object,
18 | };
19 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | jobs:
4 | test:
5 | working_directory: ~/repo
6 | docker:
7 | - image: gengjiawen/node-build
8 | steps:
9 | - checkout
10 | - run: npx envinfo
11 | - run:
12 | name: test
13 | command: |
14 | cd wasm && wasm-pack build --scope=gengjiawen
15 | - store_artifacts:
16 | path: wasm/pkg
17 |
18 | workflows:
19 | version: 2
20 | build_and_test:
21 | jobs:
22 | - test
23 |
--------------------------------------------------------------------------------
/ast-website/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - node
5 | cache:
6 | yarn: true
7 | directories:
8 | - website/node_modules
9 | before_install:
10 | - curl -o- -L https://yarnpkg.com/install.sh | bash
11 | - export PATH=$HOME/.yarn/bin:$PATH
12 | install:
13 | - cd website
14 | - yarn install --production=false
15 | before_script:
16 | - yarn lint
17 | script:
18 | - yarn watch -- --no-watch
19 | env:
20 | - NODE_ENV=development
21 | - NODE_ENV=production
22 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/markdown/transformers/remark/codeExample.txt:
--------------------------------------------------------------------------------
1 | // available utilities are: "unist-util-is", "unist-util-visit", and "unist-util-visit-parents"
2 | const visit = require("unist-util-visit");
3 |
4 | module.exports = function attacher(options) {
5 | return function transformer(tree, vfile) {
6 | // add a level to headings, for example `# heading` to `## heading`
7 | visit(tree, "heading", (node) => {
8 | node.depth += 1
9 | });
10 | return tree;
11 | };
12 | };
13 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/python/codeExample.txt:
--------------------------------------------------------------------------------
1 | print("Hello world")
2 |
3 | num1 = 1.5
4 | num2 = 6.3
5 |
6 | # Add two numbers
7 | sum = num1 + num2
8 |
9 | # Display the sum
10 | print('The sum of {0} and {1} is {2}'.format(num1, num2, sum))
11 |
12 | # Note: change this value for a different result
13 | num = 8
14 |
15 | # To take the input from the user
16 | #num = float(input('Enter a number: '))
17 |
18 | num_sqrt = num ** 0.5
19 | print('The square root of %0.3f is %0.3f'%(num ,num_sqrt))
20 |
21 |
--------------------------------------------------------------------------------
/compiler/frame.rs:
--------------------------------------------------------------------------------
1 | use crate::op_code::Instructions;
2 | use object::{Closure};
3 |
4 | #[derive(Debug, Clone)]
5 | pub struct Frame {
6 | pub cl: Closure,
7 | pub ip: i32,
8 | pub base_pointer: usize,
9 | }
10 |
11 | impl Frame {
12 | pub fn new(func: Closure, base_pointer: usize) -> Self {
13 | Frame { cl: func, ip: -1, base_pointer }
14 | }
15 |
16 | pub fn instructions(&self) -> Instructions {
17 | return Instructions { data: self.cl.func.instructions.clone() };
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ast-website/server/handlers/gist/loadGist.js:
--------------------------------------------------------------------------------
1 | const {AUTH_TOKEN} = require('../../constants');
2 | const GitHub = require('github-api');
3 |
4 | module.exports = function loadGist(req, res, next) {
5 | const gh = new GitHub({token: AUTH_TOKEN});
6 | const gist = gh.getGist(req.params.snippetid);
7 | const latest = req.params.revisionid === 'latest';
8 | (latest ?
9 | gist.read() :
10 | gist.getRevision(req.params.revisionid)
11 | )
12 | .then(response => res.json(response.data))
13 | .catch(next);
14 | };
15 |
--------------------------------------------------------------------------------
/.gitpod.yml:
--------------------------------------------------------------------------------
1 | image:
2 | file: .gitpod.Dockerfile
3 |
4 | tasks:
5 | - init: time cargo build
6 | command: cargo test
7 | - init: cargo install cargo-insta && exit # cargo insta test && cargo insta accept to update snapshots
8 | - init: cargo install cargo-workspaces
9 | - init: cd wasm && wasm-pack build --release --scope=gengjiawen && cd .. && pnpm i
10 |
11 | vscode:
12 | extensions:
13 | - vadimcn.vscode-lldb
14 | - gengjiawen.vscode-wasm
15 | - gengjiawen.vscode-postfix-ts
16 | - rust-lang.rust-analyzer
17 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/PasteDropTargetContainer.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'react-redux';
2 | import PasteDropTarget from '../components/PasteDropTarget';
3 | import {setError, dropText} from '../store/actions';
4 |
5 | function mapDispatchToProps(dispatch) {
6 | return {
7 | onText: (type, event, code, categoryId) => {
8 | dispatch(dropText(code, categoryId));
9 | },
10 | onError: error => dispatch(setError(error)),
11 | };
12 | }
13 |
14 | export default connect(null, mapDispatchToProps)(PasteDropTarget);
15 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/utils/defaultESTreeParserInterface.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../../utils/defaultParserInterface';
2 |
3 | export default {
4 | ...defaultParserInterface,
5 |
6 | opensByDefault(node, key) {
7 | return (
8 | Boolean(node) && node.type === 'Program' ||
9 | key === 'body' ||
10 | key === 'elements' || // array literals
11 | key === 'declarations' || // variable declaration
12 | key === 'expression' // expression statements
13 | );
14 | },
15 |
16 | };
17 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/buttons/NewButton.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 |
4 | export default function SaveButton({saving, forking, onNew}) {
5 | return (
6 |
12 | );
13 | }
14 |
15 | SaveButton.propTypes = {
16 | saving: PropTypes.bool,
17 | forking: PropTypes.bool,
18 | onNew: PropTypes.func,
19 | };
20 |
21 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/pug/codeExample.txt:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang='en')
3 | head
4 | title Pug
5 | script(type='text/javascript').
6 | const foo = true;
7 | let bar = function() {};
8 | if (foo) {
9 | bar(1 + 5)
10 | }
11 | body
12 | h1 Pug - node template engine
13 | #container.col
14 | p You are amazing
15 | p
16 | | Pug is a terse and simple
17 | | templating language with a
18 | | strong focus on performance
19 | | and powerful features.
20 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/buttons/ShareButton.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 |
4 | export default function ShareButton({onShareButtonClick, snippet}) {
5 | return (
6 |
12 | );
13 | }
14 |
15 | ShareButton.propTypes = {
16 | onShareButtonClick: PropTypes.func.isRequired,
17 | snippet: PropTypes.object,
18 | };
19 |
--------------------------------------------------------------------------------
/ast-website/server/handlers/gist/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const loadGist = require('./loadGist');
3 | const saveAnonymousGist = require('./saveAnonymousGist');
4 |
5 | module.exports = express.Router()
6 | // Load snippet
7 | .get('/:snippetid/:revisionid', loadGist)
8 | // Create new "anonymous" snippet
9 | .post('/', saveAnonymousGist.create)
10 | // Update "anonymous" snippet
11 | .patch('/:snippetid', saveAnonymousGist.update)
12 | // Fork "anonymous" snippet
13 | .post('/:snippetid/:revisionid', saveAnonymousGist.fork);
14 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/ErrorMessageContainer.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'react-redux';
2 | import ErrorMessage from '../components/ErrorMessage';
3 | import {clearError} from '../store/actions';
4 | import {getError} from '../store/selectors';
5 |
6 | function mapStateToProps(state) {
7 | return {
8 | error: getError(state),
9 | };
10 | }
11 |
12 |
13 | function mapDispatchToProps(dispatch) {
14 | return {
15 | onWantToClose: () => dispatch(clearError()),
16 | };
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(ErrorMessage);
20 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/css/transformers/postcss/codeExample.txt:
--------------------------------------------------------------------------------
1 | const plugin = () => ({
2 | postcssPlugin: 'postcss-reverse-props',
3 | Once(root) {
4 | // Transform CSS AST here
5 | root.walkRules(rule => {
6 | // Transform each rule here
7 | rule.walkDecls(decl => {
8 | // Transform each property declaration here
9 | decl.prop = decl.prop.split('').reverse().join('');
10 | });
11 | });
12 | }
13 | });
14 |
15 | plugin.postcss = true;
16 |
17 | export default plugin;
18 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/html/transformers/svelte/codeExample.txt:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | return {
3 | name: 'svelte-transform',
4 |
5 | // transform function for entire markup
6 | markup: function(content) {
7 | return content;
8 | },
9 |
10 | // transform function for script tag
11 | script:function(content, attributes) {
12 | return content.replace(/foo/g, 'baz');
13 | },
14 |
15 | // transform function for style tag
16 | style: function(content, attributes) {
17 | return content;
18 | }
19 | };
20 | };
21 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/handlebars.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from './utils/defaultHandlebarsParserInterface';
2 | import pkg from 'handlebars/package.json';
3 |
4 | const ID = 'handlebars';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 |
14 | loadParser(callback) {
15 | require(['handlebars'], (handlebars) => callback(handlebars.parse));
16 | },
17 |
18 | opensByDefault(node, key) {
19 | return key === 'body';
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/css/utils/defaultCSSParserInterface.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../../utils/defaultParserInterface';
2 |
3 | export default {
4 | ...defaultParserInterface,
5 |
6 | getOffset({ line, column }) {
7 | return this.lineOffsets[line - 1] + column - 1;
8 | },
9 |
10 | parse(parseCSS, code) {
11 | this.lineOffsets = [];
12 | let index = 0;
13 | do {
14 | this.lineOffsets.push(index);
15 | } while (index = code.indexOf('\n', index) + 1); // eslint-disable-line no-cond-assign
16 | return parseCSS(code);
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/codeExample.txt:
--------------------------------------------------------------------------------
1 | /**
2 | * Paste or drop some JavaScript here and explore
3 | * the syntax tree created by chosen parser.
4 | * You can use all the cool new features from ES6
5 | * and even more. Enjoy!
6 | */
7 |
8 | let tips = [
9 | "Click on any AST node with a '+' to expand it",
10 |
11 | "Hovering over a node highlights the \
12 | corresponding location in the source code",
13 |
14 | "Shift click on an AST node to expand the whole subtree"
15 | ];
16 |
17 | function printTips() {
18 | tips.forEach((tip, i) => console.log(`Tip ${i}:` + tip));
19 | }
20 |
--------------------------------------------------------------------------------
/Maintainer.md:
--------------------------------------------------------------------------------
1 | ## Version and Publish
2 |
3 | Now automated with release-please
4 |
5 | Version
6 |
7 | ```bash
8 | cargo install cargo-workspaces
9 | cargo workspaces version custom 0.7.0 --no-git-commit
10 | ```
11 |
12 | Publish
13 |
14 | ```bash
15 | cargo workspaces publish --from-git --token $CARGO_TOKEN
16 | ```
17 |
18 | ## Debug CI
19 |
20 | docker run -v $PWD:/pwd -w /pwd gengjiawen/node-build bash -c "npx envinfo"
21 | docker run -v $PWD:/pwd -w /pwd -it gengjiawen/node-build fish
22 | docker run -v $PWD:/pwd -w /pwd gengjiawen/node-build bash -c "cd wasm && wasm-pack build --release --scope=gengjiawen"
23 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/ember-template-recast.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from './utils/defaultHandlebarsParserInterface';
2 | import pkg from 'ember-template-recast/package.json';
3 |
4 | const ID = 'ember-template-recast';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 |
14 | loadParser(callback) {
15 | require(['ember-template-recast'], (recast) => callback(recast.parse));
16 | },
17 |
18 | opensByDefault(node, key) {
19 | return key === 'body';
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/ast-website/website/src/utils/stringify.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Converts a JS value to a sensible string representation.
3 | */
4 | export default function stringify(value) {
5 | switch (typeof value) {
6 | case 'function':
7 | return value.toString().match(/function[^(]*\([^)]*\)/)[0];
8 | case 'object':
9 | return value ? JSON.stringify(value, stringify) : 'null';
10 | case 'undefined':
11 | return 'undefined';
12 | case 'number':
13 | case 'bigint':
14 | return Number.isNaN(value) ? 'NaN' : String(value);
15 | default:
16 | return JSON.stringify(value);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/playground/src/Editor.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import CodeMirror, { ReactCodeMirrorProps } from '@uiw/react-codemirror';
3 | import { vim } from '@replit/codemirror-vim';
4 |
5 | interface EditorProps {
6 | extra?: ReactCodeMirrorProps,
7 | code?: string,
8 | onChange?: (code: string) => void;
9 | }
10 |
11 | export function Editor(editorProps? : EditorProps) {
12 | return (
13 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/parser/main.rs:
--------------------------------------------------------------------------------
1 | use lexer::Lexer;
2 | use parser::Parser;
3 | use std::io::stdin;
4 |
5 | pub fn main() {
6 | println!("Welcome to monkey parser by gengjiawen");
7 | loop {
8 | let mut input = String::new();
9 | stdin().read_line(&mut input).unwrap();
10 |
11 | if input.trim_end().is_empty() {
12 | println!("bye");
13 | std::process::exit(0)
14 | }
15 |
16 | let lexer = Lexer::new(&input);
17 | let mut parser = Parser::new(lexer);
18 | let program = parser.parse_program().unwrap();
19 | println!("{}", program);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/glimmer.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from './utils/defaultHandlebarsParserInterface';
2 | import pkg from '@glimmer/syntax/package.json';
3 |
4 | const ID = 'glimmer';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage || 'https://github.com/glimmerjs/glimmer-vm',
13 |
14 | loadParser(callback) {
15 | require(['@glimmer/syntax'], (glimmer) => callback(glimmer.preprocess));
16 | },
17 |
18 | opensByDefault(node, key) {
19 | return key === 'body';
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/jscodeshift/codeExample.txt:
--------------------------------------------------------------------------------
1 | // jscodeshift can take a parser, like "babel", "babylon", "flow", "ts", or "tsx"
2 | // Read more: https://github.com/facebook/jscodeshift#parser
3 | export const parser = '{{parser}}'
4 |
5 | // Press ctrl+space for code completion
6 | export default function transformer(file, api) {
7 | const j = api.jscodeshift;
8 |
9 | return j(file.source)
10 | .find(j.Identifier)
11 | .forEach(path => {
12 | j(path).replaceWith(
13 | j.identifier(path.node.name.split('').reverse().join(''))
14 | );
15 | })
16 | .toSource();
17 | }
18 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/transpilers/babel.js:
--------------------------------------------------------------------------------
1 | import * as babel from 'babel-core';
2 | import es2015 from 'babel-preset-es2015';
3 | import stage0 from 'babel-preset-stage-0';
4 | import flowStripTypes from 'babel-plugin-transform-flow-strip-types';
5 | import protect from '../utils/protectFromLoops';
6 |
7 | const options = {
8 | presets: [es2015, stage0],
9 | plugins: [flowStripTypes],
10 | ast: false,
11 | babelrc: false,
12 | highlightCode: false,
13 | };
14 |
15 | export default function transpile(code) {
16 | let es5Code = babel.transform(code, options).code;
17 | es5Code = protect(es5Code);
18 | return es5Code;
19 | }
20 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_return.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: return 3
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "ReturnStatement",
11 | "argument": {
12 | "type": "Integer",
13 | "raw": 3,
14 | "span": {
15 | "start": 7,
16 | "end": 8
17 | }
18 | },
19 | "span": {
20 | "start": 0,
21 | "end": 8
22 | }
23 | }
24 | ],
25 | "span": {
26 | "start": 0,
27 | "end": 9
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/ShareDialogContainer.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'react-redux';
2 | import {closeShareDialog} from '../store/actions';
3 | import {showShareDialog, getRevision} from '../store/selectors';
4 | import ShareDialog from '../components/dialogs/ShareDialog';
5 |
6 | function mapStateToProps(state) {
7 | return {
8 | visible: showShareDialog(state),
9 | snippet: getRevision(state),
10 | };
11 | }
12 |
13 | function mapDispatchToProps(dispatch) {
14 | return {
15 | onWantToClose: () => dispatch(closeShareDialog()),
16 | };
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(ShareDialog);
20 |
--------------------------------------------------------------------------------
/packages/playground/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | // @ts-ignore
4 | import topLevelAwait from "vite-plugin-top-level-await"
5 | import wasm from "vite-plugin-wasm"
6 | import visualizer from 'rollup-plugin-visualizer'
7 |
8 | // https://vitejs.dev/config/
9 | export default defineConfig({
10 | base: process.env.GITHUB_ACTION ? '/monkey-rust/' : '/',
11 | server: {
12 | port: 3000
13 | },
14 | plugins: [
15 | react(),
16 | wasm(),
17 | topLevelAwait()
18 | ],
19 | build: {
20 | rollupOptions: {
21 | plugins: [visualizer()],
22 | },
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/object/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "monkey-object"
3 | version = "0.10.1"
4 | description = "a object system for monkey lang"
5 | homepage = "https://github.com/gengjiawen/monkey-rust"
6 | repository = "https://github.com/gengjiawen/monkey-rust"
7 | authors = ["gengjiawen "]
8 | edition = "2018"
9 | license = "MIT"
10 |
11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
12 |
13 | [lib]
14 | name = "object"
15 | path= "object.rs"
16 |
17 | [dependencies]
18 | lazy_static = "1.5.0"
19 | monkey-parser = { path = "../parser", version = "0.10.0" }
20 |
21 | [dev-dependencies]
22 | insta = "1.42.2"
23 |
--------------------------------------------------------------------------------
/packages/playground/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": true,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/.github/workflows/prepare-release.yml:
--------------------------------------------------------------------------------
1 | name: prepare-dist
2 | on:
3 | push:
4 | branches:
5 | - 'release-*'
6 | - 'release/*'
7 | create:
8 | branches:
9 | - 'release-*'
10 | - 'release/*'
11 | workflow_dispatch:
12 | jobs:
13 | prepare-dist:
14 | runs-on: ubuntu-latest
15 | permissions:
16 | contents: write
17 | steps:
18 | - uses: actions/checkout@v3
19 | - run: docker run -v $PWD:/pwd -w /pwd gengjiawen/node-build bash -c "yarn && pnpx ts-node scripts/bump_cargo_packages.ts"
20 | - uses: stefanzweifel/git-auto-commit-action@v4
21 | with:
22 | commit_message: 'chore: prepare rust packages'
23 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint4/codeExample.txt:
--------------------------------------------------------------------------------
1 | export default function(context) {
2 | return {
3 | TemplateLiteral(node) {
4 | context.report({
5 | node,
6 | message: 'Do not use template literals',
7 |
8 | fix(fixer) {
9 | if (node.expressions.length) {
10 | // Can't auto-fix template literal with expressions
11 | return;
12 | }
13 |
14 | return [
15 | fixer.replaceTextRange([node.start, node.start + 1], '"'),
16 | fixer.replaceTextRange([node.end - 1, node.end], '"'),
17 | ];
18 | },
19 | });
20 | }
21 | };
22 | };
23 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/sql/sqlite-parser.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'sqlite-parser/package.json';
3 |
4 | const ID = 'sqlite-parser';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage || 'https://github.com/codeschool/sqlite-parser',
13 |
14 | loadParser(callback) {
15 | require(['sqlite-parser'], callback);
16 | },
17 |
18 | parse(sqliteParser, code) {
19 | return sqliteParser(code);
20 | },
21 |
22 | opensByDefault(node, key) {
23 | return key === 'statement';
24 | },
25 |
26 | };
27 |
--------------------------------------------------------------------------------
/compiler/symbol_table_test.rs:
--------------------------------------------------------------------------------
1 | #[cfg(test)]
2 | mod tests {
3 | use crate::symbol_table::{SymbolScope, SymbolTable};
4 | #[test]
5 | fn test_define() {
6 | let mut symbol_table = SymbolTable::new();
7 | let symbol = symbol_table.define("x".to_string());
8 | assert_eq!(symbol.name, "x");
9 | assert_eq!(symbol.scope, SymbolScope::Global);
10 | assert_eq!(symbol.index, 0);
11 | }
12 |
13 | #[test]
14 | fn test_resolve() {
15 | let mut symbol_table = SymbolTable::new();
16 | let symbol = symbol_table.define("x".to_string());
17 | assert_eq!(symbol_table.resolve("x".to_string()), Some(symbol));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lexer/main.rs:
--------------------------------------------------------------------------------
1 | use lexer::token::TokenKind;
2 | use lexer::Lexer;
3 | use std::io::stdin;
4 |
5 | pub fn main() {
6 | println!("Welcome to monkey lexer by gengjiawen");
7 | loop {
8 | let mut input = String::new();
9 | stdin().read_line(&mut input).unwrap();
10 |
11 | if input.trim_end().is_empty() {
12 | println!("bye");
13 | std::process::exit(0)
14 | }
15 |
16 | let mut l = Lexer::new(&input);
17 | loop {
18 | let t = l.next_token();
19 | if t.kind == TokenKind::EOF {
20 | break;
21 | } else {
22 | println!("{}", t)
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lexer/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "monkey-lexer"
3 | version = "0.10.1"
4 | description = "a lexer for monkey lang"
5 | homepage = "https://github.com/gengjiawen/monkey-rust"
6 | repository = "https://github.com/gengjiawen/monkey-rust"
7 | authors = ["gengjiawen "]
8 | edition = "2018"
9 | license = "MIT"
10 |
11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
12 |
13 | [lib]
14 | name = "lexer"
15 | path= "lib.rs"
16 |
17 | [[bin]]
18 | name = "monkey-lexer"
19 | path = "main.rs"
20 |
21 | [dependencies]
22 | serde = {version = "1.0", features = ["derive"]}
23 | serde_json = "1.0"
24 |
25 | [dev-dependencies]
26 | insta = "1.42.2"
27 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/SettingsDrawerContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import { expandSettingsDrawer, collapseSettingsDrawer } from '../store/actions';
3 | import { showSettingsDrawer } from '../store/selectors';
4 | import SettingsDrawer from '../components/SettingsDrawer';
5 |
6 | function mapStateToProps(state) {
7 | return {
8 | isOpen: showSettingsDrawer(state),
9 | };
10 | }
11 |
12 | function mapDispatchToProps(dispatch) {
13 | return {
14 | onWantToExpand: () => dispatch(expandSettingsDrawer()),
15 | onWantToCollapse: () => dispatch(collapseSettingsDrawer()),
16 | };
17 | }
18 |
19 | export default connect(
20 | mapStateToProps,
21 | mapDispatchToProps,
22 | )(SettingsDrawer);
23 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/json/json-to-ast.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'json-to-ast/package.json';
3 |
4 | const ID = 'jsonToAst';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['loc']),
14 |
15 | loadParser(callback) {
16 | require(['json-to-ast'], callback);
17 | },
18 |
19 | parse(jsonToAst, code) {
20 | return jsonToAst(code);
21 | },
22 |
23 | nodeToRange({loc}) {
24 | if (loc) {
25 | return [
26 | loc.start.offset,
27 | loc.end.offset,
28 | ];
29 | }
30 | },
31 | }
32 |
--------------------------------------------------------------------------------
/interpreter/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "monkey-interpreter"
3 | version = "0.10.1"
4 | description = "an interpreter for monkeylang"
5 | homepage = "https://github.com/gengjiawen/monkey-rust"
6 | repository = "https://github.com/gengjiawen/monkey-rust"
7 | authors = ["gengjiawen "]
8 | edition = "2018"
9 | license = "MIT"
10 |
11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
12 |
13 | [lib]
14 | name = "interpreter"
15 | path= "lib.rs"
16 |
17 | [[bin]]
18 | name = "monkey-interpreter"
19 | path = "main.rs"
20 |
21 | [dependencies]
22 | monkey-parser = { path = "../parser", version = "0.10.0" }
23 | monkey-object = { path = "../object", version = "0.10.0" }
24 |
--------------------------------------------------------------------------------
/lexer/snapshots/lexer__lexer_test__tests__array.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: lexer/lexer_test.rs
3 | expression: "[3]"
4 | ---
5 | [
6 | {
7 | "kind": {
8 | "type": "LBRACKET"
9 | },
10 | "span": {
11 | "start": 0,
12 | "end": 1
13 | }
14 | },
15 | {
16 | "kind": {
17 | "type": "INT",
18 | "value": 3
19 | },
20 | "span": {
21 | "start": 1,
22 | "end": 2
23 | }
24 | },
25 | {
26 | "kind": {
27 | "type": "RBRACKET"
28 | },
29 | "span": {
30 | "start": 2,
31 | "end": 3
32 | }
33 | },
34 | {
35 | "kind": {
36 | "type": "EOF"
37 | },
38 | "span": {
39 | "start": 3,
40 | "end": 4
41 | }
42 | }
43 | ]
44 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/monkey/codeExample.txt:
--------------------------------------------------------------------------------
1 | let version = 1 + (50 / 2) - (8 * 3);
2 |
3 | let name = "The Monkey programming language";
4 |
5 | let isMonkeyFastNow = true;
6 |
7 | let people = [{"name": "Anna", "age": 24}, {"name": "Bob", "age": 99}];
8 |
9 | let getName = fn(person) { person["name"]; };
10 | getName(people[0]);
11 | getName(people[1]);
12 |
13 | puts(len(people))
14 |
15 | let fibonacci = fn(x) {
16 | if (x == 0) {
17 | 0
18 | } else {
19 | if (x == 1) {
20 | return 1;
21 | } else {
22 | fibonacci(x - 1) + fibonacci(x - 2);
23 | }
24 | }
25 | };
26 |
27 |
28 | let newAdder = fn(a, b) {
29 | fn(c) { a + b + c };
30 | };
31 |
32 | let adder = newAdder(1, 2);
33 |
34 | adder(8);
35 |
--------------------------------------------------------------------------------
/compiler/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "monkey-compiler"
3 | version = "0.10.1"
4 | description = "a compiler for monkeylang"
5 | homepage = "https://github.com/gengjiawen/monkey-rust"
6 | repository = "https://github.com/gengjiawen/monkey-rust"
7 | authors = ["gengjiawen "]
8 | edition = "2018"
9 | license = "MIT"
10 |
11 | [lib]
12 | name = "compiler"
13 | path= "lib.rs"
14 |
15 | [[bin]]
16 | name = "monkey-compiler"
17 | path = "main.rs"
18 |
19 | [dependencies]
20 | lazy_static = "1.5.0"
21 | byteorder = "1.5.0"
22 | strum = { version = "0.25.0", features = ["derive"]}
23 | strum_macros = "0.26"
24 | monkey-parser = { path = "../parser", version = "0.10.0" }
25 | monkey-object = { path = "../object", version = "0.10.0" }
26 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/utils/protectFromLoops.js:
--------------------------------------------------------------------------------
1 | import halts, {loopProtect} from 'halting-problem';
2 |
3 | export default function protect(jsCode) {
4 | // assert that there are no obvious infinite loops
5 | halts(jsCode);
6 | // guard against non-obvious loops with a timeout of 5 seconds
7 | let start = Date.now();
8 | jsCode = loopProtect(
9 | jsCode,
10 | [
11 | // this function gets called in all possible loops
12 | // it gets passed the line number as its only argument
13 | '(function (line) {',
14 | 'if (Date.now() > ' + (start + 5000) + ') {',
15 | ' throw new Error("Infinite loop detected on line " + line);',
16 | '}',
17 | '})',
18 | ].join(''),
19 | );
20 |
21 | return jsCode;
22 | }
23 |
--------------------------------------------------------------------------------
/ast-website/website/src/core/ParseResult.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Describes the result of a parse process. Only exists here for documentation
3 | * purposes.
4 | */
5 | // eslint-disable-next-line no-unused-vars
6 | const ParseResult = {
7 | /**
8 | * The generated AST
9 | */
10 | ast: 'any',
11 |
12 | /**
13 | * An error object, if parsing resulted in an error
14 | */
15 | error: 'Object',
16 |
17 | /**
18 | * How long it took to generate the AST
19 | */
20 | time: 'number',
21 |
22 | treeAdapter: {
23 | /**
24 | * The type of the adapter to use, as defined in TreeAdapters.js
25 | */
26 | type: 'string',
27 | /**
28 | * Override the default options with these values
29 | */
30 | options: 'Object',
31 | },
32 | };
33 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2020",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "sourceMap": true,
7 | "declaration": true,
8 | "allowSyntheticDefaultImports": true,
9 | "removeComments": true,
10 | "noImplicitAny": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "strictNullChecks": true,
14 | "noUnusedLocals": false,
15 | "experimentalDecorators": true,
16 | "emitDecoratorMetadata": true,
17 | "strict": true,
18 | "outDir": "./build",
19 | "lib": [
20 | "es2020",
21 | "dom"
22 | ]
23 | },
24 | "exclude": [
25 | "node_modules",
26 | "build",
27 | "test",
28 | "**/*.test.ts"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/packages/playground/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-float infinite 3s ease-in-out;
13 | }
14 | }
15 |
16 | .App-header {
17 | min-height: 100vh;
18 | display: flex;
19 | flex-direction: column;
20 | align-items: center;
21 | justify-content: center;
22 | font-size: calc(10px + 2vmin);
23 | }
24 |
25 | .App-link {
26 | color: rgb(112, 76, 182);
27 | }
28 |
29 | @keyframes App-logo-float {
30 | 0% {
31 | transform: translateY(0);
32 | }
33 | 50% {
34 | transform: translateY(10px);
35 | }
36 | 100% {
37 | transform: translateY(0px);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/parser/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "monkey-parser"
3 | version = "0.10.1"
4 | description = "a parser for monkey lang"
5 | homepage = "https://github.com/gengjiawen/monkey-rust"
6 | repository = "https://github.com/gengjiawen/monkey-rust"
7 | authors = ["gengjiawen "]
8 | edition = "2018"
9 | license = "MIT"
10 |
11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
12 |
13 | [lib]
14 | name = "parser"
15 | path= "lib.rs"
16 |
17 | [[bin]]
18 | name = "monkey-parser"
19 | path = "main.rs"
20 |
21 | [dependencies]
22 | monkey-lexer = { path = "../lexer", version = "0.10.0" }
23 | serde = {version = "1.0", features = ["derive"]}
24 | serde_json = "1.0"
25 |
26 | [dev-dependencies]
27 | insta = "1.42.2"
28 |
29 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/graphviz/redot.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'redot/package.json';
3 |
4 | const ID = 'redot';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['position']),
14 |
15 | loadParser(callback) {
16 | require(['redot'], callback);
17 | },
18 |
19 | parse(redot, code) {
20 | return redot().parse(code);
21 | },
22 |
23 | nodeToRange({ position }) {
24 | if (position) {
25 | return [position.start.offset, position.end.offset];
26 | }
27 | },
28 |
29 | opensByDefault(node, key) {
30 | return key === 'children';
31 | },
32 | };
33 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/protobuf/codeExample.txt:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package tutorial;
3 |
4 | import "google/protobuf/timestamp.proto";
5 |
6 | option go_package = "github.com/protocolbuffers/protobuf/examples/go/tutorialpb";
7 |
8 | message Person {
9 | string name = 1;
10 | int32 id = 2; // Unique ID number for this person.
11 | string email = 3;
12 |
13 | enum PhoneType {
14 | MOBILE = 0;
15 | HOME = 1;
16 | WORK = 2;
17 | }
18 |
19 | message PhoneNumber {
20 | string number = 1;
21 | PhoneType type = 2;
22 | }
23 |
24 | repeated PhoneNumber phones = 4;
25 |
26 | google.protobuf.Timestamp last_updated = 5;
27 | }
28 |
29 | // Our address book file is just one of these.
30 | message AddressBook {
31 | repeated Person people = 1;
32 | }
33 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint8/codeExample.txt:
--------------------------------------------------------------------------------
1 | export const meta = {
2 | type: 'problem',
3 | hasSuggestions: true,
4 | fixable: true,
5 | };
6 |
7 | export function create(context) {
8 | return {
9 | TemplateLiteral(node) {
10 | context.report({
11 | node,
12 | message: 'Do not use template literals',
13 |
14 | fix(fixer) {
15 | if (node.expressions.length) {
16 | // Can't auto-fix template literal with expressions
17 | return;
18 | }
19 |
20 | return [
21 | fixer.replaceTextRange([node.start, node.start + 1], '"'),
22 | fixer.replaceTextRange([node.end - 1, node.end], '"'),
23 | ];
24 | },
25 | });
26 | }
27 | };
28 | };
29 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/LocalStorage.js:
--------------------------------------------------------------------------------
1 | const storage = global.localStorage;
2 | const key = 'explorerSettingsV1';
3 | const noop = () => {};
4 |
5 | export const writeState = storage ?
6 | state => {
7 | try {
8 | storage.setItem(key, JSON.stringify(state));
9 | } catch(e) {
10 | // eslint-disable-next-line no-console
11 | console.warn('Unable to write to local storage.');
12 | }
13 | } :
14 | noop;
15 |
16 | export const readState = storage ?
17 | () => {
18 | try {
19 | const state = storage.getItem(key);
20 | if (state) {
21 | return JSON.parse(state);
22 | }
23 | } catch(e) {
24 | // eslint-disable-next-line no-console
25 | console.warn('Unable to read from local storage.');
26 | }
27 | } :
28 | noop;
29 |
--------------------------------------------------------------------------------
/ast-website/website/fontcustom/input-svg/reason.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint8/index.js:
--------------------------------------------------------------------------------
1 | import pkg from 'eslint8/package.json';
2 |
3 | const ID = 'eslint-v8';
4 | const name = 'ESLint v8';
5 |
6 | export default {
7 | id: ID,
8 | displayName: name,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 |
12 | defaultParserID: 'babel-eslint',
13 |
14 | loadTransformer(callback) {
15 | require([
16 | 'eslint8/lib/linter',
17 | 'eslint8/lib/source-code',
18 | '../../utils/eslint4Utils',
19 | ], (Linter, sourceCode, utils) =>
20 | callback({ eslint: new Linter.Linter(), sourceCode, utils }));
21 | },
22 |
23 | transform({ eslint, sourceCode, utils }, transformCode, code) {
24 | utils.defineRule(eslint, transformCode);
25 | return utils.runRule(code, eslint, sourceCode);
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_index.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: "a[1]"
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "Index",
11 | "object": {
12 | "type": "IDENTIFIER",
13 | "name": "a",
14 | "span": {
15 | "start": 0,
16 | "end": 1
17 | }
18 | },
19 | "index": {
20 | "type": "Integer",
21 | "raw": 1,
22 | "span": {
23 | "start": 2,
24 | "end": 3
25 | }
26 | },
27 | "span": {
28 | "start": 1,
29 | "end": 4
30 | }
31 | }
32 | ],
33 | "span": {
34 | "start": 0,
35 | "end": 5
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/visualization/css/tree.css:
--------------------------------------------------------------------------------
1 | .tree-visualization {
2 | display: flex;
3 | flex-direction: column;
4 | }
5 |
6 | .tree-visualization > .toolbar {
7 | padding: 5px;
8 | flex-shrink: 0;
9 | }
10 |
11 | .tree-visualization > .toolbar label {
12 | cursor: pointer;
13 | margin-right: 5px;
14 | -webkit-touch-callout: none;
15 | user-select: none;
16 | white-space: nowrap;
17 | }
18 |
19 | .tree-visualization ul {
20 | margin: 0;
21 | padding-left: 20px;
22 | overflow: auto;
23 | }
24 |
25 | .tree-visualization > ul {
26 | cursor: default;
27 | box-sizing: border-box;
28 | font-family: monospace;
29 | -webkit-touch-callout: none;
30 | user-select: none;
31 | flex: 1;
32 | }
33 |
34 | .tree-visualization .value-body {
35 | min-width: 300px;
36 | width: fit-content;
37 | }
38 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/SettingsDialogContainer.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'react-redux';
2 | import {closeSettingsDialog, setParserSettings} from '../store/actions';
3 | import {showSettingsDialog, getParser, getParserSettings} from '../store/selectors';
4 | import SettingsDialog from '../components/dialogs/SettingsDialog';
5 |
6 | function mapStateToProps(state) {
7 | return {
8 | visible: showSettingsDialog(state),
9 | parser: getParser(state),
10 | parserSettings: getParserSettings(state),
11 | };
12 | }
13 |
14 | function mapDispatchToProps(dispatch) {
15 | return {
16 | onSave: (parser, newSettings) => dispatch(setParserSettings(newSettings)),
17 | onWantToClose: () => dispatch(closeSettingsDialog()),
18 | };
19 | }
20 |
21 | export default connect(mapStateToProps, mapDispatchToProps)(SettingsDialog);
22 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/css/rework.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from './utils/defaultCSSParserInterface';
2 | import pkg from 'css/package.json';
3 |
4 | const ID = 'rework';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage || 'https://github.com/reworkcss/rework',
13 | locationProps: new Set(['position']),
14 |
15 | loadParser(callback) {
16 | require(['css/lib/parse'], callback);
17 | },
18 |
19 | nodeToRange({ position: range }) {
20 | if (!range) return;
21 | return [range.start, range.end].map(pos => this.getOffset(pos));
22 | },
23 |
24 | opensByDefault(node, key) {
25 | return key === 'rules';
26 | },
27 |
28 | _ignoredProperties: new Set(['parsingErrors', 'source', 'content']),
29 | };
30 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint4/index.js:
--------------------------------------------------------------------------------
1 | import pkg from 'eslint4/package.json';
2 |
3 | const ID = 'eslint-v4';
4 | const name = 'ESLint v4';
5 |
6 | export default {
7 | id: ID,
8 | displayName: name,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 |
12 | defaultParserID: 'babel-eslint',
13 |
14 | loadTransformer(callback) {
15 | require(
16 | [
17 | 'eslint4/lib/linter',
18 | 'eslint4/lib/util/source-code',
19 | '../../utils/eslint4Utils',
20 | ],
21 | (Linter, sourceCode, utils) => callback({eslint: new Linter(), sourceCode, utils}),
22 | );
23 | },
24 |
25 | transform({ eslint, sourceCode, utils }, transformCode, code) {
26 | utils.defineRule(eslint, transformCode);
27 | return utils.runRule(code, eslint, sourceCode);
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/tslint/codeExample.txt:
--------------------------------------------------------------------------------
1 | export class Rule extends Lint.Rules.AbstractRule {
2 | public static FAILURE_STRING = "Do not use template literals";
3 |
4 | public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
5 | return this.applyWithWalker(new NoTemplateExpressionWalker(sourceFile, this.getOptions()));
6 | }
7 | }
8 |
9 | // The walker takes care of all the work.
10 | class NoTemplateExpressionWalker extends Lint.RuleWalker {
11 | public visitTemplateExpression(node: ts.TemplateExpression) {
12 | // create a failure at the current position
13 | this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
14 |
15 | // call the base version of this visitor to actually parse this node
16 | super.visitTemplateExpression(node);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_unary.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: "-3"
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "UnaryExpression",
11 | "op": {
12 | "kind": {
13 | "type": "MINUS"
14 | },
15 | "span": {
16 | "start": 0,
17 | "end": 1
18 | }
19 | },
20 | "operand": {
21 | "type": "Integer",
22 | "raw": 3,
23 | "span": {
24 | "start": 1,
25 | "end": 2
26 | }
27 | },
28 | "span": {
29 | "start": 0,
30 | "end": 2
31 | }
32 | }
33 | ],
34 | "span": {
35 | "start": 0,
36 | "end": 3
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/visualization/tree/CompactObjectView.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 |
4 | export default function CompactObjectView({keys, onClick}) {
5 | if (keys.length === 0) {
6 | return {'{ }'};
7 | } else {
8 | if (keys.length > 5) {
9 | keys = keys.slice(0, 5).concat([`... +${keys.length - 5}`]);
10 | }
11 | return (
12 |
13 | {'{'}
14 |
15 | {keys.join(', ')}
16 |
17 | {'}'}
18 |
19 | );
20 | }
21 | }
22 |
23 | CompactObjectView.propTypes = {
24 | keys: PropTypes.arrayOf(PropTypes.string).isRequired,
25 | onClick: PropTypes.func,
26 | };
27 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/buttons/SaveButton.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 | import cx from '../../utils/classnames.js';
4 |
5 | export default function SaveButton({canSave, saving, forking, onSave}) {
6 | return (
7 |
23 | );
24 | }
25 |
26 | SaveButton.propTypes = {
27 | canSave: PropTypes.bool,
28 | saving: PropTypes.bool,
29 | forking: PropTypes.bool,
30 | onSave: PropTypes.func,
31 | };
32 |
--------------------------------------------------------------------------------
/ast-website/scripts/check-conflicts.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | SOURCE_DIR=$1
4 | TARGET_DIR=$2
5 |
6 | for source_file in $(ls $1); do
7 | target_path=$TARGET_DIR/$source_file
8 | source_path=$SOURCE_DIR/$source_file
9 |
10 | if ! [ -f $target_path ]; then
11 | # If a file with the same name doesn't exist in the target directory, all is
12 | # good.
13 | continue
14 | fi
15 |
16 | case $source_file in
17 | # These files are allowed to differ since the are
18 | # not cached
19 | index.html|favicon.png)
20 | continue
21 | ;;
22 | esac
23 |
24 | if ! diff --brief $target_path $source_path > /dev/null; then
25 | echo "File '$source_file' already exists but has different content."
26 | conflict=1
27 | fi
28 | done
29 |
30 | if [ -n "$conflict" ]; then
31 | echo "Bump the cache breaker."
32 | exit 1
33 | fi
34 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/buttons/PrettierButton.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 | import cx from '../../utils/classnames.js';
4 |
5 | export default function PrettierButton(props) {
6 | return ();
20 | }
21 |
22 | PrettierButton.propTypes = {
23 | toggleFormatting: PropTypes.func,
24 | enableFormatting: PropTypes.bool,
25 | }
26 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/protobuf/pbkit.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'pbkit/package.json';
3 |
4 | const ID = 'pbkit';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 | id: ID,
9 | displayName: ID,
10 | version: pkg.version,
11 | homepage: 'https://github.com/riiid/pbkit',
12 | locationProps: new Set(['start', 'end']),
13 | typeProps: new Set(['type']),
14 |
15 | loadParser(callback) {
16 | require(['pbkit/core/parser/proto'], callback);
17 | },
18 |
19 | parse(parser, code) {
20 | return parser.parse(code).ast;
21 | },
22 |
23 | nodeToRange(node) {
24 | const { start, end } = node;
25 | return [start, end];
26 | },
27 |
28 | opensByDefault(node, key) {
29 | if (key === 'statements') {
30 | return true;
31 | }
32 | },
33 | };
34 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/go/go.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface'
2 |
3 | const ID = 'go'
4 |
5 | export default {
6 | ...defaultParserInterface,
7 |
8 | id: ID,
9 | displayName: ID,
10 | version: '1.13.4',
11 | homepage: 'https://golang.org/pkg/go/',
12 | _ignoredProperties: new Set(['_type']),
13 | locationProps: new Set(['Loc']),
14 |
15 | async loadParser(callback) {
16 | require(['astexplorer-go'], async parser => {
17 | await parser.init()
18 | callback(parser)
19 | })
20 | },
21 |
22 | parse(parser, code) {
23 | return parser.parseFile(code)
24 | },
25 |
26 | getNodeName(node) {
27 | return node._type
28 | },
29 |
30 | nodeToRange(node) {
31 | if (node.Loc) {
32 | return [node.Loc.Start, node.Loc.End].map(({ Offset }) => Offset)
33 | }
34 | },
35 | }
36 |
--------------------------------------------------------------------------------
/ast-website/website/src/containers/CodeEditorContainer.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'react-redux';
2 | import {setCode, setCursor} from '../store/actions';
3 | import Editor from '../components/Editor';
4 | import {getCode, getParser, getParseResult, getKeyMap} from '../store/selectors';
5 |
6 | function mapStateToProps(state) {
7 | return {
8 | keyMap: getKeyMap(state),
9 | value: getCode(state),
10 | mode: getParser(state).category.editorMode || getParser(state).category.id,
11 | error: (getParseResult(state) || {}).error,
12 | };
13 | }
14 |
15 | function mapDispatchToProps(dispatch) {
16 | return {
17 | onContentChange: ({value, cursor}) => {
18 | dispatch(setCode({code: value, cursor}));
19 | },
20 | onActivity: cursor => dispatch(setCursor(cursor)),
21 | };
22 | }
23 |
24 | export default connect(mapStateToProps, mapDispatchToProps)(Editor);
25 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/handlebars/utils/defaultHandlebarsParserInterface.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../../utils/defaultParserInterface';
2 |
3 | export default {
4 | ...defaultParserInterface,
5 |
6 | locationProps: new Set(['loc']),
7 |
8 | parse(parseHandlebars, code) {
9 | this.lineOffsets = [];
10 | let index = 0;
11 | do {
12 | this.lineOffsets.push(index);
13 | } while (index = code.indexOf('\n', index) + 1); // eslint-disable-line no-cond-assign
14 | return parseHandlebars(code);
15 | },
16 |
17 | getOffset({ line, column }) {
18 | return this.lineOffsets[line - 1] + column;
19 | },
20 |
21 | nodeToRange({ loc }) {
22 | if (!loc) return;
23 | const serializedLoc = 'toJSON' in loc ? loc.toJSON() : loc;
24 | return [serializedLoc.start, serializedLoc.end].map(pos => this.getOffset(pos));
25 | },
26 | };
27 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/san/san-template-parser.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'san/package.json';
3 |
4 | const ID = 'san';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set([]),
14 | typeProps: new Set(['tag']),
15 |
16 | loadParser(callback) {
17 | require(['san'], callback);
18 | },
19 |
20 | parse(parser, code, options) {
21 | return parser.parseTemplate(code, options).children[0];
22 | },
23 |
24 | opensByDefault(node, key) {
25 | return key === 'children';
26 | },
27 |
28 | getNodeName(node) {
29 | return node.tagName;
30 | },
31 |
32 | getDefaultOptions() {
33 | return {};
34 | },
35 | _ignoredProperties: new Set([]),
36 | };
37 |
--------------------------------------------------------------------------------
/interpreter/main.rs:
--------------------------------------------------------------------------------
1 | use interpreter::eval;
2 | use object::environment::Env;
3 | use parser::parse;
4 | use std::cell::RefCell;
5 | use std::io::stdin;
6 | use std::rc::Rc;
7 |
8 | fn main() {
9 | println!("Welcome to monkey interpreter by gengjiawen");
10 | let env: Env = Rc::new(RefCell::new(Default::default()));
11 | loop {
12 | let mut input = String::new();
13 | stdin().read_line(&mut input).unwrap();
14 |
15 | if input.trim_end().is_empty() {
16 | println!("bye");
17 | std::process::exit(0)
18 | }
19 |
20 | match parse(&input) {
21 | Ok(node) => match eval(node, &env) {
22 | Ok(evaluated) => println!("{}", evaluated),
23 | Err(e) => eprintln!("{}", e),
24 | },
25 | Err(e) => eprintln!("parse error: {}", e[0]),
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_array.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: "[1, true]"
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "Array",
11 | "elements": [
12 | {
13 | "type": "Integer",
14 | "raw": 1,
15 | "span": {
16 | "start": 1,
17 | "end": 2
18 | }
19 | },
20 | {
21 | "type": "Boolean",
22 | "raw": true,
23 | "span": {
24 | "start": 4,
25 | "end": 8
26 | }
27 | }
28 | ],
29 | "span": {
30 | "start": 0,
31 | "end": 9
32 | }
33 | }
34 | ],
35 | "span": {
36 | "start": 0,
37 | "end": 10
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/html/posthtml.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'posthtml-parser/package.json';
3 |
4 | const ID = 'posthtml-parser';
5 | const name = 'posthtml-parser';
6 |
7 | export default {
8 | ...defaultParserInterface,
9 |
10 | id: ID,
11 | displayName: name,
12 | version: pkg.version,
13 | homepage: pkg.homepage || 'https://github.com/fb55/htmlparser2',
14 |
15 | loadParser(callback) {
16 | require(['posthtml-parser'], callback);
17 | },
18 |
19 | parse(posthtmlParser, code, options) {
20 | return posthtmlParser(code, options);
21 | },
22 |
23 | opensByDefault(node, key) {
24 | return key === 'content';
25 | },
26 |
27 | getDefaultOptions() {
28 | return { lowerCaseTags: false, lowerCaseAttributeNames: false };
29 | },
30 |
31 | typeProps: new Set(['tag']),
32 | };
33 |
--------------------------------------------------------------------------------
/ast-website/website/src/utils/pubsub.js:
--------------------------------------------------------------------------------
1 | const subscribers = {};
2 |
3 | export function subscribe(topic, handler) {
4 | let handlers = subscribers[topic];
5 | if (!handlers) {
6 | handlers = subscribers[topic] = [];
7 | }
8 | if (handlers.indexOf(handler) === -1) {
9 | handlers.push(handler);
10 | }
11 |
12 | return () => handlers.splice(handlers.indexOf(handler), 1);
13 | }
14 |
15 | export function publish(topic, data) {
16 | if (subscribers[topic]) {
17 | setTimeout(function callSubscribers() {
18 | if (subscribers[topic]) {
19 | const handlers = subscribers[topic];
20 | for (var i = 0; i < handlers.length; i++) {
21 | handlers[i](data);
22 | }
23 | }
24 | }, 0);
25 | }
26 | }
27 |
28 | export function clear(unsubscribers) {
29 | unsubscribers.forEach(call);
30 | }
31 |
32 | function call(f) {
33 | return f();
34 | }
35 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/lua/codeExample.txt:
--------------------------------------------------------------------------------
1 | --[[
2 | Paste or drop some Lua here and explore
3 | the syntax tree created by chosen parser.
4 | Enjoy!
5 | --]]
6 |
7 | function allwords ()
8 | local line = io.read() -- current line
9 | local pos = 1 -- current position in the line
10 | return function () -- iterator function
11 | while line do -- repeat while there are lines
12 | local s, e = string.find(line, "%w+", pos)
13 | if s then -- found a word?
14 | pos = e + 1 -- update next position
15 | return string.sub(line, s, e) -- return the word
16 | else
17 | line = io.read() -- word not found; try next line
18 | pos = 1 -- restart from first position
19 | end
20 | end
21 | return nil -- no more lines: end of traversal
22 | end
23 | end
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/regexp/transformers/regexp-tree/index.js:
--------------------------------------------------------------------------------
1 | import compileModule from '../../../utils/compileModule';
2 | import pkg from 'regexp-tree/package.json';
3 |
4 | const ID = 'regexp-tree';
5 |
6 | export default {
7 | id: ID,
8 | displayName: ID,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 |
12 | defaultParserID: ID,
13 |
14 | loadTransformer(callback) {
15 | require([
16 | '../../../transpilers/babel',
17 | 'regexp-tree',
18 | ], (transpile, regexpTree) => callback({ transpile: transpile.default, regexpTree }));
19 | },
20 |
21 | transform({ transpile, regexpTree }, transformCode, code) {
22 | transformCode = transpile(transformCode);
23 | let handler = compileModule( // eslint-disable-line no-shadow
24 | transformCode,
25 | );
26 |
27 | return regexpTree.transform(code, handler).toString();
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/visualization/SelectedNodeContext.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const SelectedNodeContext = React.createContext();
4 |
5 | function useSelectedNode() {
6 | const context = React.useContext(SelectedNodeContext);
7 | if (!context) {
8 | throw new Error('useSelectedNode must be used within a SelectedNodeContext');
9 | }
10 | return context;
11 | }
12 |
13 | let unselectCallback;
14 |
15 | function setSelectedNode(node, cb) {
16 | if (unselectCallback) {
17 | unselectCallback();
18 | }
19 | if (node) {
20 | global.$node = node;
21 | unselectCallback = cb;
22 | } else {
23 | unselectCallback = null;
24 | delete global.$node;
25 | }
26 | }
27 |
28 | function SelectedNodeProvider(props) {
29 | return ;
30 | }
31 |
32 | export {SelectedNodeProvider, useSelectedNode};
33 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/json/momoa.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from '@humanwhocodes/momoa/package.json';
3 |
4 | const ID = 'momoa';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['loc']),
14 |
15 | loadParser(callback) {
16 | require(['@humanwhocodes/momoa'], callback);
17 | },
18 |
19 | parse(momoa, code, options) {
20 | return momoa.parse(code, options);
21 | },
22 |
23 | nodeToRange({loc}) {
24 | if (loc) {
25 | return [
26 | loc.start.offset,
27 | loc.end.offset,
28 | ];
29 | }
30 | },
31 |
32 | getDefaultOptions() {
33 | return {
34 | comments: true,
35 | tokens: true,
36 | ranges: true,
37 | };
38 | },
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/ErrorMessage.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 |
4 | export default class ErrorMessage extends React.Component {
5 | render() {
6 | return this.props.error ?
7 |
8 |
9 |
10 |
11 | {' '}
12 | Error
13 |
14 |
{this.props.error.message}
15 |
16 |
21 |
22 |
23 |
:
24 | null;
25 | }
26 | }
27 |
28 | ErrorMessage.propTypes = {
29 | error: PropTypes.object,
30 | onWantToClose: PropTypes.func,
31 | };
32 |
--------------------------------------------------------------------------------
/lexer/snapshots/lexer__lexer_test__tests__bool.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: lexer/lexer_test.rs
3 | expression: let y=true
4 | ---
5 | [
6 | {
7 | "kind": {
8 | "type": "LET"
9 | },
10 | "span": {
11 | "start": 0,
12 | "end": 3
13 | }
14 | },
15 | {
16 | "kind": {
17 | "type": "IDENTIFIER",
18 | "value": {
19 | "name": "y"
20 | }
21 | },
22 | "span": {
23 | "start": 4,
24 | "end": 5
25 | }
26 | },
27 | {
28 | "kind": {
29 | "type": "ASSIGN"
30 | },
31 | "span": {
32 | "start": 5,
33 | "end": 6
34 | }
35 | },
36 | {
37 | "kind": {
38 | "type": "TRUE"
39 | },
40 | "span": {
41 | "start": 6,
42 | "end": 10
43 | }
44 | },
45 | {
46 | "kind": {
47 | "type": "EOF"
48 | },
49 | "span": {
50 | "start": 10,
51 | "end": 11
52 | }
53 | }
54 | ]
55 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_let.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: let a = 3
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "Let",
11 | "identifier": {
12 | "kind": {
13 | "type": "IDENTIFIER",
14 | "value": {
15 | "name": "a"
16 | }
17 | },
18 | "span": {
19 | "start": 4,
20 | "end": 5
21 | }
22 | },
23 | "expr": {
24 | "type": "Integer",
25 | "raw": 3,
26 | "span": {
27 | "start": 8,
28 | "end": 9
29 | }
30 | },
31 | "span": {
32 | "start": 0,
33 | "end": 9
34 | }
35 | }
36 | ],
37 | "span": {
38 | "start": 0,
39 | "end": 10
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ast-website/scripts/publish-latest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | REMOTE=${1:-"server"}
6 | LATEST_BRANCH=${2:-"website-latest"}
7 | STABLE_BRANCH=${3:-"website-stable"}
8 |
9 | TARGETPATH="../$(basename $(pwd))_$STABLE_BRANCH"
10 | WORKING_DIR=$(pwd)
11 |
12 | trap cleanup EXIT
13 |
14 | function cleanup {
15 | if [ -d $TARGETPATH ]; then
16 | echo "Cleaning up worktree"
17 | git worktree remove -f $TARGETPATH
18 | fi
19 | cd $WORKING_DIR
20 | }
21 |
22 | echo "Creating worktree for $STABLE_BRANCH..."
23 | # Initialize worktree
24 | git worktree add $TARGETPATH $STABLE_BRANCH || exit 1
25 |
26 | cd $TARGETPATH
27 |
28 | echo "Merging $LATEST_BRANCH into $STABLE_BRANCH..."
29 | git merge --squash --strategy-option=theirs $LATEST_BRANCH
30 |
31 | if ! git diff --cached --quiet; then
32 | git commit -m"Publish"
33 | $WORKING_DIR/scripts/deploy.sh $REMOTE $STABLE_BRANCH
34 | else
35 | echo "Nothing to do"
36 | fi
37 |
--------------------------------------------------------------------------------
/lexer/snapshots/lexer__lexer_test__tests__let.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: lexer/lexer_test.rs
3 | expression: let x=5
4 | ---
5 | [
6 | {
7 | "kind": {
8 | "type": "LET"
9 | },
10 | "span": {
11 | "start": 0,
12 | "end": 3
13 | }
14 | },
15 | {
16 | "kind": {
17 | "type": "IDENTIFIER",
18 | "value": {
19 | "name": "x"
20 | }
21 | },
22 | "span": {
23 | "start": 4,
24 | "end": 5
25 | }
26 | },
27 | {
28 | "kind": {
29 | "type": "ASSIGN"
30 | },
31 | "span": {
32 | "start": 5,
33 | "end": 6
34 | }
35 | },
36 | {
37 | "kind": {
38 | "type": "INT",
39 | "value": 5
40 | },
41 | "span": {
42 | "start": 6,
43 | "end": 7
44 | }
45 | },
46 | {
47 | "kind": {
48 | "type": "EOF"
49 | },
50 | "span": {
51 | "start": 7,
52 | "end": 8
53 | }
54 | }
55 | ]
56 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/glsl/codeExample.txt:
--------------------------------------------------------------------------------
1 | // Game Of Life ( https://gl-react-cookbook.surge.sh/gol )
2 | precision highp float;
3 | varying vec2 uv;
4 | uniform float size;
5 | uniform sampler2D t; // the previous world state
6 | void main() {
7 | float prev = step(0.5, texture2D(t, uv).r);
8 | float c = 1.0 / size;
9 | float sum =
10 | step(0.5, texture2D(t, uv + vec2(-1.0, -1.0)*c).r) +
11 | step(0.5, texture2D(t, uv + vec2(-1.0, 0.0)*c).r) +
12 | step(0.5, texture2D(t, uv + vec2(-1.0, 1.0)*c).r) +
13 | step(0.5, texture2D(t, uv + vec2( 0.0, 1.0)*c).r) +
14 | step(0.5, texture2D(t, uv + vec2( 1.0, 1.0)*c).r) +
15 | step(0.5, texture2D(t, uv + vec2( 1.0, 0.0)*c).r) +
16 | step(0.5, texture2D(t, uv + vec2( 1.0, -1.0)*c).r) +
17 | step(0.5, texture2D(t, uv + vec2( 0.0, -1.0)*c).r);
18 | float next = prev==1.0 && sum >= 2.0 && sum <= 3.0 || sum == 3.0 ? 1.0 : 0.0;
19 | gl_FragColor = vec4(vec3(next), 1.0);
20 | }
21 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_hash.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: "{\"a\": 1}"
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "Hash",
11 | "elements": [
12 | [
13 | {
14 | "type": "String",
15 | "raw": "a",
16 | "span": {
17 | "start": 1,
18 | "end": 4
19 | }
20 | },
21 | {
22 | "type": "Integer",
23 | "raw": 1,
24 | "span": {
25 | "start": 6,
26 | "end": 7
27 | }
28 | }
29 | ]
30 | ],
31 | "span": {
32 | "start": 0,
33 | "end": 8
34 | }
35 | }
36 | ],
37 | "span": {
38 | "start": 0,
39 | "end": 9
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lexer/snapshots/lexer__lexer_test__tests__let_with_space.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: lexer/lexer_test.rs
3 | expression: let x = 5
4 | ---
5 | [
6 | {
7 | "kind": {
8 | "type": "LET"
9 | },
10 | "span": {
11 | "start": 0,
12 | "end": 3
13 | }
14 | },
15 | {
16 | "kind": {
17 | "type": "IDENTIFIER",
18 | "value": {
19 | "name": "x"
20 | }
21 | },
22 | "span": {
23 | "start": 4,
24 | "end": 5
25 | }
26 | },
27 | {
28 | "kind": {
29 | "type": "ASSIGN"
30 | },
31 | "span": {
32 | "start": 6,
33 | "end": 7
34 | }
35 | },
36 | {
37 | "kind": {
38 | "type": "INT",
39 | "value": 5
40 | },
41 | "span": {
42 | "start": 8,
43 | "end": 9
44 | }
45 | },
46 | {
47 | "kind": {
48 | "type": "EOF"
49 | },
50 | "span": {
51 | "start": 9,
52 | "end": 10
53 | }
54 | }
55 | ]
56 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/buttons/ForkButton.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 | import cx from '../../utils/classnames.js';
4 |
5 | export default class ForkButton extends React.Component {
6 | render() {
7 | const { canFork, saving, forking, onFork } = this.props;
8 | return (
9 |
25 | );
26 | }
27 | }
28 |
29 | ForkButton.propTypes = {
30 | canFork: PropTypes.bool,
31 | saving: PropTypes.bool,
32 | forking: PropTypes.bool,
33 | onFork: PropTypes.func,
34 | };
35 |
--------------------------------------------------------------------------------
/ast-website/website/fontcustom/README.md:
--------------------------------------------------------------------------------
1 | # Custom Fonts
2 |
3 | There's not a great way to customize font-awesome at the moment
4 | (see: https://github.com/FortAwesome/Font-Awesome/wiki/Customize-Font-Awesome).
5 |
6 | So we are using [fontcustom](https://github.com/FontCustom/fontcustom) to add
7 | custom logos / fonts to the app.
8 |
9 | ## Build Instructions
10 |
11 | - install fontcustom: https://github.com/FontCustom/fontcustom#installation
12 | - add the svgs you want to convert to the `./fontcustom/input-svg/` directory
13 | - in the root of the astexplorer project, run:
14 | ```bash
15 | yarn run fontcustom
16 | ```
17 | - you can then confirm things worked by running
18 | `open ./fontcustom/fontcustom-preview.html`
19 | - now you can reference your icons in a very similar manner to font-awesome,
20 | for example:
21 | - font-awesome: ``
22 | - fontcustom: ``
23 | (if you added `./fontcustom/input-svg/myfoo.svg`)
24 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/thrift/thrift-parser.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from '@creditkarma/thrift-parser/package.json';
3 |
4 | const ID = 'ck-thrift-parser';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: 'https://github.com/creditkarma/thrift-parser',
13 | locationProps: new Set(['location']),
14 |
15 | loadParser(callback) {
16 | require(['@creditkarma/thrift-parser'], callback);
17 | },
18 |
19 | parse({parse}, code) {
20 | return parse(code);
21 | },
22 |
23 | getNodeName(node) {
24 | return node.type;
25 | },
26 |
27 | nodeToRange({ loc }) {
28 | if (loc !== null && loc !== undefined) {
29 | return [loc.start.index, loc.end.index];
30 | }
31 | },
32 |
33 | opensByDefault(node, key) {
34 | return node === 'ThriftDocument' || key === 'body';
35 | },
36 | };
37 |
--------------------------------------------------------------------------------
/.github/workflows/doc-publish.yml:
--------------------------------------------------------------------------------
1 | name: Build and Deploy
2 | on:
3 | push:
4 | branches:
5 | - main
6 | permissions:
7 | contents: write
8 |
9 | jobs:
10 | build-and-deploy:
11 | concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession.
12 | runs-on: ubuntu-latest
13 | # container: gengjiawen/node-build:latest
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v3
17 |
18 | - name: Install and Build
19 | run: |
20 | curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
21 | npm i -g pnpm@8
22 | cargo build
23 | cd wasm && wasm-pack build --release --scope=gengjiawen
24 | pnpm i
25 | cd $GITHUB_WORKSPACE/packages/playground && pnpm build
26 |
27 | - name: Deploy 🚀
28 | uses: JamesIves/github-pages-deploy-action@v4
29 | with:
30 | folder: packages/playground/dist
31 |
--------------------------------------------------------------------------------
/lexer/snapshots/lexer__lexer_test__tests__comments_then_blank_line.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: lexer/lexer_test.rs
3 | expression: "// comment\n\nlet x = 5"
4 | ---
5 | [
6 | {
7 | "kind": {
8 | "type": "LET"
9 | },
10 | "span": {
11 | "start": 12,
12 | "end": 15
13 | }
14 | },
15 | {
16 | "kind": {
17 | "type": "IDENTIFIER",
18 | "value": {
19 | "name": "x"
20 | }
21 | },
22 | "span": {
23 | "start": 16,
24 | "end": 17
25 | }
26 | },
27 | {
28 | "kind": {
29 | "type": "ASSIGN"
30 | },
31 | "span": {
32 | "start": 18,
33 | "end": 19
34 | }
35 | },
36 | {
37 | "kind": {
38 | "type": "INT",
39 | "value": 5
40 | },
41 | "span": {
42 | "start": 20,
43 | "end": 21
44 | }
45 | },
46 | {
47 | "kind": {
48 | "type": "EOF"
49 | },
50 | "span": {
51 | "start": 21,
52 | "end": 22
53 | }
54 | }
55 | ]
56 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/prettier/index.js:
--------------------------------------------------------------------------------
1 | import compileModule from '../../../utils/compileModule';
2 | import pkg from 'prettier/package.json';
3 |
4 | const ID = 'prettier';
5 | const name = 'prettier';
6 |
7 | export default {
8 | id: ID,
9 | displayName: name,
10 | version: pkg.version,
11 | homepage: pkg.homepage,
12 |
13 | defaultParserID: 'babylon7',
14 |
15 | loadTransformer(callback) {
16 | require(
17 | ['../../../transpilers/babel', 'prettier/standalone', 'prettier/parser-babel'],
18 | (transpile, prettier, babel) => callback({ transpile: transpile.default, prettier, babel }),
19 | );
20 | },
21 |
22 | transform({ transpile, prettier, babel }, transformCode, code) {
23 | transformCode = transpile(transformCode);
24 | const options = compileModule(transformCode);
25 | return prettier.format(
26 | code,
27 | Object.assign({plugins: [babel]}, options.default || options),
28 | );
29 | },
30 | };
31 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/babel/index.js:
--------------------------------------------------------------------------------
1 | import compileModule from '../../../utils/compileModule';
2 | import pkg from 'babel5/package.json';
3 |
4 | const ID = 'babel';
5 |
6 | export default {
7 | id: ID,
8 | displayName: ID,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 | showInMenu: false,
12 |
13 | defaultParserID: 'babylon',
14 |
15 | loadTransformer(callback) {
16 | require(
17 | ['../../../transpilers/babel', 'babel5'],
18 | (transpile, babel) => callback({ transpile: transpile.default, babel: babel }),
19 | );
20 | },
21 |
22 | transform({ transpile, babel }, transformCode, code) {
23 | transformCode = transpile(transformCode);
24 | let transform = compileModule( // eslint-disable-line no-shadow
25 | transformCode,
26 | );
27 |
28 | return babel.transform(code, {
29 | whitelist: [],
30 | plugins: [transform.default || transform],
31 | sourceMaps: true,
32 | });
33 | },
34 | };
35 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/babel-eslint9.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from './utils/defaultESTreeParserInterface';
2 | import pkg from 'babel-eslint9/package.json';
3 |
4 | const ID = 'babel-eslint9';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['loc', 'start', 'end', 'range']),
14 |
15 | loadParser(callback) {
16 | require(['babel-eslint9'], callback);
17 | },
18 |
19 | parse(parser, code) {
20 | const opts = {
21 | sourceType: 'module',
22 | };
23 |
24 | const ast = parser.parseNoPatch(code, opts);
25 | delete ast.tokens;
26 | return ast;
27 | },
28 |
29 | nodeToRange(node) {
30 | if (typeof node.start !== 'undefined') {
31 | return [node.start, node.end];
32 | }
33 | },
34 |
35 | _ignoredProperties: new Set([
36 | '_paths',
37 | '_babelType',
38 | '__clone',
39 | ]),
40 | };
41 |
--------------------------------------------------------------------------------
/ast-website/website/src/components/SettingsDrawer.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 |
4 | export default class SettingsDrawer extends React.Component {
5 | constructor(props) {
6 | super(props);
7 | this._expand = this._expand.bind(this);
8 | this._collapse = this._collapse.bind(this);
9 | }
10 |
11 | _expand() {
12 | this.props.onWantToExpand();
13 | }
14 |
15 | _collapse() {
16 | this.props.onWantToCollapse();
17 | }
18 |
19 | render() {
20 | return (
21 | this.props.isOpen ?
22 |
23 |
Settings
24 |
25 |
26 | :
27 |
28 | );
29 | }
30 | }
31 |
32 | SettingsDrawer.propTypes = {
33 | onWantToExpand: PropTypes.func,
34 | onWantToCollapse: PropTypes.func,
35 | isOpen: PropTypes.bool,
36 | };
37 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/babel-eslint.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from './utils/defaultESTreeParserInterface';
2 | import pkg from 'babel-eslint/package.json';
3 |
4 | const ID = 'babel-eslint';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['loc', 'start', 'end', 'range']),
14 | showInMenu: false,
15 |
16 | loadParser(callback) {
17 | require(['babel-eslint'], callback);
18 | },
19 |
20 | parse(parser, code) {
21 | const opts = {
22 | sourceType: 'module',
23 | };
24 |
25 | const ast = parser.parseNoPatch(code, opts);
26 | delete ast.tokens;
27 | return ast;
28 | },
29 |
30 | nodeToRange(node) {
31 | if (typeof node.start !== 'undefined') {
32 | return [node.start, node.end];
33 | }
34 | },
35 |
36 | _ignoredProperties: new Set([
37 | '_paths',
38 | '_babelType',
39 | '__clone',
40 | ]),
41 | };
42 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/babel-eslint8.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from './utils/defaultESTreeParserInterface';
2 | import pkg from 'babel-eslint8/package.json';
3 |
4 | const ID = 'babel-eslint8';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['loc', 'start', 'end', 'range']),
14 | showInMenu: false,
15 |
16 | loadParser(callback) {
17 | require(['babel-eslint8'], callback);
18 | },
19 |
20 | parse(parser, code) {
21 | const opts = {
22 | sourceType: 'module',
23 | };
24 |
25 | const ast = parser.parseNoPatch(code, opts);
26 | delete ast.tokens;
27 | return ast;
28 | },
29 |
30 | nodeToRange(node) {
31 | if (typeof node.start !== 'undefined') {
32 | return [node.start, node.end];
33 | }
34 | },
35 |
36 | _ignoredProperties: new Set([
37 | '_paths',
38 | '_babelType',
39 | '__clone',
40 | ]),
41 | };
42 |
--------------------------------------------------------------------------------
/packages/playground/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "monkey-playground",
3 | "private": true,
4 | "version": "0.0.1",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "tsc && vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@chakra-ui/react": "^2.2.4",
12 | "@emotion/react": "^11",
13 | "@emotion/styled": "^11",
14 | "@gengjiawen/monkey-wasm": "workspace:^0.10.1",
15 | "@replit/codemirror-vim": "^6.0.1",
16 | "@uiw/react-codemirror": "^4.11.4",
17 | "framer-motion": "^6",
18 | "lodash.debounce": "^4.0.8",
19 | "react": "18.2.0",
20 | "react-dom": "18.2.0"
21 | },
22 | "devDependencies": {
23 | "@types/lodash.debounce": "^4.0.7",
24 | "@types/react": "^18.0.15",
25 | "@types/react-dom": "^18.0.6",
26 | "@vitejs/plugin-react": "^2.0.0",
27 | "rollup-plugin-visualizer": "^5.7.1",
28 | "typescript": "^4.7.4",
29 | "vite": "^3.0.4",
30 | "vite-plugin-top-level-await": "^1.1.1",
31 | "vite-plugin-wasm": "^2.1.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ast-website/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Browser (please complete the following information):**
24 | - OS: [e.g. iOS]
25 | - Browser [e.g. chrome, safari]
26 | - Version [e.g. 22]
27 |
28 | **astexplorer settings:**
29 | - Selected parser: [e.g. acorn]
30 | - Selected transformer (if applicable): [e.g. jscodeshift]
31 | - Contents of the local storage key `explorerSettingsV1` (code can be removed if you don't want it to be public)
32 |
33 | **Additional context**
34 | Add any other context about the problem here.
35 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/mathjs/mathjs.js:
--------------------------------------------------------------------------------
1 | import pkg from 'mathjs/package.json';
2 |
3 | import defaultParserInterface from '../utils/defaultParserInterface'
4 |
5 | const ID = 'mathjs'
6 |
7 | export default {
8 | ...defaultParserInterface,
9 |
10 | id: ID,
11 | displayName: ID,
12 | version: pkg.version,
13 | homepage: 'https://mathjs.org/',
14 | locationProps: new Set(['span']),
15 |
16 | defaultParserID: 'mathjs',
17 |
18 | async loadParser(callback) {
19 | require(['mathjs'], callback);
20 | },
21 |
22 | parse(parser, code) {
23 | try {
24 | return parser.parse(code)
25 | } catch (message) {
26 | // AST Explorer expects the thrown error to be an object, not a string.
27 | throw new SyntaxError(message);
28 | }
29 | },
30 |
31 | getNodeName(node) {
32 | return node.type
33 | },
34 |
35 | // TODO once this feature is added to mathjs
36 | // nodeToRange(node) {
37 | // },
38 |
39 | opensByDefault(node) {
40 | return node.type === 'BlockNode'
41 | },
42 | }
43 |
--------------------------------------------------------------------------------
/examples/hello.monkey:
--------------------------------------------------------------------------------
1 | // Integers & arithmetic expressions...
2 | let version = 1 + (50 / 2) - (8 * 3);
3 |
4 | // ... and strings
5 | let name = "The Monkey programming language";
6 |
7 | // ... booleans
8 | let isMonkeyFastNow = true;
9 |
10 | // ... arrays & hash maps
11 | let people = [{"name": "Anna", "age": 24}, {"name": "Bob", "age": 99}];
12 |
13 | // User-defined functions...
14 | let getName = fn(person) { person["name"]; };
15 | getName(people[0]); // => "Anna"
16 | getName(people[1]); // => "Bob"
17 |
18 | // and built-in functions
19 | puts(len(people)) // prints: 2
20 |
21 | let fibonacci = fn(x) {
22 | if (x == 0) {
23 | 0
24 | } else {
25 | if (x == 1) {
26 | return 1;
27 | } else {
28 | fibonacci(x - 1) + fibonacci(x - 2);
29 | }
30 | }
31 | };
32 |
33 | // `newAdder` returns a closure that makes use of the free variables `a` and `b`:
34 | let newAdder = fn(a, b) {
35 | fn(c) { a + b + c };
36 | };
37 | // This constructs a new `adder` function:
38 | let adder = newAdder(1, 2);
39 |
40 | adder(8); // => 11
--------------------------------------------------------------------------------
/parser/precedences.rs:
--------------------------------------------------------------------------------
1 | use lexer::token::TokenKind;
2 |
3 | #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
4 | pub enum Precedence {
5 | LOWEST,
6 | EQUALS, // ==
7 | LessGreater, // > or <
8 | SUM, // + or =
9 | PRODUCT, // * or /
10 | PREFIX, // -X or !X
11 | CALL, // myFunction(x)
12 | INDEX, // array[index]
13 | }
14 |
15 | pub fn get_token_precedence(token: &TokenKind) -> Precedence {
16 | match token {
17 | TokenKind::EQ => Precedence::EQUALS,
18 | TokenKind::NotEq => Precedence::EQUALS,
19 | TokenKind::LT => Precedence::LessGreater,
20 | TokenKind::GT => Precedence::LessGreater,
21 | TokenKind::PLUS => Precedence::SUM,
22 | TokenKind::MINUS => Precedence::SUM,
23 | TokenKind::ASTERISK => Precedence::PRODUCT,
24 | TokenKind::SLASH => Precedence::PRODUCT,
25 | TokenKind::LPAREN => Precedence::CALL,
26 | TokenKind::LBRACKET => Precedence::INDEX,
27 | _ => Precedence::LOWEST,
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/monkey/monkey.js:
--------------------------------------------------------------------------------
1 | import pkg from '@gengjiawen/monkey-wasm/package.json';
2 |
3 | import defaultParserInterface from '../utils/defaultParserInterface'
4 |
5 | const ID = 'monkey'
6 |
7 | export default {
8 | ...defaultParserInterface,
9 |
10 | id: ID,
11 | displayName: ID,
12 | version: pkg.version,
13 | homepage: 'https://monkeylang.org/',
14 | locationProps: new Set(['span']),
15 |
16 | async loadParser(callback) {
17 | require(['@gengjiawen/monkey-wasm/monkey_wasm.js'], callback);
18 | },
19 |
20 | parse(parser, code) {
21 | try {
22 | return JSON.parse(parser.parse(code));
23 | } catch (message) {
24 | // AST Explorer expects the thrown error to be an object, not a string.
25 | throw new SyntaxError(message);
26 | }
27 | },
28 |
29 | getNodeName(node) {
30 | return node.type
31 | },
32 |
33 | nodeToRange(node) {
34 | if (node && node.span && typeof node.span.start === 'number') {
35 | return [node.span.start, node.span.end];
36 | }
37 | },
38 | }
39 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/python/python.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'filbert/package.json';
3 |
4 | const ID = 'python';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage || 'https://github.com/differentmatt/filbert',
13 | locationProps: new Set(['range', 'loc', 'start', 'end']),
14 |
15 | loadParser(callback) {
16 | require(['filbert'], (parser) => {
17 | callback({ parser });
18 | });
19 | },
20 |
21 | parse({ parser }, code) {
22 | return parser.parse(code, {
23 | locations: true,
24 | ranges: true,
25 | });
26 | },
27 |
28 | opensByDefault(node, key) {
29 | switch (key) {
30 | case 'block':
31 | case 'nodes':
32 | return true;
33 | }
34 | },
35 |
36 | nodeToRange(node) {
37 | const { range } = node;
38 | if (typeof range === 'object') {
39 | return range;
40 | }
41 | },
42 |
43 | };
44 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/html/transformers/posthtml/index.js:
--------------------------------------------------------------------------------
1 | import compileModule from '../../../utils/compileModule';
2 | import pkg from 'posthtml/package.json';
3 |
4 | const ID = 'posthtml';
5 |
6 | export default {
7 | id: ID,
8 | displayName: ID,
9 | version: pkg.version,
10 | homepage: pkg.homepage || 'https://github.com/posthtml/posthtml',
11 |
12 | defaultParserID: 'posthtml-parser',
13 |
14 | loadTransformer(callback) {
15 | require(['../../../transpilers/babel', 'posthtml'], (transpile, posthtml) =>
16 | callback({ transpile: transpile.default, posthtml }));
17 | },
18 |
19 | transform({ transpile, posthtml }, transformCode, code) {
20 | // transpile with babel for es6+ support
21 | transformCode = transpile(transformCode);
22 | // compile to turn from string into a module
23 | let transform = compileModule(
24 | // eslint-disable-line no-shadow
25 | transformCode,
26 | );
27 | return posthtml()
28 | .use(transform.default || transform)
29 | .process(code, { sync: true }).html;
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/graphql/graphql-js.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'graphql/package.json';
3 |
4 | const ID = 'graphql-js';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['loc']),
14 | typeProps: new Set(['kind']),
15 |
16 | loadParser(callback) {
17 | require(['graphql/language'], ({ parse }) => {
18 | callback({ parse });
19 | });
20 | },
21 |
22 | parse({ parse }, code, options) {
23 | return parse(code, options);
24 | },
25 |
26 | nodeToRange(node) {
27 | if (node.loc) {
28 | return [node.loc.start, node.loc.end];
29 | }
30 | },
31 |
32 | getNodeName(node) {
33 | return node.kind;
34 | },
35 |
36 | opensByDefault(node, key) {
37 | return key === 'definitions';
38 | },
39 |
40 | getDefaultOptions() {
41 | return {
42 | noLocation: false,
43 | noSource: false,
44 | };
45 | },
46 | };
47 |
--------------------------------------------------------------------------------
/compiler/README.md:
--------------------------------------------------------------------------------
1 | # monkey-rust
2 | 
3 | [](https://gitpod.io/#https://github.com/gengjiawen/monkey_rust)
4 |
5 | This is a compiler for the Monkey programming language written in Rust
6 |
7 | 
8 |
9 | ## What’s Monkey?
10 |
11 | Monkey has a C-like syntax, supports **variable bindings**, **prefix** and **infix operators**, has **first-class** and **higher-order functions**, can handle **closures** with ease and has **integers**, **booleans**, **arrays** and **hashes** built-in.
12 |
13 | Official site is: https://monkeylang.org/. It's has various implementation languages :).
14 |
15 | There is a book about learning how to make an interpreter: [Writing An Interpreter In Go](https://interpreterbook.com/#the-monkey-programming-language). This is where the Monkey programming language come from.
16 |
--------------------------------------------------------------------------------
/object/README.md:
--------------------------------------------------------------------------------
1 | # monkey-rust
2 | 
3 | [](https://gitpod.io/#https://github.com/gengjiawen/monkey_rust)
4 |
5 | This is a object for the Monkey programming language written in Rust
6 |
7 | 
8 |
9 | ## What’s Monkey?
10 |
11 | Monkey has a C-like syntax, supports **variable bindings**, **prefix** and **infix operators**, has **first-class** and **higher-order functions**, can handle **closures** with ease and has **integers**, **booleans**, **arrays** and **hashes** built-in.
12 |
13 | Official site is: https://monkeylang.org/. It's has various implementation languages :).
14 |
15 | There is a book about learning how to make an interpreter: [Writing An Interpreter In Go](https://interpreterbook.com/#the-monkey-programming-language). This is where the Monkey programming language come from.
16 |
--------------------------------------------------------------------------------
/parser/README.md:
--------------------------------------------------------------------------------
1 | # monkey-rust
2 | 
3 | [](https://gitpod.io/#https://github.com/gengjiawen/monkey_rust)
4 |
5 | This is a parser for the Monkey programming language written in Rust
6 |
7 | 
8 |
9 | ## What’s Monkey?
10 |
11 | Monkey has a C-like syntax, supports **variable bindings**, **prefix** and **infix operators**, has **first-class** and **higher-order functions**, can handle **closures** with ease and has **integers**, **booleans**, **arrays** and **hashes** built-in.
12 |
13 | Official site is: https://monkeylang.org/. It's has various implementation languages :).
14 |
15 | There is a book about learning how to make an interpreter: [Writing An Interpreter In Go](https://interpreterbook.com/#the-monkey-programming-language). This is where the Monkey programming language come from.
16 |
--------------------------------------------------------------------------------
/parser/snapshots/parser__ast_tree_test__tests__test_func_call.snap:
--------------------------------------------------------------------------------
1 | ---
2 | source: parser/ast_tree_test.rs
3 | expression: "add(1, 2)"
4 | ---
5 | {
6 | "Program": {
7 | "type": "Program",
8 | "body": [
9 | {
10 | "type": "FunctionCall",
11 | "callee": {
12 | "type": "IDENTIFIER",
13 | "name": "add",
14 | "span": {
15 | "start": 0,
16 | "end": 3
17 | }
18 | },
19 | "arguments": [
20 | {
21 | "type": "Integer",
22 | "raw": 1,
23 | "span": {
24 | "start": 4,
25 | "end": 5
26 | }
27 | },
28 | {
29 | "type": "Integer",
30 | "raw": 2,
31 | "span": {
32 | "start": 7,
33 | "end": 8
34 | }
35 | }
36 | ],
37 | "span": {
38 | "start": 0,
39 | "end": 9
40 | }
41 | }
42 | ],
43 | "span": {
44 | "start": 0,
45 | "end": 10
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint1/index.js:
--------------------------------------------------------------------------------
1 | import pkg from 'eslint1/package.json';
2 |
3 | const ID = 'eslint-v1';
4 | const name = 'ESLint v1'
5 |
6 | export default {
7 | id: ID,
8 | displayName: name,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 | showInMenu: false,
12 |
13 | defaultParserID: 'acorn-to-esprima',
14 |
15 | loadTransformer(callback) {
16 | require(
17 | [
18 | // Explicitly require just the stuff we care about to avoid loading
19 | // RuleTester and CLIEngine, which are unnecessary and bloat out the
20 | // package size.
21 | 'eslint1/lib/eslint',
22 | 'eslint1/lib/util/source-code',
23 | 'eslint1/lib/rules',
24 | '../../utils/eslintUtils',
25 | ],
26 | (eslint, sourceCode, rules, utils) => callback({eslint, sourceCode, rules, utils}),
27 | );
28 | },
29 |
30 | transform({ eslint, sourceCode, rules, utils }, transformCode, code) {
31 | utils.defineRule(rules, transformCode);
32 | return utils.runRule(code, eslint, sourceCode);
33 | },
34 | };
35 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint2/index.js:
--------------------------------------------------------------------------------
1 | import pkg from 'eslint2/package.json';
2 |
3 | const ID = 'eslint-v2';
4 | const name = 'ESLint v2'
5 |
6 | export default {
7 | id: ID,
8 | displayName: name,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 | showInMenu: false,
12 |
13 | defaultParserID: 'babel-eslint',
14 |
15 | loadTransformer(callback) {
16 | require(
17 | [
18 | // Explicitly require just the stuff we care about to avoid loading
19 | // RuleTester and CLIEngine, which are unnecessary and bloat out the
20 | // package size.
21 | 'eslint2/lib/eslint',
22 | 'eslint2/lib/util/source-code',
23 | 'eslint2/lib/rules',
24 | '../../utils/eslintUtils',
25 | ],
26 | (eslint, sourceCode, rules, utils) => callback({eslint, sourceCode, rules, utils}),
27 | );
28 | },
29 |
30 | transform({ eslint, rules, sourceCode, utils }, transformCode, code) {
31 | utils.defineRule(rules, transformCode);
32 | return utils.runRule(code, eslint, sourceCode);
33 | },
34 | };
35 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/js/transformers/eslint3/index.js:
--------------------------------------------------------------------------------
1 | import pkg from 'eslint3/package.json';
2 |
3 | const ID = 'eslint-v3';
4 | const name = 'ESLint v3'
5 |
6 | export default {
7 | id: ID,
8 | displayName: name,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 | showInMenu: false,
12 |
13 | defaultParserID: 'babel-eslint',
14 |
15 | loadTransformer(callback) {
16 | require(
17 | [
18 | // Explicitly require just the stuff we care about to avoid loading
19 | // RuleTester and CLIEngine, which are unnecessary and bloat out the
20 | // package size.
21 | 'eslint3/lib/eslint',
22 | 'eslint3/lib/util/source-code',
23 | 'eslint3/lib/rules',
24 | '../../utils/eslintUtils',
25 | ],
26 | (eslint, sourceCode, rules, utils) => callback({eslint, sourceCode, rules, utils}),
27 | );
28 | },
29 |
30 | transform({ eslint, rules, sourceCode, utils }, transformCode, code) {
31 | utils.defineRule(rules, transformCode);
32 | return utils.runRule(code, eslint, sourceCode);
33 | },
34 | };
35 |
--------------------------------------------------------------------------------
/interpreter/README.md:
--------------------------------------------------------------------------------
1 | # monkey-rust
2 | 
3 | [](https://gitpod.io/#https://github.com/gengjiawen/monkey_rust)
4 |
5 | This is a interpreter for the Monkey programming language written in Rust
6 |
7 | 
8 |
9 | ## What’s Monkey?
10 |
11 | Monkey has a C-like syntax, supports **variable bindings**, **prefix** and **infix operators**, has **first-class** and **higher-order functions**, can handle **closures** with ease and has **integers**, **booleans**, **arrays** and **hashes** built-in.
12 |
13 | Official site is: https://monkeylang.org/. It's has various implementation languages :).
14 |
15 | There is a book about learning how to make an interpreter: [Writing An Interpreter In Go](https://interpreterbook.com/#the-monkey-programming-language). This is where the Monkey programming language come from.
16 |
--------------------------------------------------------------------------------
/lexer/README.md:
--------------------------------------------------------------------------------
1 | # monkey-rust
2 | 
3 | [](https://gitpod.io/#https://github.com/gengjiawen/monkey_rust)
4 |
5 | This is lexer for the Monkey programming language written in Rust
6 |
7 | 
8 |
9 | ## What’s Monkey?
10 |
11 | Monkey has a C-like syntax, supports **variable bindings**, **prefix** and **infix operators**, has **first-class** and **higher-order functions**, can handle **closures** with ease and has **integers**, **booleans**, **arrays** and **hashes** built-in.
12 |
13 | Official site is: https://monkeylang.org/. It's has various implementation languages :).
14 |
15 | There is a book about learning how to make an interpreter: [Writing An Interpreter In Go](https://interpreterbook.com/#the-monkey-programming-language). This is where the Monkey programming language come from.
16 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/html/svelte.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'svelte/package.json';
3 |
4 | const ID = 'svelte';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage,
13 | locationProps: new Set(['start', 'end']),
14 | typeProps: new Set(['tag']),
15 |
16 | loadParser(callback) {
17 | require(['svelte/compiler'], callback);
18 | },
19 |
20 | parse(parser, code, options) {
21 | return parser.compile(code, options).ast;
22 | },
23 |
24 | nodeToRange(node) {
25 | if (node.type || node.name) {
26 | return [node.start, node.end];
27 | }
28 | },
29 |
30 | opensByDefault(node, key) {
31 | return key === 'children';
32 | },
33 |
34 | getNodeName(node) {
35 | return node.tag;
36 | },
37 |
38 | getDefaultOptions() {
39 | return {
40 | preserveWhitespace: true,
41 | preserveComments: true,
42 | };
43 | },
44 | _ignoredProperties: new Set(['parent']),
45 | };
46 |
--------------------------------------------------------------------------------
/wasm/README.md:
--------------------------------------------------------------------------------
1 | 
2 | [](https://gitpod.io/#https://github.com/gengjiawen/monkey_rust)
3 |
4 | This lib designed for compiling monkey-parser into WebAssembly and
5 | publishing the resulting package to NPM.
6 |
7 | 
8 |
9 | ## What’s Monkey?
10 |
11 | Monkey has a C-like syntax, supports **variable bindings**, **prefix** and **infix operators**, has **first-class** and **higher-order functions**, can handle **closures** with ease and has **integers**, **booleans**, **arrays** and **hashes** built-in.
12 |
13 | Official site is: https://monkeylang.org/. It's has various implementation languages :).
14 |
15 | There is a book about learning how to make an interpreter: [Writing An Interpreter In Go](https://interpreterbook.com/#the-monkey-programming-language). This is where the Monkey programming language come from.
16 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/wat/wat-parser.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from '@webassemblyjs/wast-parser/package.json';
3 |
4 | const ID = 'wat-parser';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: 'https://webassembly.js.org/',
13 |
14 | locationProps: new Set(['loc']),
15 |
16 | getOffset({ line, column }) {
17 | return this.lineOffsets[line - 1] + column;
18 | },
19 |
20 | nodeToRange({ loc }) {
21 | if (!loc) return;
22 | return [loc.start, loc.end].map(pos => this.getOffset(pos));
23 | },
24 |
25 | loadParser(callback) {
26 | require(['@webassemblyjs/wast-parser'], function(parser) {
27 | callback(parser);
28 | });
29 | },
30 |
31 | parse({ parse }, code) {
32 | this.lineOffsets = [];
33 | let index = 0;
34 | do {
35 | this.lineOffsets.push(index);
36 | } while (index = code.indexOf('\n', index) + 1); // eslint-disable-line no-cond-assign
37 | return parse(code);
38 | },
39 | };
40 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/webidl/webidl2.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'webidl2/package.json';
3 |
4 | const ID = 'webidl2';
5 |
6 | export default {
7 | ...defaultParserInterface,
8 |
9 | id: ID,
10 | displayName: ID,
11 | version: pkg.version,
12 | homepage: pkg.homepage || 'https://github.com/w3c/webidl2.js',
13 | typeProps: new Set(['name', 'type', 'idlType', 'escapedName']),
14 |
15 | getNodeName(node) {
16 | if (node.name) {
17 | return node.name + (node.optional ? '?' : '');
18 | } else if (node.type) {
19 | return node.type;
20 | } else if (node.idlType) {
21 | return node.idlType.idlType || node.idlType;
22 | }
23 | },
24 |
25 | loadParser(callback) {
26 | require(['webidl2'], callback);
27 | },
28 |
29 | parse({ parse }, code, options) {
30 | return parse(code, options);
31 | },
32 |
33 | opensByDefault(node, key) {
34 | return key === 'members';
35 | },
36 |
37 | getDefaultOptions() {
38 | return {
39 | concrete: false,
40 | };
41 | },
42 | };
43 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/yaml/yaml-ast-parser.js:
--------------------------------------------------------------------------------
1 | import defaultParserInterface from '../utils/defaultParserInterface';
2 | import pkg from 'yaml-ast-parser/package.json';
3 |
4 | const ID = 'yaml-ast-parser';
5 | let Kind = null;
6 |
7 | export default {
8 | ...defaultParserInterface,
9 |
10 | id: ID,
11 | displayName: ID,
12 | version: pkg.version,
13 | homepage: pkg.homepage || 'https://www.npmjs.com/package/yaml-ast-parser',
14 |
15 | _ignoredProperties: new Set(['parent', 'errors']),
16 | locationProps: new Set(['startPosition', 'endPosition']),
17 | typeProps: new Set(['kind']),
18 |
19 | nodeToRange(node) {
20 | if (typeof node.startPosition === 'number') {
21 | return [node.startPosition, node.endPosition];
22 | }
23 | },
24 |
25 | getNodeName(node) {
26 | return Kind[node.kind];
27 | },
28 |
29 | loadParser(callback) {
30 | require(['yaml-ast-parser'], function(yamlAstParser) {
31 | Kind = yamlAstParser.Kind;
32 | callback(yamlAstParser);
33 | });
34 | },
35 |
36 | parse({ load }, code) {
37 | return load(code);
38 | },
39 | };
40 |
--------------------------------------------------------------------------------
/packages/playground/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ast-website/website/src/parsers/css/transformers/postcss/index.js:
--------------------------------------------------------------------------------
1 | import compileModule from '../../../utils/compileModule';
2 | import pkg from 'postcss/package.json';
3 |
4 | const ID = 'postcss';
5 |
6 | export default {
7 | id: ID,
8 | displayName: ID,
9 | version: pkg.version,
10 | homepage: pkg.homepage,
11 |
12 | defaultParserID: 'postcss',
13 |
14 | loadTransformer(callback) {
15 | require(['../../../transpilers/babel', 'postcss'], (transpile, postcss) => {
16 | callback({ transpile: transpile.default, postcss });
17 | });
18 | },
19 |
20 | transform({ transpile, postcss }, transformCode, code) {
21 | transformCode = transpile( transformCode);
22 | let transform = compileModule( // eslint-disable-line no-shadow
23 | transformCode,
24 | {
25 | require(name) {
26 | switch (name) {
27 | case 'postcss': return postcss;
28 | default: throw new Error(`Cannot find module '${name}'`);
29 | }
30 | },
31 | },
32 | );
33 | return postcss([ (transform.default || transform)() ]).process(code).css;
34 | },
35 | };
36 |
--------------------------------------------------------------------------------
/object/environment.rs:
--------------------------------------------------------------------------------
1 | use crate::Object;
2 | use std::cell::RefCell;
3 | use std::collections::HashMap;
4 | use std::rc::Rc;
5 |
6 | pub type Env = Rc>;
7 |
8 | #[derive(Debug, Default, Eq, Clone, PartialEq)]
9 | pub struct Environment {
10 | store: HashMap>,
11 | outer: Option,
12 | }
13 |
14 | impl Environment {
15 | pub fn new_enclosed_environment(outer: &Env) -> Self {
16 | let mut env: Environment = Default::default();
17 | env.outer = Some(Rc::clone(outer));
18 | return env;
19 | }
20 |
21 | pub fn get(&self, name: &str) -> Option> {
22 | match self.store.get(name) {
23 | Some(obj) => Some(Rc::clone(obj)),
24 | None => {
25 | if let Some(outer) = &self.outer {
26 | return outer.borrow().get(name);
27 | } else {
28 | return None;
29 | }
30 | }
31 | }
32 | }
33 |
34 | pub fn set(&mut self, name: String, val: Rc