AST: Simple AST. Not used in the clients. Only part of the testing for now.
This commit is contained in:
parent
81642a18bd
commit
fa8e5cd7d8
|
@ -46,7 +46,10 @@ Token::Token(Token **t) :
|
||||||
_isLong(false),
|
_isLong(false),
|
||||||
_isUnused(false),
|
_isUnused(false),
|
||||||
_isStandardType(false),
|
_isStandardType(false),
|
||||||
_isExpandedMacro(false)
|
_isExpandedMacro(false),
|
||||||
|
_astOperand1(NULL),
|
||||||
|
_astOperand2(NULL),
|
||||||
|
_astParent(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,3 +1048,41 @@ std::string Token::stringifyList(bool varid) const
|
||||||
{
|
{
|
||||||
return stringifyList(varid, false, true, true, true, 0, 0);
|
return stringifyList(varid, false, true, true, true, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Token::astOperand1(Token *tok)
|
||||||
|
{
|
||||||
|
if (tok->_astParent) {
|
||||||
|
tok->_astParent->_astOperand2 = this;
|
||||||
|
_astParent = tok->_astParent;
|
||||||
|
}
|
||||||
|
tok->_astParent = this;
|
||||||
|
_astOperand1 = tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Token::astOperand2(Token *tok)
|
||||||
|
{
|
||||||
|
if (tok->_astParent) {
|
||||||
|
tok->_astParent->_astOperand1 = this;
|
||||||
|
_astParent = tok->_astParent;
|
||||||
|
}
|
||||||
|
_astOperand2 = tok;
|
||||||
|
tok->_astParent = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Token::astHandleParenthesis()
|
||||||
|
{
|
||||||
|
Token *innerTop = (_str == "(") ? _next : _previous;
|
||||||
|
while (innerTop->_astParent)
|
||||||
|
innerTop = innerTop->_astParent;
|
||||||
|
|
||||||
|
if (_astParent) {
|
||||||
|
if (_str == "(")
|
||||||
|
_astParent->_astOperand2 = innerTop;
|
||||||
|
else
|
||||||
|
_astParent->_astOperand1 = innerTop;
|
||||||
|
innerTop->_astParent = _astParent;
|
||||||
|
} else {
|
||||||
|
_astParent = innerTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
32
lib/token.h
32
lib/token.h
|
@ -542,6 +542,38 @@ private:
|
||||||
|
|
||||||
/** Update internal property cache about isStandardType() */
|
/** Update internal property cache about isStandardType() */
|
||||||
void update_property_isStandardType();
|
void update_property_isStandardType();
|
||||||
|
|
||||||
|
// AST..
|
||||||
|
Token *_astOperand1;
|
||||||
|
Token *_astOperand2;
|
||||||
|
Token *_astParent;
|
||||||
|
public:
|
||||||
|
void astOperand1(Token *tok);
|
||||||
|
void astOperand2(Token *tok);
|
||||||
|
void astHandleParenthesis();
|
||||||
|
void astHandleBrackets();
|
||||||
|
|
||||||
|
const Token * astOperand1() const {
|
||||||
|
return _astOperand1;
|
||||||
|
}
|
||||||
|
const Token * astOperand2() const {
|
||||||
|
return _astOperand2;
|
||||||
|
}
|
||||||
|
const Token *astTop() const {
|
||||||
|
const Token *ret = this;
|
||||||
|
while (ret->_astParent)
|
||||||
|
ret = ret->_astParent;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string astString() const {
|
||||||
|
std::string ret;
|
||||||
|
if (_astOperand1)
|
||||||
|
ret = _astOperand1->astString();
|
||||||
|
if (_astOperand2)
|
||||||
|
ret += _astOperand2->astString();
|
||||||
|
return ret+_str;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -339,6 +339,57 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0)
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void TokenList::createAst()
|
||||||
|
{
|
||||||
|
// operators that must be ordered according to C-precedence
|
||||||
|
const char * const operators[] = {
|
||||||
|
" :: ",
|
||||||
|
" [ . ++ -- ",
|
||||||
|
"> ++ -- + - ! ~ * & ", // prefix unary operators, from right to left
|
||||||
|
" || ",
|
||||||
|
" && ",
|
||||||
|
" | ",
|
||||||
|
" ^ ",
|
||||||
|
" & ",
|
||||||
|
" == != ",
|
||||||
|
" < <= > >= ",
|
||||||
|
" << >> ",
|
||||||
|
" + - ",
|
||||||
|
" * / % "
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < sizeof(operators) / sizeof(*operators); ++i) {
|
||||||
|
// TODO: extract operators to std::set - that should be faster
|
||||||
|
if (*operators[i] == '>') {
|
||||||
|
const std::string op(1+operators[i]);
|
||||||
|
Token *tok = _front;
|
||||||
|
while (tok->next())
|
||||||
|
tok = tok->next();
|
||||||
|
for (; tok; tok = tok->previous()) {
|
||||||
|
if ((!tok->previous() || tok->previous()->isOp()) &&
|
||||||
|
op.find(" "+tok->str()+" ")!=std::string::npos) {
|
||||||
|
tok->astOperand1(tok->next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const std::string op(operators[i]);
|
||||||
|
for (Token *tok = _front; tok; tok = tok->next()) {
|
||||||
|
if (tok->astOperand1()==NULL && op.find(" "+tok->str()+" ")!=std::string::npos) {
|
||||||
|
tok->astOperand1(tok->previous());
|
||||||
|
tok->astOperand2(tok->next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parentheses..
|
||||||
|
for (Token *tok = _front; tok; tok = tok->next()) {
|
||||||
|
if (tok->str() == "(" || tok->str() == ")" || tok->str() == "]") {
|
||||||
|
tok->astHandleParenthesis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& TokenList::file(const Token *tok) const
|
const std::string& TokenList::file(const Token *tok) const
|
||||||
{
|
{
|
||||||
return _files.at(tok->fileIndex());
|
return _files.at(tok->fileIndex());
|
||||||
|
|
|
@ -105,6 +105,8 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string fileLine(const Token *tok) const;
|
std::string fileLine(const Token *tok) const;
|
||||||
|
|
||||||
|
void createAst();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Disable copy constructor, no implementation */
|
/** Disable copy constructor, no implementation */
|
||||||
TokenList(const TokenList &);
|
TokenList(const TokenList &);
|
||||||
|
|
|
@ -459,6 +459,12 @@ private:
|
||||||
TEST_CASE(platformUnix64);
|
TEST_CASE(platformUnix64);
|
||||||
|
|
||||||
TEST_CASE(simplifyMathExpressions); //ticket #1620
|
TEST_CASE(simplifyMathExpressions); //ticket #1620
|
||||||
|
|
||||||
|
// AST data
|
||||||
|
TEST_CASE(astexpr);
|
||||||
|
TEST_CASE(astpar);
|
||||||
|
TEST_CASE(astbrackets);
|
||||||
|
TEST_CASE(astunaryop);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp", bool cpp11 = true) {
|
std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp", bool cpp11 = true) {
|
||||||
|
@ -7619,6 +7625,43 @@ private:
|
||||||
ASSERT_EQUALS(expected1, tokenizeAndStringify(code1));
|
ASSERT_EQUALS(expected1, tokenizeAndStringify(code1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::string testAst(const char code[]) {
|
||||||
|
// tokenize given code..
|
||||||
|
TokenList tokenList(NULL);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
if (!tokenList.createTokens(istr,"test.cpp"))
|
||||||
|
return "ERROR";
|
||||||
|
|
||||||
|
// Create AST..
|
||||||
|
tokenList.createAst();
|
||||||
|
|
||||||
|
return tokenList.front()->astTop()->astString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void astexpr() {
|
||||||
|
ASSERT_EQUALS("123++", testAst("1+2+3"));
|
||||||
|
ASSERT_EQUALS("12*3+", testAst("1*2+3"));
|
||||||
|
ASSERT_EQUALS("123*+", testAst("1+2*3"));
|
||||||
|
ASSERT_EQUALS("12*34*+", testAst("1*2+3*4"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void astpar() {
|
||||||
|
ASSERT_EQUALS("12+3*", testAst("(1+2)*3"));
|
||||||
|
ASSERT_EQUALS("123+*", testAst("1*(2+3)"));
|
||||||
|
ASSERT_EQUALS("123+*4*", testAst("1*(2+3)*4"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void astbrackets() {
|
||||||
|
ASSERT_EQUALS("123+[4+", testAst("1[2+3]+4"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void astunaryop() {
|
||||||
|
ASSERT_EQUALS("12-+", testAst("1+-2"));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestTokenizer)
|
REGISTER_TEST(TestTokenizer)
|
||||||
|
|
Loading…
Reference in New Issue