lava-oushudb-dt-sql-parser/src/parser/common/basicParser.ts

115 lines
2.9 KiB
TypeScript
Raw Normal View History

2023-05-04 10:13:05 +08:00
import { ParseTreeWalker, CommonTokenStream } from 'antlr4';
import type { Parser } from 'antlr4/src/antlr4';
import ParserErrorListener, {
ParserError,
ErrorHandler,
ParserErrorCollector,
} from './parserErrorListener';
2023-05-04 10:13:05 +08:00
interface IParser {
// Lost in type definition
ruleNames: string[];
// Customized in our parser
program(): any;
}
/**
* Custom Parser class, subclass needs extends it.
*/
2023-05-04 10:13:05 +08:00
export default abstract class BasicParser {
private _parser: IParser & Parser;
public parse(
input: string,
2023-05-04 10:13:05 +08:00
errorListener?: ErrorHandler<any>,
) {
const parser = this.createParser(input);
this._parser = parser;
parser.removeErrorListeners();
parser.addErrorListener(new ParserErrorListener(errorListener));
2022-12-16 02:58:20 +08:00
const parserTree = parser.program();
return parserTree;
}
public validate(input: string): ParserError[] {
const lexerError = []; const syntaxErrors = [];
const parser = this.createParser(input);
this._parser = parser;
parser.removeErrorListeners();
parser.addErrorListener(new ParserErrorCollector(syntaxErrors));
2022-12-16 02:58:20 +08:00
parser.program();
return lexerError.concat(syntaxErrors);
}
/**
* Create antrl4 Lexer object
* @param input source string
*/
2023-05-04 10:13:05 +08:00
public abstract createLexer(input: string);
/**
* Create Parser by lexer
* @param lexer Lexer
*/
2023-05-04 10:13:05 +08:00
public abstract createParserFromLexer(lexer);
/**
2023-05-04 10:13:05 +08:00
* Get all Tokens of input string
* @param input string
2023-05-04 10:13:05 +08:00
* @returns Token[]
*/
2023-05-04 10:13:05 +08:00
public getAllTokens(input: string): string[] {
const lexer = this.createLexer(input);
const tokensStream = new CommonTokenStream(lexer);
tokensStream.fill();
return tokensStream.tokens;
};
/**
* Get Parser instance by input string
* @param input
*/
2023-05-04 10:13:05 +08:00
public createParser(input: string): IParser & Parser {
const lexer = this.createLexer(input);
const parser: any = this.createParserFromLexer(lexer);
parser.buildParseTrees = true;
this._parser = parser;
return parser;
}
/**
* It convert tree to string, it's convenient to use in unit test.
* @param string input
*/
public parserTreeToString(input: string): string {
const parser = this.createParser(input);
this._parser = parser;
2022-12-16 02:58:20 +08:00
const tree = parser.program();
return tree.toStringTree(parser.ruleNames);
}
/**
* Get List-like style tree string
* @param parserTree
*/
public toString(parserTree: any): string {
return parserTree.toStringTree(this._parser.ruleNames);
}
/**
* @param listener Listener instance extends ParserListener
* @param parserTree parser Tree
*/
public listen(listener: any, parserTree: any) {
ParseTreeWalker.DEFAULT.walk(listener, parserTree);
}
}