📄 parse.cpp
字号:
/******************************************************************************************************** * PROGRAM : * DATE - TIME : lundi 10 avril 2006 - 22:28 * AUTHOR : IComplete Team and Anacr0x ( fred.julian at gmail.com ) * FILENAME : * LICENSE : GPL * COMMENTARY : Modified file (with qt) of the icomplete project ********************************************************************************************************/#include <QRegExp>#include <QFile>#include <QProcess>#include <QDebug>#include "parse.h"#include "tree.h"#define QD qDebug() << __FILE__ << __LINE__ << ":"extern QString simplifiedText( QString );char* Parse::scanForIdent(const char **expr){ static char ident[256]; int valid_chars = 0; /* number of identified characters in the ident string */ char c; while ((c = **expr) != '\0') { if (valid_chars == 0 && isspace(c)) { (*expr)++; continue; } // XXX: Namespace support else if (isalpha(c) || c == '_') // ???: || c == ':') { ident[valid_chars] = c; if (++valid_chars == 255) { ident[255] = '\0'; return ident; } } /* a digit may be part of an ident but not from the start */ else if (isdigit(c)) { if (valid_chars) { ident[valid_chars] = c; if (++valid_chars == 255) { ident[255] = '\0'; return ident; } } else return NULL; } else break; (*expr)++; } if (valid_chars) { ident[valid_chars] = '\0'; return ident; } else return NULL;}bool Parse::scanForFuncdef(const QString &expr){ const char *pExpr = expr.toAscii(); char c; while ((c = *pExpr) != '\0') { switch (c) { case ' ': case '\t': case '\n': pExpr++; continue; case '(': return true; default: return false; } } return false;}QString Parse::getTypeOfToken(const QString &ident, const QString &className, Scope * scope, bool token_is_function){ /* if we have a variable and already found a local definition, just return it after duplicating */ if (!token_is_function && scope->localdef.length() && ident!="this") return scope->localdef; /* if the identifier is this-> return the current class */ if (ident == "this") { return scope->scope; } Tree *tree = NULL; if (className.length()) { tree = Tree::buildInheritanceTree(className); if (!tree) return NULL; } tagFileInfo info; tagEntry entry; tagFile *tfile = tagsOpen(tagsFilePath.toAscii(), &info); if (tfile && info.status.opened) { if (tagsFind(tfile, &entry, ident.toAscii(), TAG_OBSERVECASE | TAG_FULLMATCH) == TagSuccess) { do { if (tree && !tree->isMemberOfScope(&entry, scope)) continue; const char *kind = tagsField(&entry, "kind"); if (token_is_function) /* only list if tag is a function */ { if (!kind || (strcmp(kind, "function") && strcmp(kind, "prototype"))) continue; } else /* or a variable */ { //brc: add externvar for extern variables like cout if (!kind || (strcmp(kind, "variable") && strcmp(kind, "externvar") //brc: namespace workarround: add namespace && strcmp(kind, "namespace") && strcmp(kind, "member"))) continue; } /* need to duplicate the pattern, don't ask me why */ QString type = extractTypeQualifier(entry.address.pattern, ident); if(tree) tree->freeTree(); tagsClose(tfile); return type; } while (tagsFindNext(tfile, &entry) == TagSuccess); } tagsClose(tfile); } return NULL;}QString Parse::extractTypeQualifier(const QString &str, const QString &varName){#define STRING "\".*\""#define BRACKETEXPR "\\{.*\\}"//#define IDENT "[a-zA-Z_][a-zA-Z0-9_]*"//#define IDENT "[a-zA-Z_:][a-zA-Z0-9_:]*"#define IDENT "[a-zA-Z_:][a-zA-Z0-9_:]*"#define WS "[ \t\r\n]*"#define PTR "[\\*&]?\\*?"#define INITIALIZER "=(" WS IDENT WS ")|=(" WS STRING WS ")|=(" WS BRACKETEXPR WS ")"#define CONSTRUCTOR "(\\(" WS IDENT WS "\\))|(\\(" WS STRING WS "\\))"#define ARRAY WS "\\[" WS "[0-9]*" WS "\\]" WS QString pattern = "(" IDENT ")" // the 'std' in example a) "(::" IDENT ")*" // ::vector "(" WS "<[^>;]*>)?[ \t\n*&]{1}" // <char *> "(" WS PTR WS IDENT WS "(" ARRAY ")*" WS "((" INITIALIZER ")?|(" CONSTRUCTOR ")?)" WS "," WS ")*" // other variables for the same ident (string i,j,k;) "(" WS "[*&])?"; // check again for pointer/reference type QRegExp rx(pattern + WS + varName + "[^.-\\w]"); if( varName.isEmpty() ) return QString(); QString text = simplifiedText( str ); int pos = -1; int begin = -1; while( (pos = text.lastIndexOf(varName, begin) ) != -1 ) { begin = pos; while( begin>0 && text.at(begin)!= '\n' ) begin--; int end = pos; while( end<text.length()-1 && text.at(end)!= '\n' ) end++; QString line = text.mid(begin, end-begin).simplified(); if( !line.isEmpty() ) { int pos2 = 0; while ((pos2 = rx.indexIn(line, pos2)) != -1) { if( !QString("|delete|else|endif|throw|return|").contains( "|"+rx.cap(1)+"|" ) && rx.cap(1)!=":") { return rx.cap(1); } pos2 += rx.matchedLength(); } } } return QString();}bool Parse::getTypeOfExpression(const QString &expr, Expression * exp, Scope * scope){ char *ident = NULL; /* very basic stack implementation to keep track of tokens */ const int max_items = 20; const char *stack[max_items]; int num_stack = 0; /* skip nested brackets */ int brackets = 0, square_brackets = 0; bool in_ident = false; /* if the current position is within an identifier */ bool extract_ident = false; /* if we extract the next string which looks like an identifier - only after: . -> and ( */ QByteArray array(expr.toLocal8Bit() ); if( !array.count() ) return false; unsigned long len = array.length(); const char *first = array.data(), *start = first + len; while (--start >= first && start < (first + len) ) { /* skip brackets */ if (brackets > 0 || square_brackets > 0) { if (*start == '(') --brackets; else if (*start == ')') ++brackets; else if (*start == '[') --square_brackets; else if (*start == ']') ++square_brackets; continue; } /* identifier */ if (isdigit(*start)) in_ident = false; else if (isalpha(*start) || *start == '_') in_ident = true; else { switch (*start) { /* skip whitespace */ case ' ': case '\t': if (in_ident) goto extract; else { in_ident = false; continue; } /* continue searching to the left, if we * have a . or -> accessor */ case '.': if (in_ident && extract_ident) { const char *ident = start + 1; if (num_stack < max_items) stack[num_stack++] = ident; else return false; } in_ident = false; extract_ident = true; continue; case '>': /* pointer access */ case ':': /* static access */ if ((*start == '>' && (start - 1 >= first && *(start - 1) == '-')) || (*start == ':' && (start - 1 >= first && *(start - 1) == ':'))) { if (in_ident && extract_ident) { const char *ident = start + 1; if (num_stack < max_items) stack[num_stack++] = ident; else return false; } in_ident = false; extract_ident = true; --start; continue; } else { start++; goto extract; } case '(': /* start of a function */ if (extract_ident) { start++; goto extract; } else { extract_ident = true; in_ident = false; break; } case ')': if (in_ident) /* probably a cast - (const char*)str */ { start++; goto extract; } brackets++; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -