Commit 0536fc67 authored by frmdstryr's avatar frmdstryr Committed by Sven Brauch
Browse files

Add 3.10 match syntax

parent 204c7f38
......@@ -345,11 +345,6 @@ DictionaryComprehensionAst::DictionaryComprehensionAst(Ast* parent): ExpressionA
}
EllipsisAst::EllipsisAst(Ast* parent): ExpressionAst(parent, Ast::EllipsisAstType)
{
}
ExceptionHandlerAst::ExceptionHandlerAst(Ast* parent): Ast(parent, Ast::ExceptionHandlerAstType), type(nullptr), name(nullptr)
{
......@@ -577,11 +572,6 @@ QString AwaitAst::dump() const
return r;
}
NameConstantAst::NameConstantAst(Ast* parent): ExpressionAst(parent, Ast::NameConstantAstType), value(Invalid)
{
}
QString NameConstantAst::dump() const
{
switch (value) {
......@@ -596,11 +586,6 @@ QString NameConstantAst::dump() const
}
}
NumberAst::NumberAst(Ast* parent): ExpressionAst(parent, Ast::NumberAstType), value(0), isInt(false)
{
}
QString NumberAst::dump() const
{
if (isInt)
......@@ -671,11 +656,6 @@ StatementAst::StatementAst(Ast* parent, AstType type): Ast(parent, type)
}
StringAst::StringAst(Ast* parent): ExpressionAst(parent, Ast::StringAstType), value(""), usedAsComment(false)
{
}
JoinedStringAst::JoinedStringAst(Ast* parent): ExpressionAst(parent, Ast::JoinedStringAstType), values()
{
......@@ -686,11 +666,6 @@ FormattedValueAst::FormattedValueAst(Ast* parent): ExpressionAst(parent, Ast::Fo
}
BytesAst::BytesAst(Ast* parent): ExpressionAst(parent, Ast::BytesAstType), value("")
{
}
SubscriptAst::SubscriptAst(Ast* parent): ExpressionAst(parent, Ast::SubscriptAstType), value(nullptr), slice(nullptr)
{
......@@ -851,5 +826,108 @@ QString AliasAst::dump() const
return r;
}
QString MatchAst::dump() const
{
QString r = "Match(";
dumpNode(r, "subject=", subject);
dumpList(r, ", cases=", cases);
r.append(")");
return r;
}
QString MatchCaseAst::dump() const
{
QString r = "MatchCase(";
dumpNode(r, "pattern=", pattern);
if (guard)
dumpNode(r, ", guard=", guard);
dumpList(r, ", body=", body);
r.append(")");
return r;
}
QString MatchValueAst::dump() const
{
QString r = "MatchValue(";
dumpNode(r, "value=", value);
r.append(")");
return r;
}
QString MatchSingletonAst::dump() const
{
QString r = "MatchSingleton(";
switch (value) {
case NameConstantAst::NameConstantTypes::True:
r.append("value=True");
break;
case NameConstantAst::NameConstantTypes::False:
r.append("value=False");
break;
case NameConstantAst::NameConstantTypes::None:
r.append("value=None");
break;
default:
r.append("value=Invalid");
}
r.append(")");
return r;
}
QString MatchSequenceAst::dump() const
{
QString r = "MatchSequence(";
dumpList(r, "patterns=", patterns);
r.append(")");
return r;
}
QString MatchMappingAst::dump() const
{
QString r = "MatchMapping(";
dumpList(r, "keys=", keys);
dumpList(r, ", patterns=", patterns);
dumpNode(r, ", rest=", rest);
r.append(")");
return r;
}
QString MatchClassAst::dump() const
{
QString r = "MatchClass(";
dumpNode(r, "cls=", cls);
dumpList(r, ", patterns=", patterns);
dumpNode(r, ", kwd_attrs=", kwdAttrs);
dumpList(r, ", kwd_patterns=", kwdPatterns);
r.append(")");
return r;
}
QString MatchStarAst::dump() const
{
QString r = "MatchStar(";
dumpNode(r, "name=", name);
r.append(")");
return r;
}
QString MatchAsAst::dump() const
{
QString r = "MatchAs(";
dumpNode(r, "name=", name);
if (pattern)
dumpNode(r, ", pattern=", pattern);
r.append(")");
return r;
}
QString MatchOrAst::dump() const
{
QString r = "MatchOr(";
dumpList(r, ", patterns=", patterns);
r.append(")");
return r;
}
}
......@@ -80,9 +80,12 @@ public:
AssertionAstType,
AugmentedAssignmentAstType,
AnnotationAssignmentAstType,
MatchAstType,
LastStatementType,
ExpressionAstType, // everything below is an expression
AwaitAstType,
ConstantAstType,
NameAstType,
NameConstantAstType,
CallAstType,
......@@ -116,6 +119,19 @@ public:
AssignmentExpressionAstType,
LastExpressionType, // keep this at the end of the expr ast list
// everything below is a pattern
MatchCaseAstType,
PatternAstType,
MatchValueAstType,
MatchSingletonAstType,
MatchSequenceAstType,
MatchMappingAstType,
MatchClassAstType,
MatchStarAstType,
MatchAsAstType,
MatchOrAstType,
LastPatternType,
CodeAstType,
ExceptionHandlerAstType,
AliasAstType, // for imports
......@@ -474,6 +490,12 @@ public:
ExpressionAst* value; // WARNING this is not set in most cases!
};
class KDEVPYTHONPARSER_EXPORT ConstantAst : public ExpressionAst {
public:
ConstantAst(Ast* parent, AstType type = Ast::ConstantAstType): ExpressionAst(parent, type) {}
// TODO: Python 3.8 + removed classes ast.Num, ast.Str, ast.Bytes, ast.NameConstant and ast.Ellipsis
};
class KDEVPYTHONPARSER_EXPORT AssignmentExpressionAst : public ExpressionAst {
public:
AssignmentExpressionAst(Ast* parent);
......@@ -625,19 +647,19 @@ public:
ExpressionAst* value;
};
class KDEVPYTHONPARSER_EXPORT NumberAst : public ExpressionAst {
class KDEVPYTHONPARSER_EXPORT NumberAst : public ConstantAst {
public:
NumberAst(Ast* parent);
long value; // only used for ints
bool isInt; // otherwise it's a float
NumberAst(Ast* parent) : ConstantAst(parent, Ast::NumberAstType) {}
long value = 0; // only used for ints
bool isInt = false; // otherwise it's a float
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT StringAst : public ExpressionAst {
class KDEVPYTHONPARSER_EXPORT StringAst : public ConstantAst {
public:
StringAst(Ast* parent);
QString value;
bool usedAsComment;
StringAst(Ast* parent) : ConstantAst(parent, Ast::StringAstType) {}
QString value = "";
bool usedAsComment = false;
QString dump() const override { return "Str('" + value + "')"; }
};
......@@ -655,10 +677,10 @@ public:
ExpressionAst* formatSpec;
};
class KDEVPYTHONPARSER_EXPORT BytesAst : public ExpressionAst {
class KDEVPYTHONPARSER_EXPORT BytesAst : public ConstantAst {
public:
BytesAst(Ast* parent);
QString value;
BytesAst(Ast* parent) : ConstantAst(parent, Ast::BytesAstType) {};
QString value = "";
};
class KDEVPYTHONPARSER_EXPORT YieldAst : public ExpressionAst {
......@@ -676,16 +698,16 @@ public:
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT NameConstantAst : public ExpressionAst {
class KDEVPYTHONPARSER_EXPORT NameConstantAst : public ConstantAst {
public:
NameConstantAst(Ast* parent);
NameConstantAst(Ast* parent) : ConstantAst(parent, Ast::NameConstantAstType) {}
enum NameConstantTypes {
False,
True,
None,
Invalid // should not happen
};
NameConstantTypes value;
NameConstantTypes value = Invalid;
QString dump() const override;
};
......@@ -741,9 +763,9 @@ public:
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT EllipsisAst : public ExpressionAst {
class KDEVPYTHONPARSER_EXPORT EllipsisAst : public ConstantAst {
public:
EllipsisAst(Ast* parent);
EllipsisAst(Ast* parent) : ConstantAst(parent, Ast::EllipsisAstType) {};
QString dump() const override { return "Ellipsis()"; }
};
......@@ -812,6 +834,95 @@ public:
QString dump() const override;
};
}
/** Match classes **/
class KDEVPYTHONPARSER_EXPORT PatternAst : public Ast {
public:
PatternAst(Ast* parent, AstType type = Ast::PatternAstType): Ast(parent, type) {};
};
class KDEVPYTHONPARSER_EXPORT MatchCaseAst : public Ast {
public:
MatchCaseAst(Ast* parent) : Ast(parent, Ast::MatchCaseAstType) {};
PatternAst* pattern = nullptr;
ExpressionAst* guard = nullptr;
QList<Ast*> body;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchAst : public Ast {
public:
MatchAst(Ast* parent) : Ast(parent, Ast::MatchAstType) {};
ExpressionAst* subject = nullptr;
QList<MatchCaseAst*> cases;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchValueAst : public PatternAst {
public:
MatchValueAst(Ast* parent): PatternAst(parent, Ast::MatchValueAstType) {};
ExpressionAst* value = nullptr;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchSingletonAst : public PatternAst {
public:
MatchSingletonAst(Ast* parent): PatternAst(parent, Ast::MatchSingletonAstType) {};
NameConstantAst::NameConstantTypes value = NameConstantAst::NameConstantTypes::Invalid;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchSequenceAst : public PatternAst {
public:
MatchSequenceAst(Ast* parent) : PatternAst(parent, Ast::MatchSequenceAstType) {};
QList<PatternAst*> patterns;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchMappingAst : public PatternAst {
public:
MatchMappingAst(Ast* parent) : PatternAst(parent, Ast::MatchMappingAstType) {};
QList<ExpressionAst*> keys;
Identifier *rest = nullptr;
QList<PatternAst*> patterns;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchClassAst : public PatternAst {
public:
MatchClassAst(Ast* parent): PatternAst(parent, Ast::MatchClassAstType) {};
ExpressionAst* cls = nullptr;
QList<PatternAst*> patterns;
Identifier *kwdAttrs = nullptr;
QList<PatternAst*> kwdPatterns;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchStarAst : public PatternAst {
public:
MatchStarAst(Ast* parent): PatternAst(parent, Ast::MatchStarAstType) {};
Identifier* name = nullptr;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchAsAst : public PatternAst {
public:
MatchAsAst(Ast* parent): PatternAst(parent, Ast::MatchAsAstType) {};
PatternAst* pattern = nullptr;
Identifier* name = nullptr;
QString dump() const override;
};
class KDEVPYTHONPARSER_EXPORT MatchOrAst : public PatternAst {
public:
MatchOrAst(Ast* parent): PatternAst(parent, Ast::MatchOrAstType) {};
QList<PatternAst*> patterns;
QString dump() const override;
};
} // end namespace Python
#endif
......@@ -172,6 +172,12 @@ Ast* AstTransformer::visitNode(PyObject* node, Ast* parent)
return visitExceptHandlerNode(node, parent);
if (PyObject_IsInstance(node, grammar.ast_slice))
return visitSliceNode(node, parent);
#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 10, 0)
if (PyObject_IsInstance(node, grammar.ast_match_case))
return visitMatchCaseNode(node, parent);
if (PyObject_IsInstance(node, grammar.ast_pattern))
return visitPatternNode(node, parent);
#endif
if (PyObject_IsInstance(node, grammar.ast_mod))
return visitModuleNode(node, parent);
qWarning() << "Unsupported AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
......@@ -708,7 +714,7 @@ Ast* AstTransformer::visitExprNode(PyObject* node, Ast* parent)
PyObjectRef value = getattr<PyObjectRef>(node, "value");
if (value == Py_None)
v->value = NameConstantAst::None;
else if (value == Py_false)
else if (value == Py_False)
v->value = NameConstantAst::False;
else
v->value = NameConstantAst::True;
......@@ -1198,6 +1204,20 @@ Ast* AstTransformer::visitStmtNode(PyObject* node, Ast* parent)
NonlocalAst* v = new NonlocalAst(parent);
result = v;
}
#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 10, 0)
else if (PyObject_IsInstance(node, grammar.ast_Match)) {
MatchAst* v = new MatchAst(parent);
{
PyObjectRef subject = getattr<PyObjectRef>(node, "subject");
v->subject = static_cast<ExpressionAst*>(visitExprNode(subject, v));
}
{
PyObjectRef cases = getattr<PyObjectRef>(node, "cases");
v->cases = visitNodeList<MatchCaseAst>(cases, v);
}
result = v;
}
#endif
else {
qWarning() << "Unsupported _stmt AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
Q_ASSERT(false);
......@@ -1250,6 +1270,129 @@ Ast* AstTransformer::visitWithItemNode(PyObject* node, Ast* parent)
return v;
}
#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 10, 0)
Ast* AstTransformer::visitMatchCaseNode(PyObject* node, Ast* parent)
{
if ( !node || node == Py_None ) return nullptr;
// qDebug() << "visit match case: " << PyUnicodeObjectToQString(PyObject_Str(node));
Q_ASSERT(PyObject_IsInstance(node, grammar.ast_match_case));
MatchCaseAst* v = new MatchCaseAst(parent);
{
PyObjectRef pattern = getattr<PyObjectRef>(node, "pattern");
v->pattern = static_cast<PatternAst*>(visitPatternNode(pattern, v));
}
{
PyObjectRef guard = getattr<PyObjectRef>(node, "guard");
v->guard = static_cast<ExpressionAst*>(visitExprNode(guard, v));
}
{
PyObjectRef body = getattr<PyObjectRef>(node, "body");
v->body = visitNodeList<Ast>(body, v);
}
return v;
}
Ast* AstTransformer::visitPatternNode(PyObject* node, Ast* parent)
{
if ( !node || node == Py_None ) return nullptr;
// qDebug() << "visit pattern: " << PyUnicodeObjectToQString(PyObject_Str(node));
Q_ASSERT(PyObject_IsInstance(node, grammar.ast_pattern));
Ast* result = nullptr;
if (PyObject_IsInstance(node, grammar.ast_MatchValue)) {
MatchValueAst* v = new MatchValueAst(parent);
PyObjectRef value = getattr<PyObjectRef>(node, "value");
v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
result = v;
}
else if (PyObject_IsInstance(node, grammar.ast_MatchSingleton)) {
MatchSingletonAst* v = new MatchSingletonAst(parent);
{
PyObjectRef value = getattr<PyObjectRef>(node, "value");
if (value == Py_None)
v->value = NameConstantAst::None;
else if (value == Py_False)
v->value = NameConstantAst::False;
else
v->value = NameConstantAst::True;
}
result = v;
}
else if (PyObject_IsInstance(node, grammar.ast_MatchSequence)) {
MatchSequenceAst* v = new MatchSequenceAst(parent);
PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
v->patterns = visitNodeList<PatternAst>(patterns, v);
result = v;
}
else if (PyObject_IsInstance(node, grammar.ast_MatchMapping)) {
MatchMappingAst* v = new MatchMappingAst(parent);
{
PyObjectRef keys = getattr<PyObjectRef>(node, "keys");
v->keys = visitNodeList<ExpressionAst>(keys, v);
}
{
QString rest = getattr<QString>(node, "rest");
v->rest = rest.size() ? new Python::Identifier(rest) : nullptr;
}
{
PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
v->patterns = visitNodeList<PatternAst>(patterns, v);
}
result = v;
}
else if (PyObject_IsInstance(node, grammar.ast_MatchClass)) {
MatchClassAst* v = new MatchClassAst(parent);
{
PyObjectRef cls = getattr<PyObjectRef>(node, "cls");
v->cls = static_cast<ExpressionAst*>(visitExprNode(cls, v));
}
{
PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
v->patterns = visitNodeList<PatternAst>(patterns, v);
}
{
QString kwd_attrs = getattr<QString>(node, "kwd_attrs");
v->kwdAttrs = kwd_attrs.size() ? new Python::Identifier(kwd_attrs) : nullptr;
}
{
PyObjectRef kwd_patterns = getattr<PyObjectRef>(node, "kwd_patterns");
v->kwdPatterns = visitNodeList<PatternAst>(kwd_patterns, v);
}
result = v;
}
else if (PyObject_IsInstance(node, grammar.ast_MatchStar)) {
MatchStarAst* v = new MatchStarAst(parent);
QString name = getattr<QString>(node, "name");
v->name = name.size() ? new Python::Identifier(name) : nullptr;
result = v;
}
else if (PyObject_IsInstance(node, grammar.ast_MatchAs)) {
MatchAsAst* v = new MatchAsAst(parent);
{
PyObjectRef pattern = getattr<PyObjectRef>(node, "pattern");
v->pattern = static_cast<PatternAst*>(visitPatternNode(pattern, v));
}
{
QString name = getattr<QString>(node, "name");
v->name = name.size() ? new Python::Identifier(name) : nullptr;
}
result = v;
}
else if (PyObject_IsInstance(node, grammar.ast_MatchOr)) {
MatchOrAst* v = new MatchOrAst(parent);
{
PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
v->patterns = visitNodeList<PatternAst>(patterns, v);
}
result = v;
}
else {
qWarning() << "Unsupported pattern AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
Q_ASSERT(false);
}
if ( ! result ) return nullptr;
updateRanges(result);
return result;
}
#endif
void AstTransformer::updateRanges(Ast* result)
{
......
......@@ -58,7 +58,10 @@ public:
Ast* visitAliasNode(PyObject* node, Ast* parent);
Ast* visitWithItemNode(PyObject* node, Ast* parent);
Ast* visitSliceNode(PyObject* node, Ast* parent);
#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 10, 0)
Ast* visitMatchCaseNode(PyObject* node, Ast* parent);
Ast* visitPatternNode(PyObject* node, Ast* parent);
#endif
void updateRanges(Ast* result);
};
......
......@@ -85,11 +85,24 @@ void AstVisitor::visitNode(Ast* node)
case Ast::ExpressionAstType: this->visitExpression(static_cast<ExpressionAst*>(node)); break;
case Ast::YieldFromAstType: this->visitYieldFrom(static_cast<YieldFromAst*>(node)); break;
case Ast::WithItemAstType: this->visitWithItem(static_cast<WithItemAst*>(node)); break;
case Ast::MatchAstType: this->visitMatch(static_cast<MatchAst*>(node)); break;
case Ast::MatchCaseAstType: this->visitMatchCase(static_cast<MatchCaseAst*>(node)); break;
case Ast::MatchValueAstType: this->visitMatchValue(static_cast<MatchValueAst*>(node)); break;
case Ast::MatchSingletonAstType: this->visitMatchSingleton(static_cast<MatchSingletonAst*>(node)); break;
case Ast::MatchSequenceAstType: this->visitMatchSequence(static_cast<MatchSequenceAst*>(node)); break;
case Ast::MatchMappingAstType: this->visitMatchMapping(static_cast<MatchMappingAst*>(node)); break;
case Ast::MatchClassAstType: this->visitMatchClass(static_cast<MatchClassAst*>(node)); break;
case Ast::MatchStarAstType: this->visitMatchStar(static_cast<MatchStarAst*>(node)); break;
case Ast::MatchAsAstType: this->visitMatchAs(static_cast<MatchAsAst*>(node)); break;
case Ast::MatchOrAstType: this->visitMatchOr(static_cast<MatchOrAst*>(node)); break;
case Ast::IdentifierAstType: break;
case Ast::StatementAstType: break;
case Ast::ConstantAstType: break;
case Ast::PatternAstType: break;
case Ast::LastAstType: Q_ASSERT(false); break;
case Ast::LastStatementType: Q_ASSERT(false); break;
case Ast::LastExpressionType: Q_ASSERT(false); break;
case Ast::LastPatternType: Q_ASSERT(false); break;
}
}
......
......@@ -98,6 +98,16 @@ public:
virtual void visitExceptionHandler(ExceptionHandlerAst* node) { Q_UNUSED(node); };
virtual void visitAlias(AliasAst* node) { Q_UNUSED(node); };
virtual void visitWithItem(WithItemAst* node) { Q_UNUSED(node); };
virtual void visitMatch(MatchAst* node) { Q_UNUSED(node); };
virtual void visitMatchCase(MatchCaseAst* node) { Q_UNUSED(node); };
virtual void visitMatchValue(MatchValueAst* node) { Q_UNUSED(node); };
virtual void visitMatchSingleton(MatchSingletonAst* node) { Q_UNUSED(node); };
virtual void visitMatchSequence(MatchSequenceAst* node) { Q_UNUSED(node); };
virtual void visitMatchMapping(MatchMappingAst* node) { Q_UNUSED(node); };
virtual void visitMatchClass(MatchClassAst* node) { Q_UNUSED(node); };
virtual void visitMatchStar(MatchStarAst* node) { Q_UNUSED(node); };
virtual void visitMatchAs(MatchAsAst* node) { Q_UNUSED(node); };
virtual void visitMatchOr(MatchOrAst* node) { Q_UNUSED(node); };
};
}
......