Commit 32da972c authored by ussrhero's avatar ussrhero

const expression parser refactored

parent 2b5d7dbe
This diff is collapsed.
This diff is collapsed.
......@@ -7,6 +7,7 @@
#include "strconvert.h"
#include "typeparser.h"
#include "exprparser.h"
namespace kdlib {
......@@ -37,11 +38,13 @@ public:
class UnMinusOperation : public UnaryOperation
{
public:
TypedValue getResult(const TypedValue& val) override;
};
class UnPlusOperation : public UnaryOperation
{
public:
TypedValue getResult(const TypedValue& val) override
{
return val;
......@@ -50,6 +53,7 @@ class UnPlusOperation : public UnaryOperation
class DerefOperation : public UnaryOperation
{
public:
TypedValue getResult(const TypedValue& val) override
{
TypedValue v = val;
......@@ -60,6 +64,7 @@ class DerefOperation : public UnaryOperation
class RefOperation : public UnaryOperation
{
public:
TypedValue getResult(const TypedValue& val) override
{
return makePointer(val.getType(), val.getAddress());
......@@ -68,16 +73,19 @@ class RefOperation : public UnaryOperation
class BitwiseNotOperation : public UnaryOperation
{
public:
TypedValue getResult(const TypedValue& val) override;
};
class BooleanNotOperation : public UnaryOperation
{
public:
TypedValue getResult(const TypedValue& val) override;
};
class PreIncrementOperation : public UnaryOperation
{
public:
TypedValue getResult(const TypedValue& val) override
{
return val.getValue() + 1;
......@@ -1372,6 +1380,8 @@ public:
private:
static TypedValue getResultForMatcher(const parser::ConstExpressionMatcher& matcher);
ScopePtr m_scope;
TypeInfoProviderPtr m_typeInfoProvider;
TokenRange m_tokenRange;
......
......@@ -6,40 +6,247 @@ namespace kdlib {
namespace parser {
class ConstExpressionMatcher;
class OperandMatcher : public Matcher
class UnaryRvalueOperation : public Matcher
{
public:
auto match(const TokenRange& matchRange)
{
return matchResult = numericMatcher.match(matchRange);
return matchResult = any_of(
m_minusMatcher,
m_plusMatcher,
m_exclaimMatcher,
m_tildeMatcher
).match(matchRange);
}
const auto& getNumeric() const
bool isMinus() const
{
return numericMatcher;
return m_minusMatcher.getMatchResult().isMatched();
}
bool isPlus() const
{
return m_plusMatcher.getMatchResult().isMatched();
}
bool isExclaim() const
{
return m_exclaimMatcher.getMatchResult().isMatched();
}
bool isTilde() const
{
return m_tildeMatcher.getMatchResult().isMatched();
}
private:
NumericMatcher numericMatcher;
Is<clang::tok::minus> m_minusMatcher;
Is<clang::tok::plus> m_plusMatcher;
Is<clang::tok::exclaim> m_exclaimMatcher;
Is<clang::tok::tilde> m_tildeMatcher;
};
class NestedExprMatcher : public Matcher
{
public:
class UnaryRvalueOperation : public Matcher
MatchResult match(const TokenRange& matchRange);
const auto& getExprMatcher() const
{
return *exprMatcher;
}
private:
std::unique_ptr<ConstExpressionMatcher> exprMatcher;
};
class OperandMatcher : public Matcher
{
public:
auto match(const TokenRange& matchRange)
{
auto mather = any_of(
all_of(
opt(rep(unaryOperations, unaryOperations)),
numericMatcher),
nestedExprMatcher);
return matchResult = mather.match(matchRange);
}
bool isNumericMatcher() const {
return numericMatcher.getMatchResult().isMatched();
}
const auto& getNumericMatcher() const {
return numericMatcher;
}
bool isNestedExpression() const
{
return nestedExprMatcher.getMatchResult().isMatched();
}
const auto& getNestedExpressionMatcher() const
{
return nestedExprMatcher;
}
const auto& getUnaryOperations() const
{
return unaryOperations;
}
private:
NestedExprMatcher nestedExprMatcher;
NumericMatcher numericMatcher;
ListMatcher<UnaryRvalueOperation> unaryOperations;
};
class BinaryOperationMatcher : public Matcher
{
public:
auto match(const TokenRange& matchRange)
{
return matchResult = any_of(
Is<clang::tok::minus>(),
Is<clang::tok::plus>(),
Is<clang::tok::exclaim>(),
Is<clang::tok::tilde>()
).match(matchRange);
auto matcher = any_of(
m_minusMatcher,
m_plusMatcher,
m_starMatcher,
m_slashMatcher,
m_percentMatcher,
m_greatergreaterMatcher,
m_lesslessMatcher,
m_ampMatcher,
m_pipeMatcher,
m_caretMatcher,
m_equalequalMatcher,
m_exclaimequalMatcher,
m_lessMatcher,
m_lessequalMatcher,
m_greaterMatcher,
m_greaterEqualMatcher,
m_pipepipeMatcher,
m_ampampMatcher
);
return matchResult = matcher.match(matchRange);
}
bool isAdd() const
{
return m_plusMatcher.getMatchResult().isMatched();
}
bool isMinus() const
{
return m_minusMatcher.getMatchResult().isMatched();
}
bool isStar() const
{
return m_starMatcher.getMatchResult().isMatched();
}
bool isSlash() const
{
return m_slashMatcher.getMatchResult().isMatched();
}
bool isPercent() const
{
return m_percentMatcher.getMatchResult().isMatched();
}
bool isGreaterGreater() const
{
return m_greatergreaterMatcher.getMatchResult().isMatched();
}
bool isLessLess() const
{
return m_lesslessMatcher.getMatchResult().isMatched();
}
bool isAmp() const
{
return m_ampMatcher.getMatchResult().isMatched();
}
bool isPipe() const
{
return m_pipeMatcher.getMatchResult().isMatched();
}
bool isCaret() const
{
return m_caretMatcher.getMatchResult().isMatched();
}
bool isEqualequal() const
{
return m_equalequalMatcher.getMatchResult().isMatched();
}
bool isExclaimequal() const
{
return m_exclaimequalMatcher.getMatchResult().isMatched();
}
bool isLess() const
{
return m_lessMatcher.getMatchResult().isMatched();
}
bool isLessEqual() const
{
return m_lessequalMatcher.getMatchResult().isMatched();
}
bool isGreater() const
{
return m_greaterMatcher.getMatchResult().isMatched();
}
bool isGreaterEqual() const
{
return m_greaterEqualMatcher.getMatchResult().isMatched();
}
bool isPipePipe() const
{
return m_pipepipeMatcher.getMatchResult().isMatched();
}
bool isAmpAmp() const
{
return m_ampampMatcher.getMatchResult().isMatched();
}
private:
Is<clang::tok::minus> m_minusMatcher;
Is<clang::tok::plus> m_plusMatcher;
Is<clang::tok::star> m_starMatcher;
Is<clang::tok::slash> m_slashMatcher;
Is<clang::tok::percent> m_percentMatcher;
Is<clang::tok::greatergreater> m_greatergreaterMatcher;
Is<clang::tok::lessless> m_lesslessMatcher;
Is<clang::tok::amp> m_ampMatcher;
Is<clang::tok::pipe> m_pipeMatcher;
Is<clang::tok::caret> m_caretMatcher;
Is<clang::tok::equalequal> m_equalequalMatcher;
Is<clang::tok::exclaimequal> m_exclaimequalMatcher;
Is<clang::tok::less> m_lessMatcher;
Is<clang::tok::lessequal> m_lessequalMatcher;
Is<clang::tok::greater> m_greaterMatcher;
Is<clang::tok::greaterequal> m_greaterEqualMatcher;
Is<clang::tok::pipepipe> m_pipepipeMatcher;
Is<clang::tok::ampamp> m_ampampMatcher;
};
class ConstExpressionMatcher : public Matcher
......@@ -47,27 +254,43 @@ class ConstExpressionMatcher : public Matcher
public:
auto match(const TokenRange& matchRange)
{
auto matcher = all_of(opt(rep(leftOps, leftOps)), operandMatcher);
matchResult = matcher.match(matchRange);
return matchResult;
auto matcher = all_of(
cap(operandMatcher, operandMatcher),
opt(rep(
all_of(operationMatcher, operandMatcher), operationMatcher, operandMatcher
))
);
return matchResult = matcher.match(matchRange);
}
const auto& getOperand() const
const auto& getOperationMatchers() const
{
return operandMatcher;
return operationMatcher;
}
const auto& getLeftOps() const
const auto& getOperandMatchers() const
{
return leftOps;
return operandMatcher;
}
private:
OperandMatcher operandMatcher;
ListMatcher<UnaryRvalueOperation> leftOps;
ListMatcher<OperandMatcher> operandMatcher;
ListMatcher<BinaryOperationMatcher> operationMatcher;
};
inline
MatchResult NestedExprMatcher::match(const TokenRange& matchRange)
{
exprMatcher = std::make_unique<ConstExpressionMatcher>();
auto matcher = all_of(
token_is(clang::tok::l_paren),
*exprMatcher.get(),
token_is(clang::tok::r_paren)
);
return matchResult = matcher.match(matchRange);
}
}
}
......@@ -323,7 +323,7 @@ public:
{}
void complete() {
capture.complete()
capture.complete();
CaptureList<Ts...>::complete();
}
......@@ -446,6 +446,11 @@ public:
return matcherList.rend();
}
bool empty() const
{
return begin() == end();
}
void complete()
{
if (currentMatcher.getMatchResult().isMatched())
......@@ -473,9 +478,34 @@ private:
class NumericMatcher : public Matcher
{
public:
MatchResult match(const TokenRange& matchRange)
{
return matchResult = Is<clang::tok::numeric_constant>().match(matchRange);
auto res = Is<clang::tok::numeric_constant>().match(matchRange);
if (res.isMatched())
return matchResult = res;
res = any_of(
token_is(clang::tok::char_constant),
token_is(clang::tok::wide_char_constant)
).match(matchRange);
if (res.isMatched())
return matchResult = res;
res = Is<clang::tok::identifier>().match(matchRange);
if (!res.isMatched())
return matchResult = MatchResult();
auto &token = *res.begin();
std::string strVal(token.getIdentifierInfo()->getNameStart(), token.getLength());
if (strVal == "false" || strVal == "true")
return matchResult = res;
return matchResult = MatchResult();
}
};
......
#pragma once
#include "parser.h"
#include "exprparser.h"
namespace kdlib {
bool isBaseTypeKeyWord(const clang::Token& token);
bool isStandardIntType(const clang::Token& token);
bool isTrueFalse(const clang::Token& token);
std::string getIdentifier(const clang::Token& token);
bool isOperationToken(const clang::Token& token);
......@@ -219,8 +221,10 @@ public:
if (matchRange.first == matchRange.second)
return matchResult = MatchResult();
if (isStandardIntType(*matchRange.first) || isBaseTypeKeyWord(*matchRange.first))
return matchResult = MatchResult();
if (isStandardIntType(*matchRange.first)
|| isBaseTypeKeyWord(*matchRange.first)
|| isTrueFalse(*matchRange.first) )
return matchResult = MatchResult();
auto matcher = all_of(nameMatcher, opt(rep(namespacesMatchers, namespacesMatchers)));
......@@ -244,35 +248,6 @@ private:
ListMatcher<NamespaceMatcher> namespacesMatchers;
};
class TemplateNumericArgMatcher : public Matcher
{
public:
MatchResult match(const TokenRange& matchRange)
{
auto& beg = matchRange.first;
auto cur = beg;
for (; cur != matchRange.second; cur++)
{
if ((*cur).is(clang::tok::numeric_constant))
continue;
if (isOperationToken(*cur))
continue;
break;
}
if ( cur != beg )
return matchResult = MatchResult(std::make_pair(beg, cur));
return matchResult = MatchResult();
}
};
class TypeMatcher;
class TemplateArgMatcher : public Matcher
......@@ -285,22 +260,21 @@ public:
const TypeMatcher& getTypeMatcher() const;
bool isNumeric() const
bool isExpression() const
{
return numericMatcher.getMatchResult().isMatched();
return exprMatcher.getMatchResult().isMatched();
}
const auto& getNumericMatcher() const
const auto& getExpressionMatcher() const
{
return numericMatcher;
return exprMatcher;
}
private:
std::unique_ptr<TypeMatcher> typeMatcher;
TemplateNumericArgMatcher numericMatcher;
ConstExpressionMatcher exprMatcher;
};
class TemplateArgsMatcher : public Matcher
......@@ -322,7 +296,6 @@ public:
}
private:
ListMatcher<TemplateArgMatcher> argsMatchers;
};
......@@ -409,10 +382,7 @@ private:
ListMatcher<TemplateArgMatcher> argsMatchers1;
ListMatcher<TemplateArgMatcher> argsMatchers2;
//TemplateArgsMatcher templateArgsMatcher1;
CustomNameMatcher nestedTemplateName;
//TemplateArgsMatcher templateArgsMatcher2;
};
......@@ -555,7 +525,11 @@ inline
MatchResult TemplateArgMatcher::match(const TokenRange& matchRange)
{
typeMatcher = std::make_unique<TypeMatcher>();
return matchResult = any_of(*typeMatcher.get(), numericMatcher).match(matchRange);
auto matcher = any_of(
exprMatcher,
*typeMatcher.get()
);
return matchResult = matcher.match(matchRange);
}
inline
......
......@@ -712,7 +712,7 @@ NumVariant TypedVarBase::getValue() const
return NumVariant( m_varData->readDouble() );
if ( m_typeInfo->getName() == L"Bool" )
return NumVariant( m_varData->readByte() );
return NumVariant( 0 != m_varData->readByte() );
if ( m_typeInfo->getName() == L"Hresult" )
return NumVariant( m_varData->readDWord() );
......
......@@ -75,6 +75,12 @@ TEST(ExprEval, NumberExpression)
EXPECT_THROW(evalExpr(L"5/"), DbgException);
}
TEST(ExprEval, DivisionError)
{
EXPECT_THROW(evalExpr("5/0"), DbgException);
EXPECT_THROW(evalExpr("5/0.0"), DbgException);
}
TEST(ExprEval, UnMinus)
{
EXPECT_EQ(-2 + 3, evalExpr(L"-2 + 3"));
......
......@@ -259,10 +259,12 @@ TEST(TypeEvalTest, TemplateNumeric)
TestStruct0<-4> val3; \
TestStruct0<true> val4; \
TestStruct1<2, 0xFFFF> val5; \
TestStruct0<'a'> val6; \
";
TypeInfoProviderPtr typeProvider = getTypeInfoProviderFromSource(sourceCode);
EXPECT_NO_THROW(evalType("TestStruct0<'a'>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct0<0x4>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct0<-4>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct1<2,0xFFFF>", typeProvider));
......@@ -348,6 +350,61 @@ TEST(TypeEvalTest, TemplateConstExpr)
EXPECT_NO_THROW(evalType("TestStruct<~0xFFFFFFFF>", typeProvider));
}
TEST(TypeEvalTest, TemplateConstExpr2)
{
static const char sourceCode[] = " \
template<int> \
struct TestStruct { \
}; \
TestStruct<10> testVal1; \
";
TypeInfoProviderPtr typeProvider = getTypeInfoProviderFromSource(sourceCode);
EXPECT_NO_THROW(evalType("TestStruct<5+5>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<15-5>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<2+3+5>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<(10-5)+5>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<5+(10-(2+3))>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<(10-5)*2>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<20/2>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<120%11>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<5<<1>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<20>>1>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<11 & 0xFE>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<0x2|8>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<0x18 ^ 0x12>", typeProvider));
EXPECT_THROW(evalType("TestStruct0<5+(10-(2+3)>", typeProvider), TypeException);
EXPECT_THROW(evalType("TestStruct0<1/0>", typeProvider), TypeException);
}
TEST(TypeEvalTest, TemplateConstExpr3)
{
static const char sourceCode[] = " \
template<bool> \
struct TestStruct { \
}; \
TestStruct<true> testVal1; \
TestStruct<false> testVal2; \
";
TypeInfoProviderPtr typeProvider = getTypeInfoProviderFromSource(sourceCode);
EXPECT_NO_THROW(evalType("TestStruct<true>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<false>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<1==1>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<1!=0>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<1<2>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<1<=2>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<1>2>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<true>=false>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<true || 0>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<0x11 && 1>", typeProvider));
EXPECT_THROW(evalType("TestStruct0<5&&&5>", typeProvider), TypeException);
}
TEST(TypeEvalTest, TemplateClose)
{
static const char sourceCode[] = " \
......@@ -368,4 +425,5 @@ TEST(TypeEvalTest, TemplateClose)
EXPECT_NO_THROW(evalType("TestStruct<int,TestStruct<int,TestStruct<int,int>>>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<int,TestStruct<int,TestStruct<int,int>> >", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<int,TestStruct<int,TestStruct<int,int> >>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<int,TestStruct<int,TestStruct<int,int> >>", typeProvider));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment