|
| 1 | +// parse |
1 | 2 | import { ANTLRInputStream, CommonTokenStream } from 'antlr4ts';
|
2 | 3 | import { JavaLexer } from './parser/JavaLexer';
|
3 | 4 | import { CompilationUnitContext, JavaParser } from './parser/JavaParser';
|
4 |
| -export { CompilationUnitContext }; |
| 5 | + |
| 6 | +// walk |
| 7 | +import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker'; |
| 8 | +import { JavaParserListener } from './parser/JavaParserListener'; |
| 9 | +import { JavaParserVisitor } from './parser/JavaParserVisitor'; |
| 10 | + |
| 11 | +// createVisitor |
| 12 | +import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor'; |
| 13 | +import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; |
| 14 | +import { RuleNode } from 'antlr4ts/tree/RuleNode'; |
5 | 15 |
|
6 | 16 | /**
|
7 | 17 | * Parses the given source code and returns the AST
|
8 | 18 | * @param source Java source code to parse
|
9 | 19 | */
|
10 |
| -export function parse(source: string): CompilationUnitContext { |
| 20 | +export function parse(source: string): ParseTree { |
11 | 21 | const chars = new ANTLRInputStream(source);
|
12 | 22 | const lexer = new JavaLexer(chars);
|
13 | 23 | const tokens = new CommonTokenStream(lexer);
|
14 | 24 | const parser = new JavaParser(tokens);
|
15 | 25 | return parser.compilationUnit();
|
16 | 26 | }
|
| 27 | + |
| 28 | +// Just to create a more user-friendly name as all arguments that are name 'tree' take this |
| 29 | +// (type alias doesn't create a new name) |
| 30 | +// tslint:disable-next-line:no-empty-interface |
| 31 | +export interface ParseTree extends CompilationUnitContext {} |
| 32 | + |
| 33 | +/** |
| 34 | + * Walks a parse tree |
| 35 | + * @see https://github.com/antlr/antlr4/blob/master/doc/listeners.md |
| 36 | + */ |
| 37 | +export function walk(listener: JavaParserListener, tree: ParseTree) { |
| 38 | + ParseTreeWalker.DEFAULT.walk(listener, tree); |
| 39 | +} |
| 40 | +export { JavaParserListener } from './parser/JavaParserListener'; |
| 41 | + |
| 42 | +/** |
| 43 | + * Create a parse tree visitor |
| 44 | + */ |
| 45 | +export function createVisitor<T>(visitor: Visitor<T>): ConcreteVisitor<T> { |
| 46 | + // we don't want users to write classes because it's not JavaScript-y |
| 47 | + // so we'll set implementation of abstract methods and other visit* methods in constructor |
| 48 | + // @ts-ignore |
| 49 | + return new class extends AbstractParseTreeVisitor<T> { |
| 50 | + constructor() { |
| 51 | + super(); |
| 52 | + Object.assign(this, visitor); |
| 53 | + } |
| 54 | + }(); |
| 55 | +} |
| 56 | + |
| 57 | +export interface Visitor<T> |
| 58 | + extends AbstractVisitor<T>, |
| 59 | + Omit<JavaParserVisitor<T>, NonOverridableMethods> {} |
| 60 | + |
| 61 | +type NonOverridableMethods = keyof ParseTreeVisitor<any>; |
| 62 | + |
| 63 | +// Just to create a better name |
| 64 | +export interface ConcreteVisitor<T> extends AbstractParseTreeVisitor<T> {} |
| 65 | + |
| 66 | +// from AbstractParseTreeVisitor |
| 67 | +interface AbstractVisitor<T> { |
| 68 | + /** |
| 69 | + * Gets the default value returned by visitor methods. This value is |
| 70 | + * returned by the default implementations of |
| 71 | + * {@link #visitTerminal visitTerminal}, {@link #visitErrorNode visitErrorNode}. |
| 72 | + * The default implementation of {@link #visitChildren visitChildren} |
| 73 | + * initializes its aggregate result to this value. |
| 74 | + * |
| 75 | + * @return The default value returned by visitor methods. |
| 76 | + */ |
| 77 | + defaultResult: () => T; |
| 78 | + |
| 79 | + /** |
| 80 | + * Aggregates the results of visiting multiple children of a node. After |
| 81 | + * either all children are visited or {@link #shouldVisitNextChild} returns |
| 82 | + * {@code false}, the aggregate value is returned as the result of |
| 83 | + * {@link #visitChildren}. |
| 84 | + * |
| 85 | + * <p>The default implementation returns {@code nextResult}, meaning |
| 86 | + * {@link #visitChildren} will return the result of the last child visited |
| 87 | + * (or return the initial value if the node has no children).</p> |
| 88 | + * |
| 89 | + * @param aggregate The previous aggregate value. In the default |
| 90 | + * implementation, the aggregate value is initialized to |
| 91 | + * {@link #defaultResult}, which is passed as the {@code aggregate} argument |
| 92 | + * to this method after the first child node is visited. |
| 93 | + * @param nextResult The result of the immediately preceeding call to visit |
| 94 | + * a child node. |
| 95 | + * |
| 96 | + * @return The updated aggregate result. |
| 97 | + */ |
| 98 | + aggregateResult: (aggregate: T, nextResult: T) => T; |
| 99 | + |
| 100 | + /** |
| 101 | + * This method is called after visiting each child in |
| 102 | + * {@link #visitChildren}. This method is first called before the first |
| 103 | + * child is visited; at that point {@code currentResult} will be the initial |
| 104 | + * value (in the default implementation, the initial value is returned by a |
| 105 | + * call to {@link #defaultResult}. This method is not called after the last |
| 106 | + * child is visited. |
| 107 | + * |
| 108 | + * <p>The default implementation always returns {@code true}, indicating that |
| 109 | + * {@code visitChildren} should only return after all children are visited. |
| 110 | + * One reason to override this method is to provide a "short circuit" |
| 111 | + * evaluation option for situations where the result of visiting a single |
| 112 | + * child has the potential to determine the result of the visit operation as |
| 113 | + * a whole.</p> |
| 114 | + * |
| 115 | + * @param node The {@link RuleNode} whose children are currently being |
| 116 | + * visited. |
| 117 | + * @param currentResult The current aggregate result of the children visited |
| 118 | + * to the current point. |
| 119 | + * |
| 120 | + * @return {@code true} to continue visiting children. Otherwise return |
| 121 | + * {@code false} to stop visiting children and immediately return the |
| 122 | + * current aggregate result from {@link #visitChildren}. |
| 123 | + */ |
| 124 | + shouldVisitNextChild?: (node: RuleNode, currentResult: T) => boolean; |
| 125 | +} |
| 126 | + |
| 127 | +export * from './parser/JavaContexts'; |
0 commit comments