Skip to content

Commit

Permalink
Added the unparser to the C++ version as well.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sreeni Viswanadha committed Mar 22, 2021
1 parent ffc3e84 commit 1feb271
Show file tree
Hide file tree
Showing 10 changed files with 804 additions and 745 deletions.
32 changes: 29 additions & 3 deletions parser/cpp/AstNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,36 @@ class AstNode : public SimpleNode {
Token* endToken;
virtual ~AstNode() {}
AstNode(int id) : SimpleNode(id) {}

AstNode(SqlParser* parser, int id) : SimpleNode(parser, id) {}
int NumChildren() { return jjtGetNumChildren(); }
AstNode* GetChild(int i) { return static_cast<AstNode*>(jjtGetChild(i)); }
JJString toString(const JJString& prefix) const {

int kind() const { return id; }

int numChildren() const { return jjtGetNumChildren(); }

AstNode* getChild(int i) const { return static_cast<AstNode*>(jjtGetChild(i)); }

std::string getImage() const { return numChildren() == 0 ? beginToken->image : string(""); }

void VisitNode(SqlParserVisitor* visitor) const { jjtAccept(visitor, nullptr); }

void VisitChildren(SqlParserVisitor* visitor) const { jjtChildrenAccept(visitor, nullptr); }

const AstNode* firstChild() const { return numChildren() > 0 ? getChild(0) : nullptr; }

const AstNode* lastChild() const { return numChildren() > 0 ? getChild(numChildren() - 1) : nullptr; }

const AstNode* getFirstChildOfKind(int kind) const {
for (int i = 0; i < numChildren(); i++) {
if (getChild(i)->kind() == kind) {
return getChild(i);
}
}

return nullptr;
}

std::string toString(const JJString& prefix) const {
return SimpleNode::toString(prefix) +
string(" (") +
std::to_string(beginToken->beginLine) +
Expand Down
562 changes: 562 additions & 0 deletions parser/cpp/SqlParserVisitor.h

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions parser/cpp/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

echo 'Generating parser ...'
mvn clean generate-sources
mv target/generated-sources/javacc/SqlParserVisitor.h .
echo 'Compiling ...'
./compile.sh
2 changes: 1 addition & 1 deletion parser/cpp/compile.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
SRC_DIR=./target/generated-sources/javacc
TARGET_DIR=./target
clang++ -fbracket-depth=1024 -funsigned-char -I. -I./$SRC_DIR -o $TARGET_DIR/sqlparser -std=c++11 ParseErrorHandler.cc main.cc $SRC_DIR/*.cc
clang++ -O2 -fbracket-depth=1024 -funsigned-char -I. -I./$SRC_DIR -o $TARGET_DIR/sqlparser -std=c++11 ParseErrorHandler.cc main.cc $SRC_DIR/*.cc unparser.cc
5 changes: 3 additions & 2 deletions parser/cpp/javacc-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ options {
NODE_PREFIX = "";
MULTI = true;
VISITOR = true;
VISITOR_METHOD_NAME_INCLUDES_TYPE_NAME = true;
}

PARSER_BEGIN(SqlParser)
Expand Down Expand Up @@ -96,8 +97,8 @@ PARSER_BEGIN(SqlParser)

// For some nodes, the node is opened after some children are already created. Reset the begin for those to be
// the begin of the left-most child.
if (astNode->NumChildren() > 0) {
Token* t0 = astNode->GetChild(0)->beginToken;
if (astNode->numChildren() > 0) {
Token* t0 = astNode->getChild(0)->beginToken;
if (t0->beginLine < t->beginLine || (t0->beginLine == t->beginLine && t0->beginColumn < t->beginColumn)) {
astNode->beginToken = t0;
}
Expand Down
13 changes: 9 additions & 4 deletions parser/cpp/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <iostream>
#include <string>
#include <stdlib.h>
#include <ctime>

#include "SqlParserConstants.h"
#include "CharStream.h"
Expand All @@ -11,8 +12,7 @@
#include "SqlParser.h"
#include "SqlParserTokenManager.h"
#include "parser.h"

#include <ctime>
#include "unparser.h"

using namespace commonsql::parser;
using namespace std;
Expand All @@ -39,21 +39,26 @@ int main(int argc, char **argv) {
double time;
start = clock();

for (int i = 0; i < 1; i++) {
CharStream *stream = new CharStream(s.c_str(), s.size() - 1, 1, 1);
SqlParserTokenManager *scanner = new SqlParserTokenManager(stream);
SqlParser parser(scanner);
parser.setErrorHandler(new ParseErrorHandler());
for (int i = 0; i < 10; i++) {
stream = new CharStream(s.c_str(), s.size() - 1, 1, 1);
scanner->ReInit(stream);
parser.ReInit(scanner);
parser.compilation_unit();
SimpleNode *root = (SimpleNode*)parser.jjtree.peekNode();
if (root) {
JAVACC_STRING_TYPE buffer;
root->dumpToBuffer(" ", "\n", &buffer);
printf("%s\n", buffer.c_str());

printf("Unparse:\n%s\n", unparse(static_cast<AstNode*>(root)).c_str());
}
}

finish = clock();
time = (double(finish)-double(start))/CLOCKS_PER_SEC;
printf ("Avg parsing time: %lfms\n", (time*1000)/1);
printf ("Avg parsing time: %lfms\n", (time*1000)/10);
}
118 changes: 118 additions & 0 deletions parser/cpp/unparser.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Licensed under the Apache License, Version 2->0 (the "License");
* you may not use this file except in compliance with the License->
* You may obtain a copy of the License at
*
* http://www->apache->org/licenses/LICENSE-2->0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied->
* See the License for the specific language governing permissions and
* limitations under the License->
*/

#include "unparser.h"

namespace commonsql {
namespace parser {

void Unparser::printSpecialTokens(const Token* t)
{
// special tokens are chained in reverse->
Token* specialToken = t->specialToken;
if (specialToken != nullptr) {
while (specialToken->specialToken != nullptr) {
specialToken = specialToken->specialToken;
}
while (specialToken != nullptr) {
stringBuilder << specialToken->image.c_str();
specialToken = specialToken->next;
}
}
}

void Unparser::printTrailingComments()
{
if (lastToken != nullptr && lastToken->kind == EOF) {
printSpecialTokens(lastToken);
}
}

void Unparser::printToken(const std::string& s)
{
stringBuilder << " " << s.c_str() << " ";
}

void Unparser::printToken(const Token* t)
{
while (lastToken != t) {
lastToken = lastToken->next;
printSpecialTokens(lastToken);
stringBuilder << lastToken->image;
}
}

void Unparser::printUptoToken(const Token* t)
{
while (lastToken->next != t) {
printToken(lastToken->next);
}
}

void Unparser::moveToEndOfNode(const AstNode* node)
{
lastToken = node->endToken;
}

void Unparser::unparseUpto(const AstNode* node)
{
printUptoToken(node->beginToken);
}

void Unparser::unparseRestOfTheNode(const AstNode* node)
{
if (lastToken != node->endToken) {
printUptoToken(node->endToken);
}
}

void Unparser::defaultVisit(const SimpleNode* node, void* data)
{
const AstNode* astNode = static_cast<const AstNode*>(node);
const AstNode* firstChild = astNode->firstChild();
const AstNode* lastChild = astNode->lastChild();

// Print the tokens->
if (firstChild == nullptr || astNode->beginToken != firstChild->beginToken) {
printToken(astNode->beginToken);
}

astNode->VisitChildren(this);

if (lastChild != nullptr && astNode->endToken != lastChild->endToken) {
printToken(astNode->endToken);
}
}

std::string Unparser::unparse(const AstNode* node)
{
stringBuilder.clear();
lastToken->next = node->beginToken;
node->VisitNode(this);
printTrailingComments();
return getUnparsedString();
}

std::string unparse(const AstNode* node, Unparser* unparser)
{
return unparser->unparse(node);
}

std::string unparse(const AstNode* node)
{
return unparse(node, new Unparser());
}

}
}
44 changes: 44 additions & 0 deletions parser/cpp/unparser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef __UNPARSE_H__
#define __UNPARSE_H__

#include <sstream>
#include "AstNode.h"
#include "SqlParserVisitor.h"

namespace commonsql {
namespace parser {

using std::string;
using std::stringstream;

class Unparser : public SqlParserDefaultVisitor {
private:
Token* lastToken = new Token();

virtual void printSpecialTokens(const Token* t);
virtual void printTrailingComments();

protected:
std::stringstream stringBuilder;

virtual void printToken(const std::string& s);
virtual void printToken(const Token* t);
virtual void printUptoToken(const Token* t);
virtual void moveToEndOfNode(const AstNode* node);
virtual void unparseUpto(const AstNode* node);
virtual void unparseRestOfTheNode(const AstNode* node);
virtual const string getUnparsedString() const { return stringBuilder.str(); }

public:
string unparse(const AstNode* node);
void defaultVisit(const SimpleNode* node, void* data);
virtual ~Unparser() {}
};

std::string unparse(const AstNode* node, Unparser* unparser);
std::string unparse(const AstNode* node);

}
}

#endif
Loading

0 comments on commit 1feb271

Please sign in to comment.