📄 rpp.cpp
字号:
/******************************************************************************** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.** Copyright (C) 2001-2004 Roberto Raggi**** This file is part of the qt3to4 porting application of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "rpp.h"#include "rppexpressionbuilder.h"using namespace TokenEngine;namespace Rpp{Preprocessor::Preprocessor(){}Source *Preprocessor::parse(const TokenEngine::TokenContainer &tokenContainer, const QVector<Type> &tokenTypeList, TypedPool<Item> *memoryPool){ m_memoryPool = memoryPool; Source *m_source = createNode<Source>(m_memoryPool); //node whith no parent m_tokenContainer = tokenContainer; m_tokenTypeList = tokenTypeList; lexerTokenIndex = 0; numTokens = m_tokenContainer.count(); if(m_tokenContainer.count() != tokenTypeList.count()) { emit error("Error", "Internal error in preprocessor: Number of tokens is not equal to number of types in type list"); return m_source; } if(tokenTypeList.isEmpty()) { // emit error("Warning:", "Trying to parse empty source file"); return m_source; } Q_ASSERT(m_source->toItemComposite()); parseGroup(m_source); return m_source;}// group-part// group group-partbool Preprocessor::parseGroup(Item *group){ Q_ASSERT(group->toItemComposite()); bool gotGroup = false; while(lexerTokenIndex < numTokens) { if (!parseGroupPart(group)) break; gotGroup = true; } return gotGroup;}//if-section (# if / # ifdef / #ifndef )//control-line ( #include / etc )//# non-directive ( # text newline//text-line (text newline )bool Preprocessor::parseGroupPart(Item *group){ //cout << "parse group part" << endl; Q_ASSERT(group->toItemComposite()); //look up first significant token Type token = lookAhead(); if(token == Token_eof) return false; //look for '#' if(token != Token_preproc) return parseTextLine(group); //look up first significant token after the '#' token = lookAheadSkipHash(); if(token == Token_eof) return false; // Check if we are at the end of a group. This is not an neccesarely an // error, it happens when we reach an #endif for example. if (token == Token_directive_elif || token == Token_directive_else || token == Token_directive_endif) return false; // if-section? if(token == Token_directive_if || token == Token_directive_ifdef || token == Token_directive_ifndef) return parseIfSection(group); // control-line? if (token == Token_directive_define) return parseDefineDirective(group); if (token == Token_directive_undef) return parseUndefDirective(group); if (token == Token_directive_include) return parseIncludeDirective(group); if (token == Token_directive_error) return parseErrorDirective(group); if (token == Token_directive_pragma) return parsePragmaDirective(group); return parseNonDirective(group);}// if-section -> if-group elif-groups[opt] else-group[opt] endif-linebool Preprocessor::parseIfSection(Item *group){ // cout << "parse if section" << endl ; Q_ASSERT(group->toItemComposite()); IfSection *ifSection = createNode<IfSection>(m_memoryPool, group); group->toItemComposite()->add(ifSection); if (!parseIfGroup(ifSection)) return false; Type type = lookAheadSkipHash(); if(type == Token_directive_elif) if(!parseElifGroups(ifSection)) return false; type = lookAheadSkipHash(); if(type == Token_directive_else) if(!parseElseGroup(ifSection)) return false; return parseEndifLine(ifSection);}bool Preprocessor::parseNonDirective(Item *group){ // cout << "parsenondirective" << endl; Q_ASSERT(group->toItemComposite()); TokenSection tokenSection = readLine(); if(tokenSection.count() == 0) return false; NonDirective *nonDirective = createNode<NonDirective>(m_memoryPool, group); group->toItemComposite()->add(nonDirective); nonDirective->setTokenSection(tokenSection); return true;}bool Preprocessor::parseTextLine(Item *group){ //cout << "parsetextline" << endl; Q_ASSERT(group->toItemComposite()); const TokenSection tokenSection = readLine(); // cout << tokenSection.fullText().constData() << endl; if(tokenSection.count() == 0) return false; Text *text = createNode<Text>(m_memoryPool, group); group->toItemComposite()->add(text); text->setTokenSection(tokenSection); // Create Token-derived nodes and atach to text QVector<Token *> tokens; tokens.reserve(tokenSection.count()); for (int t = 0; t < tokenSection.count(); ++t) { Token *node = 0; const int containerIndex = tokenSection.containerIndex(t); switch(m_tokenTypeList.at(containerIndex)) { case Token_identifier: case Token_defined: case Token_directive_if: case Token_directive_elif: case Token_directive_else: case Token_directive_undef: case Token_directive_endif: case Token_directive_ifdef: case Token_directive_ifndef: case Token_directive_define: case Token_directive_include: node = createNode<IdToken>(m_memoryPool, text); break; case Token_line_comment: node = createNode<LineComment>(m_memoryPool, text); break; case Token_multiline_comment: node = createNode<MultiLineComment>(m_memoryPool, text); break; case Token_whitespaces: case Token_char_literal: case Token_string_literal: default: node = createNode<NonIdToken>(m_memoryPool, text); break; } Q_ASSERT(node); node->setToken(containerIndex); tokens.append(node); } text->setTokens(tokens); return true;}// if-group -> ifDirective// if-group -> ifdefDirevtive// if-group -> ifndefDirevtivebool Preprocessor::parseIfGroup(IfSection *ifSection){ // cout << "parse if group" << endl; Q_ASSERT(ifSection->toItemComposite()); bool result; const Type type = lookAheadSkipHash(); if (type == Token_directive_ifdef) { IfdefDirective *d = createNode<IfdefDirective>(m_memoryPool, ifSection); result = parseIfdefLikeDirective(d); ifSection->setIfGroup(d); } else if (type == Token_directive_ifndef) { IfndefDirective *d = createNode<IfndefDirective>(m_memoryPool, ifSection); result = parseIfdefLikeDirective(d); ifSection->setIfGroup(d); } else if (type == Token_directive_if) { IfDirective *d = createNode<IfDirective>(m_memoryPool, ifSection); result = parseIfLikeDirective(d); ifSection->setIfGroup(d); } else { result = false; } return result;}bool Preprocessor::parseElifGroups(IfSection *ifSection){ //cout << "parse ElifGroups" << endl; bool gotElif = false; while(lookAheadSkipHash() == Token_directive_elif ) { if (!parseElifGroup(ifSection)) break; gotElif = true; } return gotElif;}bool Preprocessor::parseElifGroup(IfSection *ifSection){ //cout << "parse ElifGroup" << endl; ElifDirective *elifDirective = createNode<ElifDirective>(m_memoryPool, ifSection); ifSection->addElifGroup(elifDirective); return parseIfLikeDirective(elifDirective);}bool Preprocessor::parseElseGroup(IfSection *ifSection){ //cout << "parse else group" << endl; TokenSection tokenSection = readLine(); if(tokenSection.count() == 0) return false; ElseDirective *elseDirective = createNode<ElseDirective>(m_memoryPool, ifSection); ifSection->setElseGroup(elseDirective); elseDirective->setTokenSection(tokenSection); parseGroup(elseDirective); return true;}//# endif newlinebool Preprocessor::parseEndifLine(IfSection *ifSection){ //cout << "parse endifline" << endl; TokenSection tokenSection = readLine(); if(tokenSection.count() == 0) return false; EndifDirective *endifDirective = createNode<EndifDirective>(m_memoryPool, ifSection); ifSection->setEndifLine(endifDirective); endifDirective->setTokenSection(tokenSection); return true;}//parses an "ifdef-like" directive, like #ifdef and #ifndef :)//# ifdef identifier newline group[opt]bool Preprocessor::parseIfdefLikeDirective(IfdefLikeDirective *node){ Q_ASSERT(node->toItemComposite()); const TokenSection tokenSection = readLine(); const QVector<int> cleanedLine = cleanTokenRange(tokenSection); if(cleanedLine.count() < 3) return false; node->setTokenSection(tokenSection); node->setIdentifier(TokenList(m_tokenContainer, QVector<int>() << cleanedLine.at(2))); parseGroup(node); return true;}//# if constant-expression newline group[opt]bool Preprocessor::parseIfLikeDirective(IfLikeDirective *node){ //cout << "parse if-like directive" << endl; Q_ASSERT(node->toItemComposite()); TokenSection tokenSection = readLine(); QVector<int> cleanedSection = cleanTokenRange(tokenSection); if(cleanedSection.count() < 3) return false; cleanedSection.erase(cleanedSection.begin(), cleanedSection.begin() + 2); //remove # and if cleanedSection.pop_back(); //remove endl; const TokenList sectionList(m_tokenContainer, cleanedSection); ExpressionBuilder expressionBuilder(sectionList, m_tokenTypeList, m_memoryPool); Expression *expr = expressionBuilder.parse(); node->setTokenSection(tokenSection); node->setExpression(expr); parseGroup(node); return true;}/* # define identifier replacement-list new-line # define identifier lparen identifier-list[opt] ) replacement-list new-line # define identifier lparen ... ) replacement-list new-line # define identifier lparen identifier-list, ... ) replacement-list new-line*/bool Preprocessor::parseDefineDirective(Item *group){ Q_ASSERT(group->toItemComposite()); const TokenSection line = readLine(); const QVector<int> cleanedLine = cleanTokenRange(line); if(cleanedLine.count() < 3) return false; // get identifier
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -