added support for C++14/17 number literals

This commit is contained in:
Günter Obiltschnig
2018-12-30 21:00:17 +01:00
parent 5d3d62bb54
commit d6f97fe346
4 changed files with 177 additions and 50 deletions

View File

@@ -244,9 +244,16 @@ public:
Poco::Token::Class tokenClass() const;
bool start(char c, std::istream& istr);
void finish(std::istream& istr);
int asInteger() const;
double asFloat() const;
protected:
void finishHex(std::istream& istr, int next);
void finishBin(std::istream& istr, int next);
void finishExp(std::istream& istr, int next);
void finishSuffix(std::istream& istr, int next);
private:
bool _isFloat;
};

View File

@@ -513,23 +513,18 @@ void NumberLiteralToken::finish(std::istream& istr)
_isFloat = false;
if (_value[0] != '.') // starts with digit
{
if (next == 'x')
if (_value[0] == '0')
{
_value += (char) istr.get();
next = istr.peek();
while (std::isxdigit(next))
if (next == 'x' || next == 'X')
{
_value += (char) istr.get();
next = istr.peek();
return finishHex(istr, next);
}
while (next == 'L' || next == 'l' || next == 'U' || next == 'u')
else if (next == 'b' || next == 'B')
{
_value += (char) istr.get();
next = istr.peek();
return finishBin(istr, next);
}
return;
}
while (next >= '0' && next <= '9')
while ((next >= '0' && next <= '9') || next == '\'')
{
_value += (char) istr.get();
next = istr.peek();
@@ -562,6 +557,56 @@ void NumberLiteralToken::finish(std::istream& istr)
}
if (next == 'e' || next == 'E')
{
_isFloat = true;
finishExp(istr, next);
}
finishSuffix(istr, next);
}
void NumberLiteralToken::finishHex(std::istream& istr, int next)
{
_value += (char) istr.get();
next = istr.peek();
while (std::isxdigit(next) || next == '\'')
{
_value += (char) istr.get();
next = istr.peek();
}
if (next == '.')
{
_isFloat = true;
_value += (char) istr.get();
next = istr.peek();
while (std::isxdigit(next) || next == '\'')
{
_value += (char) istr.get();
next = istr.peek();
}
}
if (next == 'p' || next == 'P')
{
finishExp(istr, next);
}
finishSuffix(istr, next);
}
void NumberLiteralToken::finishBin(std::istream& istr, int next)
{
_value += (char) istr.get();
next = istr.peek();
while (next == '0' || next == '1' || next == '\'')
{
_value += (char) istr.get();
next = istr.peek();
}
finishSuffix(istr, next);
}
void NumberLiteralToken::finishExp(std::istream& istr, int next)
{
_isFloat = true;
_value += (char) istr.get();
next = istr.peek();
@@ -583,7 +628,11 @@ void NumberLiteralToken::finish(std::istream& istr)
std::string s(1, (char) next);
syntaxError("digit", s);
}
}
}
void NumberLiteralToken::finishSuffix(std::istream& istr, int next)
{
if (_isFloat)
{
if (next == 'L' || next == 'l' || next == 'F' || next == 'f')
@@ -603,7 +652,6 @@ void NumberLiteralToken::finish(std::istream& istr)
int NumberLiteralToken::asInteger() const
{
return static_cast<int>(std::strtol(_value.c_str(), 0, 0));
}

View File

@@ -13,6 +13,8 @@
#include "CppUnit/TestSuite.h"
#include "Poco/CppParser/Utility.h"
#include "Poco/CppParser/Symbol.h"
#include "Poco/CppParser/CppToken.h"
#include <sstream>
#include <iostream>
@@ -33,6 +35,7 @@ std::string options("/I \"C:\\Program Files\\Microsoft Visual Studio 8\\VC\\INCL
"/C, /P, /TP");
std::string path("C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\IDE;C:\\Program Files\\Microsoft Visual Studio 8\\VC\\BIN;C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\Tools;;C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\Tools\\bin");
CppParserTest::CppParserTest(const std::string& name): CppUnit::TestCase(name)
{
}
@@ -55,7 +58,7 @@ void CppParserTest::testParseDir()
NameSpace::SymbolTable::const_iterator it = st.begin();
NameSpace::SymbolTable::const_iterator itEnd = st.end();
for (it; it != itEnd; ++it)
for (; it != itEnd; ++it)
{
std::cout << it->first << ": ";
Symbol* pSym = it->second;
@@ -113,6 +116,70 @@ void CppParserTest::testExtractName()
}
void CppParserTest::testNumberLiterals()
{
testNumberLiteral("123");
testNumberLiteral("0123");
testNumberLiteral("0x123");
testNumberLiteral("0XABC");
testNumberLiteral("0b010101");
testNumberLiteral("0B101010");
testNumberLiteral("123L");
testNumberLiteral("0123L");
testNumberLiteral("0x123L");
testNumberLiteral("0XABCL");
testNumberLiteral("0b010101L");
testNumberLiteral("0B101010L");
testNumberLiteral("123LL");
testNumberLiteral("0123LL");
testNumberLiteral("0x123LL");
testNumberLiteral("0XABCLL");
testNumberLiteral("0b010101LL");
testNumberLiteral("0B101010LL");
testNumberLiteral("123U");
testNumberLiteral("0123U");
testNumberLiteral("0x123U");
testNumberLiteral("0XABCU");
testNumberLiteral("0b010101U");
testNumberLiteral("0B101010U");
testNumberLiteral("123UL");
testNumberLiteral("0123UL");
testNumberLiteral("0x123UL");
testNumberLiteral("0XABCUL");
testNumberLiteral("0b010101UL");
testNumberLiteral("0B101010UL");
testNumberLiteral("1.23");
testNumberLiteral(".123");
testNumberLiteral("1.23e+3");
testNumberLiteral("1.23E-3");
testNumberLiteral("0x1fp1");
testNumberLiteral("0x1f.e3p+12");
testNumberLiteral("0x1f.e3p-12");
testNumberLiteral("123'456");
testNumberLiteral("1'234'567");
testNumberLiteral("0x1234'5678");
testNumberLiteral("0xFFFF'FFFFULL");
}
void CppParserTest::testNumberLiteral(const std::string& literal)
{
NumberLiteralToken tok;
std::istringstream istr(literal);
assertTrue (tok.start(istr.get(), istr));
tok.finish(istr);
assertEquals (tok.tokenString(), literal);
}
void CppParserTest::setUp()
{
}
@@ -129,6 +196,7 @@ CppUnit::Test* CppParserTest::suite()
CppUnit_addTest(pSuite, CppParserTest, testParseDir);
CppUnit_addTest(pSuite, CppParserTest, testExtractName);
CppUnit_addTest(pSuite, CppParserTest, testNumberLiterals);
return pSuite;
}

View File

@@ -26,12 +26,16 @@ public:
void testParseDir();
void testExtractName();
void testNumberLiterals();
void setUp();
void tearDown();
static CppUnit::Test* suite();
protected:
void testNumberLiteral(const std::string& literal);
private:
};