1
SQLParser.h :HOWTO 파서를 여러 번 사용 하시겠습니까?
class SQLParser{
/*____Variables____*/
private:
std::string _vendor;
antlr4::CommonTokenStream* _tokenStream;
antlr4::Parser* _parser;
antlr4::Lexer* _lexer;
/*____Functions____*/
public:
SQLParser(const std::string& Vendor);
~SQLParser();
antlr4::CommonTokenStream* get_tokens(const std::string& text);
std::vector<std::string> get_lexems(const std::string& text);
antlr4::ParserRuleContext* parse(const std::string& text);
bool check_syntax(const std::string& text);
void print_string_tree(const std::string& text); // parse and print in LISP format
};
SQLParser.cpp :
...
CommonTokenStream* SQLParser::get_tokens(const std::string& text){
(dynamic_cast<ANTLRInputStream*>(_lexer->getInputStream()))->load(text);
_tokenStream->reset();
_tokenStream->fill();
return _tokenStream;
}
std::vector<std::string> SQLParser::get_lexems(const std::string& text){
get_tokens(text);
std::vector<std::string> lexems;
for(auto token : _tokenStream->getTokens()) {
lexems.push_back(token->getText());
}
return lexems;
}
ParserRuleContext* SQLParser::parse(const std::string& text){
get_tokens(text);
_parser->setInputStream(_tokenStream);
ParserRuleContext* tree;
try{
if(_vendor == "tsql"){
tree = (dynamic_cast<tsqlParser*>(_parser))->root();
}
if(_vendor == "mysql"){
tree = (dynamic_cast<mysqlParser*>(_parser))->root();
}
}
catch(std::_Nested_exception<ParseCancellationException>& e){
return nullptr;
}
return tree;
}
목적 SQLParser 각 콘크리트 벤더 생성된다. 이 개체를 사용하여 여러 입력 텍스트을 구문 분석하고 싶습니다. 하지만 TokenStream 크기에 문제가 있습니다. 나는 그 크기가 동적으로 변할 것이라고 예상했다. 이 같은 예를 들어 , 주요 : MAIN.CPP이 같은
#include <iostream>
#include <string>
#include <antlr4-runtime.h>
#include "SQLParser.h"
using namespace antlr4;
int main(){
SQLParser parser("tsql");
std::cout << "'select 1;': ";
parser.print_string_tree("select 1;");
std::cout << "\n\n'select 1,2,3;': ";
parser.print_string_tree("select 1,2;");
std::cout << "\n";
return 0;
}
주고 출력 :
'select 1;': (root (sql_clauses (sql_clause (dml_clause (select_statement (query_expression (query_specification select (select_list (select_list_elem (expression (constant 1)))))) ;)))) <EOF>)
'select 1,2,3;': (root (sql_clauses (sql_clause (dml_clause (select_statement (query_expression (query_specification select (select_list (select_list_elem (expression (constant 1)))))) ,)))))
어떻게 TokenStream이 오류를 방지하기 위해 사용해야합니까?
이 *은 C++ API는 C# 것과 같은 경우 =>이, 당신이 그렇게 안하고 * "나는 여러 입력 텍스트를 구문 분석이 개체를 사용하려면" - 대신 다른 스트림/렉서/파서를 생성합니다. 기본적으로 렉서는 토큰을 캐시합니다. * 왜 * 다른 방식으로하고 싶습니까? [XY 문제] (https://meta.stackexchange.com/q/66377/271659)? –