Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite the parser #11

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
ceb4644
Breaking: WIP
iwatakeshi Aug 8, 2018
383b47f
Update: WIP
iwatakeshi Aug 10, 2018
b4feda0
Update: WIP
iwatakeshi Aug 10, 2018
377a7b0
Update: WIP
iwatakeshi Aug 10, 2018
f88465b
Update: WIP
iwatakeshi Aug 13, 2018
be622e3
Update: WIP
iwatakeshi Aug 16, 2018
e5177d7
Update: WIP
iwatakeshi Aug 17, 2018
d66758f
Update: WIP
iwatakeshi Aug 18, 2018
2bdfed8
Update: WIP
iwatakeshi Aug 18, 2018
98561dc
Update: WIP
iwatakeshi Aug 20, 2018
0e7385b
Update: WIP
iwatakeshi Aug 20, 2018
decc62a
Update: WIP
iwatakeshi Aug 21, 2018
d2f997b
Update: WIP
iwatakeshi Aug 21, 2018
68908b0
Update: WIP
iwatakeshi Aug 22, 2018
287d937
Update: Complete initial TypeScript parser
iwatakeshi Aug 23, 2018
753c5e8
Update: Complete JavaScript parser
iwatakeshi Aug 23, 2018
7040307
Fix: Endless recursive call
iwatakeshi Aug 23, 2018
74e513d
Update: Replace return type
iwatakeshi Aug 23, 2018
7739bab
Update: Refactor and Doc (WIP)
iwatakeshi Aug 24, 2018
8d14cca
Update: Build and WIP
iwatakeshi Aug 24, 2018
4b631d0
Update: Refactor and finish README
iwatakeshi Aug 24, 2018
d7b7725
Update: README
iwatakeshi Aug 24, 2018
f44e8fe
Doc: Change title
iwatakeshi Aug 24, 2018
ade842b
Doc: Add note
iwatakeshi Aug 24, 2018
2a61519
Build: Remove test for now
iwatakeshi Aug 24, 2018
2510887
Merge branch 'master' of https://github.com/iwatakeshi/mr-doc-parser
iwatakeshi Aug 24, 2018
0d563c1
Update: Remove statement_block from method_definition
iwatakeshi Aug 24, 2018
0120391
Update: Logger is now available across all visitors.
iwatakeshi Aug 24, 2018
558648d
Update: Only options are needed for the ParserLogger
iwatakeshi Aug 25, 2018
51734c4
Upgrade: Package.json
iwatakeshi Aug 27, 2018
55de900
Update: Source is now publicly available
iwatakeshi Aug 27, 2018
64dfeeb
Update: Add language getter to abstract parser
iwatakeshi Aug 27, 2018
c66d3c7
Chore: Build files
iwatakeshi Aug 27, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .eslintrc

This file was deleted.

2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ language: node_js
node_js:
- 8

before_install: npm i -g gulp
# before_install: npm i -g gulp
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/main.js"
"program": "${workspaceFolder}/build/index.js"
}
]
}
12 changes: 0 additions & 12 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,12 +0,0 @@
{
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/.DS_Store": true,
"**/*.js.map": true,
"**/*.js": {
"when": "$(basename).ts"
}
}
}
92 changes: 81 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,97 @@
# Parser
# mr-doc-parser

[![Build Status](https://travis-ci.org/mr-doc/mr-doc-parser.svg?branch=master)](https://travis-ci.org/mr-doc/mr-doc-parser)

## Specification
## Introduction

A parser must implement the following interface:
This is the official parser for Mr. Doc. The parser uses [node-tree-sitter](https://github.com/tree-sitter/node-tree-sitter) to parse different programming languages. It also uses [xdoc-parser](https://github.com/iwatakeshi/xdoc-parser) to parse JSDoc-like syntaxes in a comment. Note that `mr-doc-parser` is in alpha. Thus, the algorithms may change over time. At the moment, there are two languages that are supported by `mr-doc-parser`: JavaScript and TypeScript. More languages can be added as long as [tree-sitter](https://github.com/tree-sitter) can parse them.

## Creating a Language Parser

### Extend the Language Parser

To create a parser, simply extend an abstract class named `Parser` in `src/lang/common/parser.ts`:

```typescript
interface IParser {
parse: (file: IFile) => IParseResult
abstract class Parser {
constructor(source: Source, options: any) {/* ... */}
abstract parse(): ASTNode[]
abstract get tree(): Tree
}
```

**Note**: See the [JavaScript parser](./src/lang/javascript/index.ts) for an example.

### Extend the Language Visitor

The next step is to walk the tree that parsed by `tree-sitter` and to wrap each node as an `Node` type.
Bear in mind that `tree-sitter` keeps its tree as a DOM-like structure.

It may seem like an additional step to re-wrap the nodes, but it is a necessary step to make visiting each node a bit easier:

```ts
// Example for JavaScript
import * as Parser from 'tree-sitter';
import * as JavaScript from 'tree-sitter-javascript';
import walk from 'path to [src/utils/walk]'

// Create the parser
const parser = new Parser();
// Set the langauge
parser.setLangauge(JavaScript);
// Parse the source code
const tree = parser.parse('...');
// Walk the tree
const nodes = walk(tree);

```

Once the tree is wrapped, we need to extend the abstract `Visitor` visitor:

```ts
abstract class Visitor {
abstract getAST(): ASTNode[]
abstract visitNode(node: SyntaxNode, properties?: object): ASTNode
abstract visitChildren(nodes: SyntaxNode[], properties?: object): ASTNode[]
}
```

The output should be in the following format:
**Note**: See the [JavaScript visitor](./src/lang/javascript/visitor.ts) for an example.

### Return the AST

The last step is to return the AST. To do so, simply use the `createNode` function and return an array of `ASTNode` type:

```typescript

interface IParseResult {
comments: IComment[],
interface ASTNode extends TextRange {
/**
* @property - The type of node.
*/
type: string,
file: IFile
/**
* @property - The context string.
*/
text: string,
/**
* @property - The node's children.
*/
children: ASTNode[] | undefined[],
/**
* @property - The context node that a comment node refers to.
*/
context: ASTNode,
/**
* @property - The properties that a ASTNode may possess.
*/
properties?: object
/**
* @property - The parsed XDoc comment.
*/
comment?: {
markdown: RemarkNode,
documentation: Partial<DocumentationNode>
}
}

```

These interfaces are defined in `parser/interface.ts`.
6 changes: 6 additions & 0 deletions build/corpus/example.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export declare namespace X {
/**
*
*/
function name(...args: any[]): void;
}
12 changes: 12 additions & 0 deletions build/corpus/example.js

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

28 changes: 28 additions & 0 deletions build/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Source from './src/interfaces/Source';
import Parser from './src/lang/common/parser';
import { Tree } from 'tree-sitter';
/**
* A class that parses a source code and generates an AST.
*
* @class Parser
* @implements IParser
*
* # Example
*
* ```js
* const parser = new Parser({
* name: '...',
* path: '....',
* text: '...'
* }, { language: 'typescript' });
*
* const result = parser.parse();
*
* ```
*/
export default class DocParser extends Parser {
private parser;
constructor(source: Source, options?: object);
parse: () => import("./src/interfaces/ASTNode").default[];
readonly tree: Tree;
}
37 changes: 37 additions & 0 deletions build/index.js

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

8 changes: 8 additions & 0 deletions build/src/ParserFactory.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Source from "./interfaces/Source";
import Parser from "./lang/common/parser";
export default class ParserFactory {
private source;
private options;
constructor(file: Source, options?: any);
getParser: () => Parser;
}
28 changes: 28 additions & 0 deletions build/src/ParserFactory.js

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

32 changes: 32 additions & 0 deletions build/src/interfaces/ASTNode.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import TextRange from "./TextRange";
import { RemarkNode } from "xdoc-parser/src/XDocParser";
import { DocumentationNode } from "xdoc-parser/src/XDocASTNode";
export default interface ASTNode extends TextRange {
/**
* @property - The type of node.
*/
type: string;
/**
* @property - The context string.
*/
text: string;
/**
* @property - The node's children.
*/
children: ASTNode[] | undefined[];
/**
* @property - The context node that a comment node refers to.
*/
context: ASTNode;
/**
* @property - The properties that a ASTNode may possess.
*/
properties?: object;
/**
* @property - The parsed XDoc comment.
*/
comment?: {
markdown: RemarkNode;
documentation: Partial<DocumentationNode>;
};
}
3 changes: 3 additions & 0 deletions build/src/interfaces/ASTNode.js

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

5 changes: 5 additions & 0 deletions build/src/interfaces/Source.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default interface Source {
name: string;
path: string;
text: string;
}
3 changes: 3 additions & 0 deletions build/src/interfaces/Source.js

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

37 changes: 37 additions & 0 deletions build/src/interfaces/TextRange.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* An interface that represents a range.
*
* @interface Range
*/
export interface Range {
start: number;
end: number;
}
/**
* An interface that represents the positional
* and locational ranges of a source code.
*
* @interface TextRange
*/
export default interface TextRange {
/**
* Represents a context's start and end position.
* @property position: {
* start: number,
* end: number
* }
*/
position: Range;
/**
* Represents a context's row and column location.
*
* @location: {
* row: Range,
* column: Range
* }
*/
location: {
row: Range;
column: Range;
};
}
3 changes: 3 additions & 0 deletions build/src/interfaces/TextRange.js

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

9 changes: 9 additions & 0 deletions build/src/lang/common/ast.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SyntaxNode } from "tree-sitter";
import Source from "../../interfaces/Source";
import ASTNode from "../../interfaces/ASTNode";
export declare function isASTNode(object: object): object is ASTNode;
export declare function createASTNode(source: Source, node: SyntaxNode): ASTNode;
export declare function createASTNode(source: Source, node: SyntaxNode, properties: object): any;
export declare function createASTNode(source: Source, node: SyntaxNode, children: object[]): ASTNode;
export declare function createASTNode(source: Source, node: SyntaxNode, children: object[], properties: object): any;
export declare function createASTNode(source: Source, node: SyntaxNode, context: ASTNode, document: boolean): ASTNode;
Loading