summaryrefslogtreecommitdiffstats
path: root/lib/cppparser/parser.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cppparser/parser.h')
-rw-r--r--lib/cppparser/parser.h459
1 files changed, 459 insertions, 0 deletions
diff --git a/lib/cppparser/parser.h b/lib/cppparser/parser.h
new file mode 100644
index 00000000..ff3891ac
--- /dev/null
+++ b/lib/cppparser/parser.h
@@ -0,0 +1,459 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "ast.h"
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qvaluestack.h>
+#include <set>
+#include <iostream>
+
+struct ParserPrivateData;
+
+class Driver;
+class Lexer;
+class Token;
+struct Error;
+
+
+class CommentFormatter {
+ static inline bool isWhite( QChar c ) {
+ return c.isSpace();
+ }
+
+ static void rStrip( QString str, QString& from ) {
+ if( str.isEmpty() ) return;
+
+ int i = 0;
+ int ip = from.length();
+ int s = from.length();
+
+ for( int a = s-1; a >= 0; a-- ) {
+ if( isWhite( from[a] ) ) {
+ continue;
+ } else {
+ if( from[a] == str[i] ) {
+ i++;
+ ip = a;
+ if( i == (int)str.length() ) break;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if( ip != (int)from.length() ) from = from.left( ip );
+ }
+
+ static void strip( QString str, QString& from ) {
+ if( str.isEmpty() ) return;
+
+ int i = 0;
+ int ip = 0;
+ int s = from.length();
+
+ for( int a = 0; a < s; a++ ) {
+ if( isWhite( from[a] ) ) {
+ continue;
+ } else {
+ if( from[a] == str[i] ) {
+ i++;
+ ip = a+1;
+ if( i == (int)str.length() ) break;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if( ip ) from = from.mid( ip );
+ }
+
+ public:
+
+ static QString formatComment( QString comment ) {
+ QString ret;
+ int i = 0;
+ int s = comment.length();
+ while( i < s && comment[i] == '/' ) {
+ i++;
+ }
+
+ if( i > 1 ) {
+ ret = comment.mid( i );
+ } else {
+ ///remove the star in each line
+ QStringList lines = QStringList::split( "\n", comment );
+
+ if( lines.isEmpty() ) return ret;
+
+ strip( "/**", lines.front() );
+ rStrip( "/**", lines.back() );
+
+ QStringList::iterator it = lines.begin();
+ ++it;
+ QStringList::iterator eit = lines.end();
+
+ if( it != lines.end() ) {
+ --eit;
+
+ for( ; it != eit; ++it ) {
+ strip( "*", *it );
+ }
+
+ if( lines.front().stripWhiteSpace().isEmpty() )
+ lines.pop_front();
+
+ if( lines.back().stripWhiteSpace().isEmpty() )
+ lines.pop_back();
+ }
+
+ ret = lines.join( "\n" );
+ }
+
+ return ret;
+ }
+};
+
+class Comment {
+ QString m_text;
+ int m_line;
+ bool m_formatted;
+
+
+ void format() {
+ if( m_formatted ) return;
+ m_formatted = true;
+ m_text = CommentFormatter::formatComment( m_text );
+ }
+
+ public:
+ Comment( QString text = "", int line = -1 ) : m_text( text ), m_line( line ), m_formatted(false) {
+ }
+
+ Comment( int line ) : m_line( line ) {
+ }
+
+ void operator += ( Comment rhs ) {
+ format();
+ rhs.format();
+ m_text += " " + rhs.m_text;
+ }
+
+ operator bool() const {
+ return !m_text.isEmpty();
+ }
+
+ operator QString() {
+ format();
+ return m_text;
+ }
+
+ inline int line() const {
+ return m_line;
+ }
+
+ bool operator < ( Comment& rhs ) const {
+ return m_line < rhs.m_line;
+ }
+
+ bool isSame ( const Comment& rhs ) {
+ if( rhs.m_formatted ) format();
+ return m_text == rhs.m_text;
+ }
+
+ struct cmp {
+ bool operator () ( const Comment& c1, const Comment& c2 ) const {
+ return c1.line() < c2.line();
+ }
+ };
+};
+
+
+class CommentStore {
+ private:
+ typedef std::set< Comment, Comment::cmp > CommentSet;
+ CommentSet m_comments;
+
+ public:
+
+ ///Returns the comment nearest to "end"(inclusive), and returns & removes it
+ Comment getCommentInRange( int end, int start = 0 ) {
+ CommentSet::iterator it = m_comments.lower_bound( end );
+
+
+ while( it != m_comments.begin() && (*it).line() > end ) {
+ --it;
+ }
+
+ if( it != m_comments.end() && (*it).line() >= start && (*it).line() <= end ) {
+ Comment ret = *it;
+ m_comments.erase( it );
+ return ret;
+ } else {
+ return Comment();
+ }
+ }
+
+ ///Returns and removes the comment in the line
+ Comment getComment( int line ) {
+ CommentSet::iterator it = m_comments.find( line );
+ if( it != m_comments.end() ) {
+ Comment ret = *it;
+ m_comments.erase( it );
+ return ret;
+ } else {
+ return Comment();
+ }
+ }
+
+ void addComment( Comment comment ) {
+
+ CommentSet::iterator it = m_comments.find( comment );
+ if( it != m_comments.end() ) {
+ if( comment.isSame( *it ) ) return;
+ Comment c = *it;
+ c += comment;
+ comment = c;
+ m_comments.erase( it );
+ }
+
+ m_comments.insert( comment );
+ }
+
+ ///Does not delete the comment
+ Comment latestComment() {
+ CommentSet::iterator it = m_comments.end();
+ if( it == m_comments.begin() ) return Comment();
+ --it;
+ return *it;
+ }
+
+ void clear() {
+ m_comments.clear();
+ }
+};
+
+
+class Parser
+{
+public:
+ Parser( Driver* driver, Lexer* lexer );
+ virtual ~Parser();
+
+private:
+ virtual bool reportError( const Error& err );
+ /** @todo remove*/ virtual bool reportError( const QString& msg );
+ /** @todo remove*/ virtual void syntaxError();
+
+public /*rules*/ :
+
+ bool parseTranslationUnit( TranslationUnitAST::Node& node );
+
+ bool parseDeclaration( DeclarationAST::Node& node );
+ bool parseBlockDeclaration( DeclarationAST::Node& node );
+ bool parseLinkageSpecification( DeclarationAST::Node& node );
+ bool parseLinkageBody( LinkageBodyAST::Node& node );
+ bool parseNamespace( DeclarationAST::Node& node );
+ bool parseNamespaceAliasDefinition( DeclarationAST::Node& node );
+ bool parseUsing( DeclarationAST::Node& node );
+ bool parseUsingDirective( DeclarationAST::Node& node );
+ bool parseTypedef( DeclarationAST::Node& node );
+ bool parseAsmDefinition( DeclarationAST::Node& node );
+ bool parseTemplateDeclaration( DeclarationAST::Node& node );
+ bool parseDeclarationInternal( DeclarationAST::Node& node );
+
+ bool parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node );
+ bool parseStringLiteral( AST::Node& node );
+ bool parseName( NameAST::Node& node );
+ bool parseOperatorFunctionId( AST::Node& node );
+ bool parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError=true );
+ bool parseOperator( AST::Node& node );
+ bool parseCvQualify( GroupAST::Node& node );
+ bool parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parsePtrOperator( AST::Node& node );
+ bool parseTemplateArgument( AST::Node& node );
+ bool parseTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& node );
+ bool parseDeclarator( DeclaratorAST::Node& node );
+ bool parseTemplateParameterList( TemplateParameterListAST::Node& node );
+ bool parseTemplateParameter( TemplateParameterAST::Node& node );
+ bool parseStorageClassSpecifier( GroupAST::Node& node );
+ bool parseFunctionSpecifier( GroupAST::Node& node );
+ bool parseInitDeclaratorList( InitDeclaratorListAST::Node& node );
+ bool parseInitDeclarator( InitDeclaratorAST::Node& node );
+ bool parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node );
+ bool parseCtorInitializer( AST::Node& node );
+ bool parsePtrToMember( AST::Node& node );
+ bool parseEnumSpecifier( TypeSpecifierAST::Node& node );
+ bool parseClassSpecifier( TypeSpecifierAST::Node& node );
+ bool parseWinDeclSpec( GroupAST::Node& node );
+ bool parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseDeclaratorId( NameAST::Node& node );
+ bool parseExceptionSpecification( GroupAST::Node& node );
+ bool parseEnumerator( EnumeratorAST::Node& node );
+ bool parseTypeParameter( TypeParameterAST::Node& node );
+ bool parseParameterDeclaration( ParameterDeclarationAST::Node& node );
+ bool parseTypeId( AST::Node& node );
+ bool parseAbstractDeclarator( DeclaratorAST::Node& node );
+ bool parseParameterDeclarationList( ParameterDeclarationListAST::Node& node );
+ bool parseMemberSpecification( DeclarationAST::Node& node );
+ bool parseAccessSpecifier( AST::Node& node );
+ bool parseTypeIdList( GroupAST::Node& node );
+ bool parseMemInitializerList( AST::Node& node );
+ bool parseMemInitializer( AST::Node& node );
+ bool parseInitializer( AST::Node& node );
+ bool parseBaseClause( BaseClauseAST::Node& node );
+ bool parseBaseSpecifier( BaseSpecifierAST::Node& node );
+ bool parseInitializerClause( AST::Node& node );
+ bool parseMemInitializerId( NameAST::Node& node );
+ bool parseFunctionBody( StatementListAST::Node& node );
+
+ // expression
+ bool skipExpression( AST::Node& node );
+ bool skipCommaExpression( AST::Node& node );
+ bool skipExpressionStatement( StatementAST::Node& node );
+
+ bool parseExpression( AST::Node& node );
+ bool parsePrimaryExpression( AST::Node& node );
+ bool parsePostfixExpression( AST::Node& node );
+ bool parseUnaryExpression( AST::Node& node );
+ bool parseNewExpression( AST::Node& node );
+ bool parseNewTypeId( AST::Node& node );
+ bool parseNewDeclarator( AST::Node& node );
+ bool parseNewInitializer( AST::Node& node );
+ bool parseDeleteExpression( AST::Node& node );
+ bool parseCastExpression( AST::Node& node );
+ bool parsePmExpression( AST::Node& node );
+ bool parseMultiplicativeExpression( AST::Node& node );
+ bool parseAdditiveExpression( AST::Node& node );
+ bool parseShiftExpression( AST::Node& node );
+ bool parseRelationalExpression( AST::Node& node, bool templArgs=false );
+ bool parseEqualityExpression( AST::Node& node, bool templArgs=false );
+ bool parseAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseExclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseInclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseConditionalExpression( AST::Node& node );
+ bool parseAssignmentExpression( AST::Node& node );
+ bool parseConstantExpression( AST::Node& node );
+ bool parseCommaExpression( AST::Node& node );
+ bool parseThrowExpression( AST::Node& node );
+
+ // statement
+ bool parseCondition( ConditionAST::Node& node );
+ bool parseStatement( StatementAST::Node& node );
+ bool parseWhileStatement( StatementAST::Node& node );
+ bool parseDoStatement( StatementAST::Node& node );
+ bool parseForStatement( StatementAST::Node& node );
+ bool parseForEachStatement( StatementAST::Node& node ); // qt4 [erbsland]
+ bool parseCompoundStatement( StatementAST::Node& node );
+ bool parseForInitStatement( StatementAST::Node& node );
+ bool parseIfStatement( StatementAST::Node& node );
+ bool parseSwitchStatement( StatementAST::Node& node );
+ bool parseLabeledStatement( StatementAST::Node& node );
+ bool parseDeclarationStatement( StatementAST::Node& node );
+ bool parseTryBlockStatement( StatementAST::Node& node );
+
+ // objective c
+ bool parseObjcDef( DeclarationAST::Node& node );
+ bool parseObjcClassDef( DeclarationAST::Node& node );
+ bool parseObjcClassDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDecl( DeclarationAST::Node& node );
+ bool parseObjcAliasDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDef( DeclarationAST::Node& node );
+ bool parseObjcMethodDef( DeclarationAST::Node& node );
+
+ bool parseIvarDeclList( AST::Node& node );
+ bool parseIvarDecls( AST::Node& node );
+ bool parseIvarDecl( AST::Node& node );
+ bool parseIvars( AST::Node& node );
+ bool parseIvarDeclarator( AST::Node& node );
+ bool parseMethodDecl( AST::Node& node );
+ bool parseUnarySelector( AST::Node& node );
+ bool parseKeywordSelector( AST::Node& node );
+ bool parseSelector( AST::Node& node );
+ bool parseKeywordDecl( AST::Node& node );
+ bool parseReceiver( AST::Node& node );
+ bool parseObjcMessageExpr( AST::Node& node );
+ bool parseMessageArgs( AST::Node& node );
+ bool parseKeywordExpr( AST::Node& node );
+ bool parseKeywordArgList( AST::Node& node );
+ bool parseKeywordArg( AST::Node& node );
+ bool parseReservedWord( AST::Node& node );
+ bool parseMyParms( AST::Node& node );
+ bool parseMyParm( AST::Node& node );
+ bool parseOptParmList( AST::Node& node );
+ bool parseObjcSelectorExpr( AST::Node& node );
+ bool parseSelectorArg( AST::Node& node );
+ bool parseKeywordNameList( AST::Node& node );
+ bool parseKeywordName( AST::Node& node );
+ bool parseObjcEncodeExpr( AST::Node& node );
+ bool parseObjcString( AST::Node& node );
+ bool parseProtocolRefs( AST::Node& node );
+ bool parseIdentifierList( GroupAST::Node& node );
+ bool parseIdentifierColon( AST::Node& node );
+ bool parseObjcProtocolExpr( AST::Node& node );
+ bool parseObjcOpenBracketExpr( AST::Node& node );
+ bool parseObjcCloseBracket( AST::Node& node );
+
+ void nextToken( bool skipComments = true );
+
+ ///parses all comments until the end of the line
+ Comment comment();
+ void preparseLineComments( int line );
+ void processComment( int offset = 0 );
+ void clearComment( );
+
+ bool skipUntil( int token );
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip( int l, int r );
+ QString toString( int start, int end, const QString& sep=" " ) const;
+
+private:
+ int currentLine();
+ CommentStore m_commentStore;
+
+ template<class Type>
+ void eventuallyTakeComment( int startLn, int line, Type& ast );
+ template<class Type>
+ void eventuallyTakeComment( Type& ast );
+
+ ParserPrivateData* d;
+ Driver* m_driver;
+ Lexer* lex;
+ Comment m_currentComment;
+ int m_problems;
+ int m_maxProblems;
+ bool objcp;
+
+private:
+ Parser( const Parser& source );
+ void operator = ( const Parser& source );
+};
+
+
+#endif