kde-extraapps/kdevelop/languages/cpp/parser/codegenerator.cpp
2015-07-26 14:23:17 +03:00

907 lines
18 KiB
C++

/*
Copyright 2008 Hamish Rodda <rodda@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "codegenerator.h"
#include "tokens.h"
#include "lexer.h"
#include "parsesession.h"
/*
Thoughts.
- tokens are actually the position in the token stream, whose position can be determined, and thus replaced.
- we need to be able to make changes where there are changes [todo], or generate directly when it's a new node [done]
*/
CodeGenerator::CodeGenerator(ParseSession* session)
: m_output(&m_outputString)
, m_session(session)
{
}
CodeGenerator::~CodeGenerator()
{
}
QString CodeGenerator::output()
{
m_output.flush();
return m_outputString;
}
void CodeGenerator::outputToken(uint tokenPosition)
{
if (tokenPosition) {
const Token& t = m_session->token_stream->token(tokenPosition);
m_output << m_session->token_stream->symbolString(t);
/* if (t.kind == Token_identifier || t.kind == Token_string_literal || t.kind == Token_number_literal || t.kind == Token_char_literal)
m_output << t.symbolString().str();
else
m_output << token_text( t.kind );*/
}
}
void CodeGenerator::print(const ListNode<uint>* tokenList, bool followingSpace)
{
if (!tokenList)
return;
const ListNode<uint>* it = tokenList->toFront(), *end = it;
bool first = true;
do {
if (first) first = false; else m_output << " ";
outputToken(it->element);
it = it->next;
} while (it != end);
if (followingSpace)
m_output << " ";
}
void CodeGenerator::print(uint token, bool followingSpace)
{
if (!token)
return;
outputToken(token);
if (followingSpace)
m_output << " ";
}
void CodeGenerator::printToken(int token, bool followingSpace)
{
m_output << token_text(token);
if (followingSpace)
m_output << " ";
}
void CodeGenerator::visitAccessSpecifier(AccessSpecifierAST* node)
{
print(node->specs);
m_output << ":";
}
void CodeGenerator::visitAsmDefinition(AsmDefinitionAST* node)
{
print(node->cv);
DefaultVisitor::visitAsmDefinition(node);
}
void CodeGenerator::visitBaseClause(BaseClauseAST* node)
{
m_output << ":";
commaPrintNodes(this, node->base_specifiers);
}
void CodeGenerator::visitBaseSpecifier(BaseSpecifierAST* node)
{
if (node->virt) {
print(node->virt, true);
}
print(node->access_specifier, true);
DefaultVisitor::visitBaseSpecifier(node);
}
void CodeGenerator::visitBinaryExpression(BinaryExpressionAST* node)
{
visit(node->left_expression);
// TODO whitespace
print(node->op);
visit(node->right_expression);
}
void CodeGenerator::visitBracedInitList(BracedInitListAST* node)
{
m_output << "{";
visit(node->list);
m_output << "}";
}
void CodeGenerator::visitCastExpression(CastExpressionAST* node)
{
m_output << "(";
visit(node->type_id);
m_output << ")";
visit(node->expression);
}
void CodeGenerator::visitClassMemberAccess(ClassMemberAccessAST* node)
{
print(node->op);
DefaultVisitor::visitClassMemberAccess(node);
}
void CodeGenerator::visitClassSpecifier(ClassSpecifierAST* node)
{
print(node->class_key, true);
visit(node->win_decl_specifiers);
visit(node->name);
visit(node->base_clause);
m_output << "{";
visitNodes(this, node->member_specs);
m_output << "}";
}
void CodeGenerator::visitCompoundStatement(CompoundStatementAST* node)
{
m_output << "{";
DefaultVisitor::visitCompoundStatement(node);
m_output << "}";
}
void CodeGenerator::visitCondition(ConditionAST* node)
{
if (node->declarator) {
visit(node->type_specifier);
visit(node->declarator);
m_output << "=";
}
visit(node->expression);
}
void CodeGenerator::visitConditionalExpression(ConditionalExpressionAST* node)
{
visit(node->condition);
m_output << "?";
visit(node->left_expression);
m_output << ":";
visit(node->right_expression);
}
void CodeGenerator::visitCppCastExpression(CppCastExpressionAST* node)
{
print(node->op);
m_output << "<";
visit(node->type_id);
m_output << ">(";
visit(node->expression);
m_output << ")";
visitNodes(this, node->sub_expressions);
}
void CodeGenerator::visitCtorInitializer(CtorInitializerAST* node)
{
m_output << ":";
visitCommaPrint(node->member_initializers);
}
void CodeGenerator::visitDeclarationStatement(DeclarationStatementAST* node)
{
DefaultVisitor::visitDeclarationStatement(node);
}
void CodeGenerator::visitDeclarator(DeclaratorAST* node)
{
if (node->sub_declarator) {
m_output << "(";
visit(node->sub_declarator);
m_output << ")";
}
visitNodes(this, node->ptr_ops);
visit(node->id);
if (node->bit_expression) {
m_output << ":";
visit(node->bit_expression);
}
surroundPrintNodes(this, node->array_dimensions, "[", "]");
if (node->parameter_declaration_clause) {
m_output << "(";
visit(node->parameter_declaration_clause);
m_output << ")";
}
print(node->fun_cv, true);
visit(node->exception_spec);
}
void CodeGenerator::visitDeleteExpression(DeleteExpressionAST* node)
{
print( node->scope_token );
print( node->delete_token );
print( node->lbracket_token );
print( node->rbracket_token );
m_output << " ";
DefaultVisitor::visitDeleteExpression(node);
}
void CodeGenerator::visitDoStatement(DoStatementAST* node)
{
printToken( Token_do, true );
visit(node->statement);
printToken( Token_while );
m_output << "(";
visit(node->expression);
m_output << ");";
}
void CodeGenerator::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST* node)
{
print(node->type, true);
DefaultVisitor::visitElaboratedTypeSpecifier(node);
}
void CodeGenerator::visitEnumSpecifier(EnumSpecifierAST* node)
{
printToken(Token_enum, true);
visit(node->name);
if (node->enumerators) {
m_output << "{";
visitCommaPrint(node->enumerators);
m_output << "}";
}
}
void CodeGenerator::visitEnumerator(EnumeratorAST* node)
{
print(node->id);
if (node->expression) {
m_output << "=";
visit(node->expression);
}
}
void CodeGenerator::visitExceptionSpecification(ExceptionSpecificationAST* node)
{
if (node->no_except)
{
printToken(Token_noexcept);
if (node->noexcept_expression)
{
m_output << "(";
DefaultVisitor::visitExceptionSpecification(node);
m_output << ")";
}
}
else
{
printToken(Token_throw);
m_output << "(";
print(node->ellipsis);
DefaultVisitor::visitExceptionSpecification(node);
m_output << ")";
}
}
void CodeGenerator::visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST* node)
{
DefaultVisitor::visitExpressionOrDeclarationStatement(node);
}
void CodeGenerator::visitExpressionStatement(ExpressionStatementAST* node)
{
DefaultVisitor::visitExpressionStatement(node);
m_output << ";";
}
void CodeGenerator::visitForStatement(ForStatementAST* node)
{
printToken(Token_for);
m_output << "(";
if (node->range_declaration) {
visit(node->range_declaration);
m_output << " : ";
} else {
if (node->init_statement) {
visit(node->init_statement);
// Init statement gives its own ;
} else {
m_output << ";";
}
visit(node->condition);
m_output << ";";
}
visit(node->expression);
m_output << ")";
visit(node->statement);
}
void CodeGenerator::visitFunctionCall(FunctionCallAST* node)
{
m_output << "(";
DefaultVisitor::visitFunctionCall(node);
m_output << ")";
}
void CodeGenerator::visitFunctionDefinition(FunctionDefinitionAST* node)
{
visit(node->type_specifier);
visit(node->declarator);
visit(node->constructor_initializers);
visit(node->function_body);
visit(node->win_decl_specifiers);
}
void CodeGenerator::visitIfStatement(IfStatementAST* node)
{
printToken(Token_if);
m_output << "(";
visit(node->condition);
m_output << ")";
visit(node->statement);
if (node->else_statement) {
printToken(Token_else, true);
visit(node->else_statement);
}
}
void CodeGenerator::visitIncrDecrExpression(IncrDecrExpressionAST* node)
{
print(node->op);
}
void CodeGenerator::visitInitDeclarator(InitDeclaratorAST* node)
{
DefaultVisitor::visitInitDeclarator(node);
}
void CodeGenerator::visitInitializer(InitializerAST* node)
{
if (node->initializer_clause) {
m_output << "=";
visit(node->initializer_clause);
} else if (node->expression) {
m_output << "(";
visit(node->expression);
m_output << ")";
}
}
void CodeGenerator::visitInitializerClause(InitializerClauseAST* node)
{
visit(node->expression);
}
void CodeGenerator::visitInitializerList(InitializerListAST* node)
{
visitCommaPrint(node->clauses);
if (node->isVariadic) {
m_output << "...";
}
}
void CodeGenerator::visitJumpStatement(JumpStatementAST* node)
{
print(node->op, true);
print(node->identifier);
m_output << ";";
}
void CodeGenerator::visitLabeledStatement(LabeledStatementAST* node)
{
print(node->label, true);
visit(node->expression);
m_output << ":";
visit(node->statement);
}
void CodeGenerator::visitLinkageBody(LinkageBodyAST* node)
{
m_output << "{";
DefaultVisitor::visitLinkageBody(node);
m_output << "}";
}
void CodeGenerator::visitLinkageSpecification(LinkageSpecificationAST* node)
{
printToken(Token_extern, true);
print(node->extern_type, true);
DefaultVisitor::visitLinkageSpecification(node);
}
void CodeGenerator::visitMemInitializer(MemInitializerAST* node)
{
visit(node->initializer_id);
m_output << "(";
visit(node->expression);
m_output << ")";
}
void CodeGenerator::visitName(NameAST* node)
{
if (node->global)
printToken( Token_scope );
if (node->qualified_names) {
commaPrintNodes( this, node->qualified_names, token_text( Token_scope ) );
printToken( Token_scope );
}
visit(node->unqualified_name);
}
void CodeGenerator::visitNamespace(NamespaceAST* node)
{
printToken( Token_namespace, true );
print(node->namespace_name);
DefaultVisitor::visitNamespace(node);
}
void CodeGenerator::visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST* node)
{
printToken( Token_namespace, true );
print(node->namespace_name);
m_output << "=";
DefaultVisitor::visitNamespaceAliasDefinition(node);
m_output << ";";
}
void CodeGenerator::visitNewDeclarator(NewDeclaratorAST* node)
{
visit(node->ptr_op);
visit(node->sub_declarator);
surroundPrintNodes(this, node->expressions, "[", "]");
}
void CodeGenerator::visitNewExpression(NewExpressionAST* node)
{
print(node->scope_token);
print(node->new_token, true);
if (node->expression) {
m_output << "(";
visit(node->expression);
m_output << ")";
}
if (node->type_id) {
m_output << "(";
visit(node->type_id);
m_output << ")";
}
visit(node->new_type_id);
visit(node->new_initializer);
}
void CodeGenerator::visitNewInitializer(NewInitializerAST* node)
{
m_output << "(";
DefaultVisitor::visitNewInitializer(node);
m_output << ")";
}
void CodeGenerator::visitNewTypeId(NewTypeIdAST* node)
{
DefaultVisitor::visitNewTypeId(node);
}
void CodeGenerator::visitOperator(OperatorAST* node)
{
print(node->op);
if (node->op != node->open)
print(node->open);
print(node->close);
DefaultVisitor::visitOperator(node);
}
void CodeGenerator::visitOperatorFunctionId(OperatorFunctionIdAST* node)
{
printToken(Token_operator, true);
DefaultVisitor::visitOperatorFunctionId( node );
}
void CodeGenerator::visitParameterDeclaration(ParameterDeclarationAST* node)
{
if (node->type_specifier) {
visit(node->type_specifier);
m_output << " ";
}
visit(node->declarator);
if (node->expression) {
m_output << "=";
visit(node->expression);
}
}
void CodeGenerator::visitParameterDeclarationClause(ParameterDeclarationClauseAST* node)
{
commaPrintNodes(this, node->parameter_declarations);
// TODO add elipsis
}
void CodeGenerator::visitPostfixExpression(PostfixExpressionAST* node)
{
DefaultVisitor::visitPostfixExpression(node);
}
void CodeGenerator::visitPrimaryExpression(PrimaryExpressionAST* node)
{
if (node->type == PrimaryExpressionAST::Token) {
print(node->token);
} else if (node->type == PrimaryExpressionAST::Literal) {
visit(node->literal);
} else if (node->type == PrimaryExpressionAST::Name) {
visit(node->name);
} else if (node->type == PrimaryExpressionAST::Statement || node->type == PrimaryExpressionAST::SubExpression) {
m_output << "(";
if (node->type == PrimaryExpressionAST::Statement) {
visit(node->expression_statement);
} else {
visit(node->sub_expression);
}
m_output << ")";
}
}
void CodeGenerator::visitPtrOperator(PtrOperatorAST* node)
{
print(node->op);
DefaultVisitor::visitPtrOperator(node);
print(node->cv);
}
void CodeGenerator::visitPtrToMember(PtrToMemberAST* node)
{
visit(node->class_type);
printToken(Token_scope);
m_output << "*";
}
void CodeGenerator::visitReturnStatement(ReturnStatementAST* node)
{
printToken(Token_return, true);
DefaultVisitor::visitReturnStatement(node);
m_output << ";";
}
void CodeGenerator::visitSimpleDeclaration(SimpleDeclarationAST* node)
{
print(node->storage_specifiers, true);
print(node->function_specifiers, true);
visit(node->type_specifier);
commaPrintNodes(this, node->init_declarators);
visit(node->win_decl_specifiers);
m_output << ";";
}
void CodeGenerator::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST* node)
{
print(node->cv, true);
print(node->integrals, true);
if (node->name) {
visit(node->name);
m_output << " ";
}
if (node->isTypeof) {
m_output << "typeof";
///TODO: expression in parens?
if (node->type_id) {
m_output << "(";
visit(node->type_id);
m_output << ")";
}
visit(node->expression);
} else if (node->isDecltype) {
m_output << "decltype(";
visit(node->expression);
m_output << ")";
}
}
void CodeGenerator::visitSizeofExpression(SizeofExpressionAST* node)
{
printToken(Token_sizeof);
if (node->type_id) {
m_output << "(";
visit(node->type_id);
m_output << ")";
}
visit(node->expression);
}
void CodeGenerator::visitStringLiteral(StringLiteralAST* node)
{
print(node->literals);
}
void CodeGenerator::visitSubscriptExpression(SubscriptExpressionAST* node)
{
m_output << "[";
DefaultVisitor::visitSubscriptExpression(node);
m_output << "]";
}
void CodeGenerator::visitSwitchStatement(SwitchStatementAST* node)
{
printToken(Token_switch);
m_output << "(";
visit(node->condition);
m_output << ")";
visit(node->statement);
}
void CodeGenerator::visitTemplateArgument(TemplateArgumentAST* node)
{
DefaultVisitor::visitTemplateArgument(node);
}
void CodeGenerator::visitTemplateDeclaration(TemplateDeclarationAST* node)
{
if (node->exported) {
printToken(Token_export, true);
}
printToken(Token_template, true);
if (node->template_parameters) {
m_output << "< ";
commaPrintNodes(this, node->template_parameters);
m_output << " >";
}
visit(node->declaration);
}
void CodeGenerator::visitTemplateParameter(TemplateParameterAST* node)
{
DefaultVisitor::visitTemplateParameter(node);
}
void CodeGenerator::visitThrowExpression(ThrowExpressionAST* node)
{
printToken(Token_throw);
DefaultVisitor::visitThrowExpression(node);
}
void CodeGenerator::visitTranslationUnit(TranslationUnitAST* node)
{
DefaultVisitor::visitTranslationUnit(node);
}
void CodeGenerator::visitTryBlockStatement(TryBlockStatementAST* node)
{
printToken(Token_try);
visit(node->try_block);
visitNodes(this, node->catch_blocks);
}
void CodeGenerator::visitCatchStatement(CatchStatementAST* node)
{
printToken(Token_catch);
m_output << "(";
visit(node->condition);
m_output << ")";
visit(node->statement);
}
void CodeGenerator::visitTypeId(TypeIdAST* node)
{
DefaultVisitor::visitTypeId(node);
}
void CodeGenerator::visitTypeIdentification(TypeIdentificationAST* node)
{
print(node->typename_token);
visit(node->name);
if (node->expression) {
m_output << "(";
visit(node->expression);
m_output << ")";
}
}
void CodeGenerator::visitTypeParameter(TypeParameterAST* node)
{
print(node->type, true);
visit(node->name);
if (node->type_id) {
m_output << "=";
visit(node->type_id);
}
if (node->template_parameters) {
m_output << "<";
commaPrintNodes(this, node->template_parameters);
m_output << ">";
// TODO when AST ready: if (node->template_class_token) printToken(Token_class);
}
if (node->template_name) {
m_output << "=";
visit(node->template_name);
}
}
void CodeGenerator::visitTypedef(TypedefAST* node)
{
printToken( Token_typedef );
visit(node->type_specifier);
commaPrintNodes(this, node->init_declarators);
m_output << ";";
}
void CodeGenerator::visitUnaryExpression(UnaryExpressionAST* node)
{
print(node->op);
DefaultVisitor::visitUnaryExpression(node);
}
void CodeGenerator::visitUnqualifiedName(UnqualifiedNameAST* node)
{
print(node->tilde);
print(node->id);
visit(node->operator_id);
if (node->template_arguments) {
m_output << "< ";
visitNodes(this, node->template_arguments);
m_output << " >";
}
}
void CodeGenerator::visitUsing(UsingAST* node)
{
printToken(Token_using, true);
print(node->type_name);
DefaultVisitor::visitUsing(node);
m_output << ";";
}
void CodeGenerator::visitUsingDirective(UsingDirectiveAST* node)
{
printToken(Token_using, true);
printToken(Token_namespace, true);
DefaultVisitor::visitUsingDirective(node);
m_output << ";";
}
void CodeGenerator::visitWhileStatement(WhileStatementAST* node)
{
printToken(Token_while);
m_output << "(";
visit(node->condition);
m_output << ")";
visit(node->statement);
}
void CodeGenerator::visitWinDeclSpec(WinDeclSpecAST* node)
{
print(node->specifier);
m_output << "(";
print(node->modifier);
m_output << ")";
}