Working on generating string literals for inclusion in generated code.

This commit is contained in:
eelke 2018-09-21 11:41:20 +02:00
parent 0c3bb27e58
commit 092ed67d5e
8 changed files with 218 additions and 3 deletions

View file

@ -65,6 +65,7 @@ for (auto row: result) {
return t;
}
std::shared_ptr<LanguageConfig> buildPglabCppLanguageConfig()
{
auto config = std::make_shared<LanguageConfig>();

View file

@ -0,0 +1,8 @@
#include "StringEscapeRule.h"
/**
*/
QString convert(QStringRef in, ConvertToNumericEscape conversion, NumericEscapeFormat format, QString prefix)
{
return "";
}

View file

@ -0,0 +1,47 @@
#ifndef STRINGESCAPERULE_H
#define STRINGESCAPERULE_H
#include <QString>
#include <boost/optional.hpp>
enum class ConvertToNumericEscape {
Utf8, ///< Generates upto four escapes for 4 utf8 chars
Utf16, ///< Generates upto four escapes for 2 utf16 chars
Utf32, ///< Generates a single escape for the unicode codepoint
};
enum class NumericEscapeFormat {
Decimal,
HexUpper,
HexLower
};
class CharToNumericConversion {
public:
ConvertToNumericEscape m_toNumericEscape;
NumericEscapeFormat m_numericEscapeFormat;
int m_minNumericDigits, m_maxNumericDigits;
};
/** The basic method of applying a StringEscapeRule is to find all matches
* in the string for the m_matchRegex.
*
* if m_numericConversion is set then the match is taken out of the string and replaced
* with one or more numerical escapes.
* if no conversion is needed the match is simple prefixed with m_prefixWidth
*/
class StringEscapeRule {
public:
/** Regular expression that finds characters in the string that need replacing.
* Each character to replace should always generate one match.
*/
QString m_matchRegex;
/** As often a simple escape character like \ or a doubling scheme is used this
* field often provides enough flexibility.
*/
QString m_prefixWith;
// boost::optional<CharToNumericConversion> m_numericConversion;
};
#endif // STRINGESCAPERULE_H

View file

@ -0,0 +1,10 @@
#include "StringLiteralRules.h"
#include <QTextStream>
void StringLiteralRules::OutputString(QTextStream &stream, QString string_literal)
{
stream << m_stringStart;
stream << m_stringEnd;
}

View file

@ -0,0 +1,37 @@
#ifndef STRINGLITERALRULES_H
#define STRINGLITERALRULES_H
#include "StringEscapeRule.h"
#include <vector>
class QTextStream;
class StringLiteralRules {
public:
/** What should be put in front of the string to make it a string literal
*
* For instance a plain char string in C this would just be a double quote "
* But for a C++11 utf8 string literal it would be u8"
*/
QString m_stringStart;
/** Similar to stringStart
*/
QString m_stringEnd;
/** If true the assumption is that the newlines
* in the source string are not escaped so no line breaking is done.
* However we should still get a multiline string if the source was.
*
* When false the assumption is that we can split the string using stringEnd,
* stringStart and the concatOperator. There is a preference to split on whitespace.
*/
bool m_supportsMultiLine;
QString m_concatOperator;
std::vector<StringEscapeRule> m_escapeRules;
void OutputString(QTextStream &stream, QString string_literal);
};
#endif // STRINGLITERALRULES_H

View file

@ -61,7 +61,9 @@ codebuilder/DefaultConfigs.cpp \
codebuilder/TypeMappings.cpp \
codebuilder/IndentationConfig.cpp \
codebuilder/StructureTemplate.cpp \
FormatToStream.cpp
FormatToStream.cpp \
codebuilder/StringLiteralRules.cpp \
codebuilder/StringEscapeRule.cpp
HEADERS += \
Pglablib.h \
@ -105,7 +107,9 @@ codebuilder/TypeMappings.h \
codebuilder/IndentationConfig.h \
codebuilder/StructureTemplate.h \
FormatToStream.h \
codebuilder/ResultLoopTemplate.h
codebuilder/ResultLoopTemplate.h \
codebuilder/StringEscapeRule.h \
codebuilder/StringLiteralRules.h
unix {
target.path = /usr/lib

View file

@ -27,7 +27,8 @@ SOURCES += main.cpp \
tst_ParamJson.cpp \
tst_CodeBuilder.cpp \
tst_NameManglingRules.cpp \
tst_TypeMappings.cpp
tst_TypeMappings.cpp \
tst_Range.cpp
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../core/release/ -lcore
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../core/debug/ -lcore

View file

@ -0,0 +1,107 @@
#include <gtest/gtest.h>
#include <gmock/gmock-matchers.h>
#include "PrintTo_Qt.h"
template <typename T>
class Range {
public:
Range(T start, T end, bool incl_start = true, bool incl_end = false)
: m_start(start), m_end(end), m_inclStart(incl_start), m_inclEnd(incl_end)
{}
bool includes(T v) const
{
// assume chance is small that outcome hangs on the edge cases
// so we start with testing for definitly outside or definitly inside
if (v < m_start || v > m_end)
return false;
if (v > m_start && v < m_end)
return true;
// Now the edge cases
if (m_inclStart && v == m_start)
return true;
if (m_inclEnd && v == m_end)
return true;
return false;
}
bool overlap(Range<T> r) const
{
if ( (r.m_start < m_end || (m_incl))
&& r.m_end > m_start)
return true;
return false;
}
private:
T m_start;
T m_end;
bool m_inclStart;
bool m_inclEnd;
};
TEST(RangeTest, test_int_includes_before)
{
bool expected = false;
Range r(2, 5, true, false);
bool result = r.includes(1);
ASSERT_EQ(result, expected);
}
TEST(RangeTest, test_int_includes_start_excl)
{
bool expected = false;
Range r(2, 5, false, false);
bool result = r.includes(2);
ASSERT_EQ(result, expected);
}
TEST(RangeTest, test_int_includes_start_incl)
{
bool expected = true;
Range r(2, 5, true, false);
bool result = r.includes(2);
ASSERT_EQ(result, expected);
}
TEST(RangeTest, test_int_includes_mid)
{
bool expected = true;
Range r(2, 5, true, false);
bool result = r.includes(3);
ASSERT_EQ(result, expected);
}
TEST(RangeTest, test_int_includes_end_incl)
{
bool expected = true;
Range r(2, 5, true, true);
bool result = r.includes(5);
ASSERT_EQ(result, expected);
}
TEST(RangeTest, test_int_includes_end_excl)
{
bool expected = false;
Range r(2, 5, true, false);
bool result = r.includes(5);
ASSERT_EQ(result, expected);
}
TEST(RangeTest, test_int_includes_after)
{
bool expected = false;
Range r(2, 5, true, false);
bool result = r.includes(6);
ASSERT_EQ(result, expected);
}