blob: 6208c376262bc2469782ab1eecb25a0378e42485 [file] [log] [blame]
----------------------------------------------------------------------------
--
-- Copyright (C) 2014-2015 Ford Motor Company.
-- Contact: https://www.qt.io/licensing/
--
-- This file is part of the QtRemoteObjects module of the Qt Toolkit.
--
-- $QT_BEGIN_LICENSE:LGPL$
-- Commercial License Usage
-- Licensees holding valid commercial Qt licenses may use this file in
-- accordance with the commercial license agreement provided with the
-- Software or, alternatively, in accordance with the terms contained in
-- a written agreement between you and The Qt Company. For licensing terms
-- and conditions see https://www.qt.io/terms-conditions. For further
-- information use the contact form at https://www.qt.io/contact-us.
--
-- GNU Lesser General Public License Usage
-- Alternatively, this file may be used under the terms of the GNU Lesser
-- General Public License version 3 as published by the Free Software
-- Foundation and appearing in the file LICENSE.LGPL3 included in the
-- packaging of this file. Please review the following information to
-- ensure the GNU Lesser General Public License version 3 requirements
-- will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
--
-- GNU General Public License Usage
-- Alternatively, this file may be used under the terms of the GNU
-- General Public License version 2.0 or (at your option) the GNU General
-- Public license version 3 or any later version approved by the KDE Free
-- Qt Foundation. The licenses are as published by the Free Software
-- Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-- included in the packaging of this file. Please review the following
-- information to ensure the GNU General Public License requirements will
-- be met: https://www.gnu.org/licenses/gpl-2.0.html and
-- https://www.gnu.org/licenses/gpl-3.0.html.
--
-- $QT_END_LICENSE$
--
----------------------------------------------------------------------------
%parser rep_grammar
%decl repparser.h
%impl repparser.cpp
%token_prefix Token_
%token semicolon "[semicolon];"
%token class "[class]class[ \\t]+(?<name>[A-Za-z_][A-Za-z0-9_]+)[ \\t]*"
%token pod "[pod]POD[ \\t]*(?<name>[A-Za-z_][A-Za-z0-9_]+)[ \\t]*\\((?<types>[^\\)]*)\\);?[ \\t]*"
%token enum "[enum][ \\t]*ENUM[ \\t]+(?<name>[A-Za-z_][A-Za-z0-9_]*)[ \\t]*"
%token enum_param "[enum_param][ \\t]*(?<name>[A-Za-z_][A-Za-z0-9_]*)[ \\t]*(=[ \\t]*(?<value>-\\d+|0[xX][0-9A-Fa-f]+|\\d+))?[ \\t]*"
%token prop "[prop][ \\t]*PROP[ \\t]*\\((?<args>[^\\)]+)\\);?[ \\t]*"
%token use_enum "[use_enum]USE_ENUM[ \\t]*\\((?<name>[^\\)]*)\\);?[ \\t]*"
%token signal "[signal][ \\t]*SIGNAL[ \\t]*\\([ \\t]*(?<name>\\S+)[ \\t]*\\((?<args>[^\\)]*)\\)[ \\t]*\\);?[ \\t]*"
%token slot "[slot][ \\t]*SLOT[ \\t]*\\((?<type>[^\\(]*)\\((?<args>[^\\)]*)\\)[ \\t]*\\);?[ \\t]*"
%token model "[model][ \\t]*MODEL[ \\t]+(?<name>[A-Za-z_][A-Za-z0-9_]+)\\((?<args>[^\\)]+)\\)[ \\t]*;?[ \\t]*"
%token childrep "[childrep][ \\t]*CLASS[ \\t]+(?<name>[A-Za-z_][A-Za-z0-9_]+)\\((?<type>[^\\)]+)\\)[ \\t]*;?[ \\t]*"
%token start "[start][ \\t]*\\{[ \\t]*"
%token stop "[stop][ \\t]*\\};?[ \\t]*"
%token comma "[comma],"
%token comment "[comment](?<comment>[ \\t]*//[^\\n]*\\n)"
%token preprocessor_directive "[preprocessor_directive](?<preprocessor_directive>#[ \\t]*[^\\n]*\\n)"
%token newline "[newline](\\r)?\\n"
%start TopLevel
/:
#ifndef REPPARSER_H
#define REPPARSER_H
#include <rep_grammar_p.h>
#include <qregexparser.h>
#include <QStringList>
#include <QVector>
#include <QRegExp>
QT_BEGIN_NAMESPACE
class QIODevice;
/// A property of a Class declaration
struct ASTProperty
{
enum Modifier
{
Constant,
ReadOnly,
ReadPush,
ReadWrite,
SourceOnlySetter
};
ASTProperty();
ASTProperty(const QString &type, const QString &name, const QString &defaultValue, Modifier modifier, bool persisted,
bool isPointer=false);
QString type;
QString name;
QString defaultValue;
Modifier modifier;
bool persisted;
bool isPointer;
};
Q_DECLARE_TYPEINFO(ASTProperty, Q_MOVABLE_TYPE);
struct ASTDeclaration
{
enum VariableType {
None = 0,
Constant = 1,
Reference = 2,
};
Q_DECLARE_FLAGS(VariableTypes, VariableType)
ASTDeclaration(const QString &declarationType = QString(), const QString &declarationName = QString(), VariableTypes declarationVariableType = None)
: type(declarationType),
name(declarationName),
variableType(declarationVariableType)
{
}
QString asString(bool withName) const;
QString type;
QString name;
VariableTypes variableType;
};
Q_DECLARE_TYPEINFO(ASTDeclaration, Q_MOVABLE_TYPE);
struct ASTFunction
{
enum ParamsAsStringFormat {
Default,
Normalized
};
explicit ASTFunction(const QString &name = QString(), const QString &returnType = QLatin1String("void"));
QString paramsAsString(ParamsAsStringFormat format = Default) const;
QStringList paramNames() const;
QString returnType;
QString name;
QVector<ASTDeclaration> params;
};
Q_DECLARE_TYPEINFO(ASTFunction, Q_MOVABLE_TYPE);
struct ASTEnumParam
{
ASTEnumParam(const QString &paramName = QString(), int paramValue = 0)
: name(paramName),
value(paramValue)
{
}
QString asString() const;
QString name;
int value;
};
Q_DECLARE_TYPEINFO(ASTEnumParam, Q_MOVABLE_TYPE);
struct ASTEnum
{
explicit ASTEnum(const QString &name = QString());
QString name;
QVector<ASTEnumParam> params;
bool isSigned;
int max;
};
Q_DECLARE_TYPEINFO(ASTEnum, Q_MOVABLE_TYPE);
struct ASTModelRole
{
ASTModelRole(const QString &roleName = QString())
: name(roleName)
{
}
QString name;
};
Q_DECLARE_TYPEINFO(ASTModelRole, Q_MOVABLE_TYPE);
struct ASTModel
{
ASTModel(int index = -1) : propertyIndex(index) {}
QVector<ASTModelRole> roles;
int propertyIndex;
};
Q_DECLARE_TYPEINFO(ASTModel, Q_MOVABLE_TYPE);
/// A Class declaration
struct ASTClass
{
explicit ASTClass(const QString& name = QString());
bool isValid() const;
bool hasPointerObjects() const;
QString name;
QVector<ASTProperty> properties;
QVector<ASTFunction> signalsList;
QVector<ASTFunction> slotsList;
QVector<ASTEnum> enums;
bool hasPersisted;
QVector<ASTModel> modelMetadata;
QVector<int> subClassPropertyIndices;
};
Q_DECLARE_TYPEINFO(ASTClass, Q_MOVABLE_TYPE);
// The attribute of a POD
struct PODAttribute
{
explicit PODAttribute(const QString &type_ = QString(), const QString &name_ = QString())
: type(type_),
name(name_)
{}
QString type;
QString name;
};
Q_DECLARE_TYPEINFO(PODAttribute, Q_MOVABLE_TYPE);
// A POD declaration
struct POD
{
QString name;
QVector<PODAttribute> attributes;
};
Q_DECLARE_TYPEINFO(POD, Q_MOVABLE_TYPE);
// The AST representation of a .rep file
struct AST
{
QVector<ASTClass> classes;
QVector<POD> pods;
QVector<ASTEnum> enums;
QVector<QString> enumUses;
QStringList preprocessorDirectives;
};
Q_DECLARE_TYPEINFO(AST, Q_MOVABLE_TYPE);
class RepParser: public QRegexParser<RepParser, $table>
{
public:
explicit RepParser(QIODevice &outputDevice);
virtual ~RepParser() {}
bool parse() override { return QRegexParser<RepParser, $table>::parse(); }
void reset() override;
int nextToken();
bool consumeRule(int ruleno);
AST ast() const;
private:
struct TypeParser
{
void parseArguments(const QString &arguments);
void appendParams(ASTFunction &slot);
void appendPods(POD &pods);
void generateFunctionParameter(QString variableName, const QString &propertyType, int &variableNameIndex, ASTDeclaration::VariableTypes variableType);
//Type, Variable
QList<ASTDeclaration> arguments;
};
bool parseProperty(ASTClass &astClass, const QString &propertyDeclaration);
/// A helper function to parse modifier flag of property declaration
bool parseModifierFlag(const QString &flag, ASTProperty::Modifier &modifier, bool &persisted);
bool parseRoles(ASTModel &astModel, const QString &modelRoles);
AST m_ast;
ASTClass m_astClass;
ASTEnum m_astEnum;
int m_astEnumValue;
};
QT_END_NAMESPACE
#endif
:/
/.
#include "repparser.h"
#include <QDebug>
#include <QTextStream>
// for normalizeTypeInternal
#include <private/qmetaobject_p.h>
#include <private/qmetaobject_moc_p.h>
// Code copied from moc.cpp
// We cannot depend on QMetaObject::normalizedSignature,
// since repc is linked against Qt5Bootstrap (which doesn't offer QMetaObject) when cross-compiling
// Thus, just use internal API which is exported in private headers, as moc does
static QByteArray normalizeType(const QByteArray &ba, bool fixScope = false)
{
const char *s = ba.constData();
int len = ba.size();
char stackbuf[64];
char *buf = (len >= 64 ? new char[len + 1] : stackbuf);
char *d = buf;
char last = 0;
while (*s && is_space(*s))
s++;
while (*s) {
while (*s && !is_space(*s))
last = *d++ = *s++;
while (*s && is_space(*s))
s++;
if (*s && ((is_ident_char(*s) && is_ident_char(last))
|| ((*s == ':') && (last == '<')))) {
last = *d++ = ' ';
}
}
*d = '\0';
QByteArray result = normalizeTypeInternal(buf, d, fixScope);
if (buf != stackbuf)
delete [] buf;
return result;
}
ASTProperty::ASTProperty()
: modifier(ReadPush), persisted(false), isPointer(false)
{
}
ASTProperty::ASTProperty(const QString &type, const QString &name, const QString &defaultValue, Modifier modifier, bool persisted, bool isPointer)
: type(type), name(name), defaultValue(defaultValue), modifier(modifier), persisted(persisted), isPointer(isPointer)
{
}
QString ASTDeclaration::asString(bool withName) const
{
QString str;
if (variableType & ASTDeclaration::Constant)
str += QLatin1String("const ");
str += type;
if (variableType & ASTDeclaration::Reference)
str += QLatin1String(" &");
if (withName)
str += QString::fromLatin1(" %1").arg(name);
return str;
}
ASTFunction::ASTFunction(const QString &name, const QString &returnType)
: returnType(returnType), name(name)
{
}
QString ASTFunction::paramsAsString(ParamsAsStringFormat format) const
{
QString str;
for (const ASTDeclaration &param : params) {
QString paramStr = param.asString(format != Normalized);
if (format == Normalized) {
paramStr = QString::fromLatin1(::normalizeType(paramStr.toLatin1().constData()));
str += paramStr + QLatin1Char(',');
} else {
str += paramStr + QLatin1String(", ");
}
}
str.chop((format == Normalized ? 1 : 2)); // chop trailing ',' or ', '
return str;
}
QStringList ASTFunction::paramNames() const
{
QStringList names;
names.reserve(params.size());
for (const ASTDeclaration &param : params)
names << param.name;
return names;
}
ASTEnum::ASTEnum(const QString &name)
: name(name), isSigned(false), max(0)
{
}
ASTClass::ASTClass(const QString &name)
: name(name), hasPersisted(false)
{
}
bool ASTClass::isValid() const
{
return !name.isEmpty();
}
bool ASTClass::hasPointerObjects() const
{
int count = modelMetadata.size() + subClassPropertyIndices.size();
return count > 0;
}
RepParser::RepParser(QIODevice &outputDevice)
: QRegexParser(), m_astEnumValue(-1)
{
setBufferFromDevice(&outputDevice);
}
void RepParser::reset()
{
m_ast = AST();
m_astClass = ASTClass();
m_astEnum = ASTEnum();
//setDebug();
}
bool RepParser::parseModifierFlag(const QString &flag, ASTProperty::Modifier &modifier, bool &persisted)
{
QRegExp regex(QStringLiteral("\\s*,\\s*"));
QStringList flags = flag.split(regex);
persisted = flags.removeAll(QStringLiteral("PERSISTED")) > 0;
if (flags.length() == 0)
return true;
if (flags.length() > 1) {
// Only valid combination is "READONLY" and "CONSTANT"
if (flags.length() == 2 && flags.contains(QStringLiteral("READONLY")) &&
flags.contains(QStringLiteral("CONSTANT"))) {
// If we have READONLY and CONSTANT that means CONSTANT
modifier = ASTProperty::Constant;
return true;
} else {
setErrorString(QLatin1String("Invalid property declaration: combination not allowed (%1)").arg(flag));
return false;
}
}
const QString &f = flags.at(0);
if (f == QLatin1String("READONLY"))
modifier = ASTProperty::ReadOnly;
else if (f == QLatin1String("CONSTANT"))
modifier = ASTProperty::Constant;
else if (f == QLatin1String("READPUSH"))
modifier = ASTProperty::ReadPush;
else if (f == QLatin1String("READWRITE"))
modifier = ASTProperty::ReadWrite;
else if (f == QLatin1String("SOURCEONLYSETTER"))
modifier = ASTProperty::SourceOnlySetter;
else {
setErrorString(QLatin1String("Invalid property declaration: flag %1 is unknown").arg(flag));
return false;
}
return true;
}
QString stripArgs(const QString &arguments)
{
// This repc parser searches for the longest possible matches, which can be multiline.
// This method "cleans" the string input, removing comments and converting to a single
// line for subsequent parsing.
QStringList lines = arguments.split(QRegExp(QStringLiteral("\r?\n")));
for (auto & line : lines)
line.replace(QRegExp(QStringLiteral("//.*")),QString());
return lines.join(QString());
}
bool RepParser::parseProperty(ASTClass &astClass, const QString &propertyDeclaration)
{
QString input = stripArgs(propertyDeclaration).trimmed();
const QRegExp whitespace(QStringLiteral("\\s"));
QString propertyType;
QString propertyName;
QString propertyDefaultValue;
ASTProperty::Modifier propertyModifier = ASTProperty::ReadPush;
bool persisted = false;
// parse type declaration which could be a nested template as well
bool inTemplate = false;
int templateDepth = 0;
int nameIndex = -1;
for (int i = 0; i < input.size(); ++i) {
const QChar inputChar(input.at(i));
if (inputChar == QLatin1Char('<')) {
propertyType += inputChar;
inTemplate = true;
++templateDepth;
} else if (inputChar == QLatin1Char('>')) {
propertyType += inputChar;
--templateDepth;
if (templateDepth == 0)
inTemplate = false;
} else if (inputChar.isSpace()) {
if (!inTemplate) {
nameIndex = i;
break;
} else {
propertyType += inputChar;
}
} else {
propertyType += inputChar;
}
}
if (nameIndex == -1) {
setErrorString(QLatin1String("PROP: Invalid property declaration: %1").arg(propertyDeclaration));
return false;
}
// parse the name of the property
input = input.mid(nameIndex).trimmed();
const int equalSignIndex = input.indexOf(QLatin1Char('='));
if (equalSignIndex != -1) { // we have a default value
propertyName = input.left(equalSignIndex).trimmed();
input = input.mid(equalSignIndex + 1).trimmed();
const int lastQuoteIndex = input.lastIndexOf(QLatin1Char('"'));
if (lastQuoteIndex != -1) {
propertyDefaultValue = input.left(lastQuoteIndex + 1);
input = input.mid(lastQuoteIndex + 1);
}
const int whitespaceIndex = input.indexOf(whitespace);
if (whitespaceIndex == -1) { // no flag given
if (propertyDefaultValue.isEmpty())
propertyDefaultValue = input;
propertyModifier = ASTProperty::ReadPush;
} else { // flag given
if (propertyDefaultValue.isEmpty())
propertyDefaultValue = input.left(whitespaceIndex).trimmed();
const QString flag = input.mid(whitespaceIndex + 1).trimmed();
if (!parseModifierFlag(flag, propertyModifier, persisted))
return false;
}
} else { // there is no default value
const int whitespaceIndex = input.indexOf(whitespace);
if (whitespaceIndex == -1) { // no flag given
propertyName = input;
propertyModifier = ASTProperty::ReadPush;
} else { // flag given
propertyName = input.left(whitespaceIndex).trimmed();
const QString flag = input.mid(whitespaceIndex + 1).trimmed();
if (!parseModifierFlag(flag, propertyModifier, persisted))
return false;
}
}
astClass.properties << ASTProperty(propertyType, propertyName, propertyDefaultValue, propertyModifier, persisted);
if (persisted)
astClass.hasPersisted = true;
return true;
}
bool RepParser::parseRoles(ASTModel &astModel, const QString &modelRoles)
{
const QString input = modelRoles.trimmed();
if (input.isEmpty())
return true;
const QStringList roleStrings = input.split(QChar(QLatin1Char(',')));
for (auto role : roleStrings)
astModel.roles << ASTModelRole(role.trimmed());
return true;
}
AST RepParser::ast() const
{
return m_ast;
}
void RepParser::TypeParser::parseArguments(const QString &arguments)
{
const QString strippedArgs = stripArgs(arguments);
int templateDepth = 0;
bool inTemplate = false;
bool inVariable = false;
QString propertyType;
QString variableName;
ASTDeclaration::VariableTypes variableType = ASTDeclaration::None;
int variableNameIndex = 0;
for (int i = 0; i < strippedArgs.size(); ++i) {
const QChar inputChar(strippedArgs.at(i));
if (inputChar == QLatin1Char('<')) {
propertyType += inputChar;
inTemplate = true;
++templateDepth;
} else if (inputChar == QLatin1Char('>')) {
propertyType += inputChar;
--templateDepth;
if (templateDepth == 0)
inTemplate = false;
} else if (inputChar.isSpace()) {
if (inTemplate)
propertyType += inputChar;
else if (!propertyType.isEmpty()) {
if (propertyType == QLatin1String("const")) {
propertyType.clear();
variableType |= ASTDeclaration::Constant;
} else {
inVariable = true;
}
}
} else if (inputChar == QLatin1Char('&')) {
variableType |= ASTDeclaration::Reference;
} else if (inputChar == QLatin1Char(',')) {
if (!inTemplate) {
RepParser::TypeParser::generateFunctionParameter(variableName, propertyType, variableNameIndex, variableType);
propertyType.clear();
variableName.clear();
variableType = ASTDeclaration::None;
inVariable = false;
} else {
propertyType += inputChar;
}
} else {
if (inVariable)
variableName += inputChar;
else
propertyType += inputChar;
}
}
if (!propertyType.isEmpty()) {
RepParser::TypeParser::generateFunctionParameter(variableName, propertyType, variableNameIndex, variableType);
}
}
void RepParser::TypeParser::generateFunctionParameter(QString variableName, const QString &propertyType, int &variableNameIndex, ASTDeclaration::VariableTypes variableType)
{
if (!variableName.isEmpty())
variableName = variableName.trimmed();
else
variableName = QString::fromLatin1("__repc_variable_%1").arg(++variableNameIndex);
arguments.append(ASTDeclaration(propertyType, variableName, variableType));
}
void RepParser::TypeParser::appendParams(ASTFunction &slot)
{
for (const ASTDeclaration &arg : qAsConst(arguments))
slot.params << arg;
}
void RepParser::TypeParser::appendPods(POD &pods)
{
for (const ASTDeclaration &arg : qAsConst(arguments)) {
PODAttribute attr;
attr.type = arg.type;
attr.name = arg.name;
pods.attributes.append(qMove(attr));
}
}
bool RepParser::consumeRule(int ruleno)
{
if (isDebug()) {
qDebug() << "consumeRule:" << ruleno << spell[rule_info[rule_index[ruleno]]];
}
switch (ruleno) {
./
TopLevel: Types | Newlines Types | FileComments Types | Newlines FileComments Types;
FileComments: Comments;
Types: Type | Type Types;
Newlines: newline | newline Newlines;
Comments: Comment | Comment Comments;
Comment: comment | comment Newlines;
Type: PreprocessorDirective | PreprocessorDirective Newlines;
Type: Pod | Pod Newlines;
Type: Class;
Type: UseEnum | UseEnum Newlines;
Type: Comments | Comments Newlines;
Type: Enum;
/.
case $rule_number:
{
m_ast.enums.append(m_astEnum);
}
break;
./
Comma: comma | comma Newlines;
PreprocessorDirective: preprocessor_directive;
/.
case $rule_number:
{
m_ast.preprocessorDirectives.append(captured().value(QStringLiteral("preprocessor_directive")));
}
break;
./
Pod: pod;
/.
case $rule_number:
{
POD pod;
pod.name = captured().value(QStringLiteral("name")).trimmed();
const QString argString = captured().value(QLatin1String("types")).trimmed();
if (argString.isEmpty()) {
qWarning() << "[repc] - Ignoring POD with no data members. POD name: " << qPrintable(pod.name);
return true;
}
RepParser::TypeParser parseType;
parseType.parseArguments(argString);
parseType.appendPods(pod);
m_ast.pods.append(pod);
}
break;
./
Class: ClassStart Start ClassTypes Stop;
/.
case $rule_number:
./
Class: ClassStart Start Comments Stop;
/.
case $rule_number:
./
Class: ClassStart Start Stop;
/.
case $rule_number:
{
m_ast.classes.append(m_astClass);
}
break;
./
ClassTypes: ClassType | ClassType ClassTypes;
ClassType: DecoratedProp | DecoratedSignal | DecoratedSlot | DecoratedModel | DecoratedClass | Comments;
ClassType: Enum;
/.
case $rule_number:
{
m_astClass.enums.append(m_astEnum);
}
break;
./
DecoratedSlot: Slot | Comments Slot | Slot Newlines | Comments Slot Newlines;
DecoratedSignal: Signal | Comments Signal | Signal Newlines | Comments Signal Newlines;
DecoratedProp: Prop | Comments Prop | Prop Newlines | Comments Prop Newlines;
DecoratedModel: Model | Comments Model | Model Newlines | Comments Model Newlines;
DecoratedClass: ChildRep | Comments ChildRep | ChildRep Newlines | Comments ChildRep Newlines;
DecoratedEnumParam: EnumParam | Comments EnumParam | EnumParam Newlines | Comments EnumParam Newlines;
Start: start | Comments start | start Newlines | Comments start Newlines;
Stop: stop | stop Newlines;
Enum: EnumStart Start EnumParams Comments Stop;
Enum: EnumStart Start EnumParams Stop;
EnumStart: enum;
/.
case $rule_number:
{
const QString name = captured().value(QLatin1String("name"));
// new Class declaration
m_astEnum = ASTEnum(name);
m_astEnumValue = -1;
}
break;
./
EnumParams: DecoratedEnumParam | DecoratedEnumParam Comma EnumParams;
EnumParam: enum_param;
/.
case $rule_number:
{
ASTEnumParam param;
param.name = captured().value(QStringLiteral("name")).trimmed();
QString value = captured().value(QStringLiteral("value"));
value.remove(QLatin1Char('='));
value = value.trimmed();
if (value.isEmpty())
param.value = ++m_astEnumValue;
else if (value.startsWith(QLatin1String("0x"), Qt::CaseInsensitive))
param.value = m_astEnumValue = value.toInt(0,16);
else
param.value = m_astEnumValue = value.toInt();
if (param.value < 0) {
m_astEnum.isSigned = true;
if (m_astEnum.max < -param.value)
m_astEnum.max = -param.value;
} else if (m_astEnum.max < param.value)
m_astEnum.max = param.value;
m_astEnum.params << param;
}
break;
./
Prop: prop;
/.
case $rule_number:
{
const QString args = captured().value(QLatin1String("args"));
if (!parseProperty(m_astClass, args))
return false;
}
break;
./
Signal: signal;
/.
case $rule_number:
{
ASTFunction signal;
signal.name = captured().value(QLatin1String("name")).trimmed();
const QString argString = captured().value(QLatin1String("args")).trimmed();
RepParser::TypeParser parseType;
parseType.parseArguments(argString);
parseType.appendParams(signal);
m_astClass.signalsList << signal;
}
break;
./
Slot: slot;
/.
case $rule_number:
{
QString returnTypeAndName = captured().value(QLatin1String("type")).trimmed();
const QString argString = captured().value(QLatin1String("args")).trimmed();
// compat code with old SLOT declaration: "SLOT(func(...))"
const bool hasWhitespace = returnTypeAndName.indexOf(u' ') != -1;
if (!hasWhitespace) {
qWarning() << "[repc] - Adding 'void' for unspecified return type on" << qPrintable(returnTypeAndName);
returnTypeAndName.prepend(QLatin1String("void "));
}
const int startOfFunctionName = returnTypeAndName.lastIndexOf(u' ') + 1;
ASTFunction slot;
slot.returnType = returnTypeAndName.mid(0, startOfFunctionName-1);
slot.name = returnTypeAndName.mid(startOfFunctionName);
RepParser::TypeParser parseType;
parseType.parseArguments(argString);
parseType.appendParams(slot);
m_astClass.slotsList << slot;
}
break;
./
Model: model;
/.
case $rule_number:
{
ASTModel model(m_astClass.properties.size());
const QString name = captured().value(QLatin1String("name")).trimmed();
const QString argString = captured().value(QLatin1String("args")).trimmed();
if (!parseRoles(model, argString))
return false;
m_astClass.modelMetadata << model;
m_astClass.properties << ASTProperty(QStringLiteral("QAbstractItemModel"), name, QStringLiteral("nullptr"), ASTProperty::SourceOnlySetter, false, true);
}
break;
./
ChildRep: childrep;
/.
case $rule_number:
{
const QString name = captured().value(QLatin1String("name")).trimmed();
const QString type = captured().value(QLatin1String("type")).trimmed();
m_astClass.subClassPropertyIndices << m_astClass.properties.size();
m_astClass.properties << ASTProperty(type, name, QStringLiteral("nullptr"), ASTProperty::SourceOnlySetter, false, true);
}
break;
./
ClassStart: class Newlines;
/.
case $rule_number:
./
ClassStart: class;
/.
case $rule_number:
{
const QString name = captured().value(QLatin1String("name"));
// new Class declaration
m_astClass = ASTClass(name);
}
break;
./
UseEnum: use_enum;
/.
case $rule_number:
{
const QString name = captured().value(QLatin1String("name"));
m_ast.enumUses.append(name);
}
break;
./
--Error conditions/messages
ClassType: ClassStart;
/.
case $rule_number:
{
setErrorString(QStringLiteral("class: Cannot be nested"));
return false;
}
break;
./
ClassType: Pod;
/.
case $rule_number:
{
setErrorString(QStringLiteral("POD: Can only be used in global scope"));
return false;
}
break;
./
ClassType: UseEnum;
/.
case $rule_number:
{
setErrorString(QStringLiteral("USE_ENUM: Can only be used in global scope"));
return false;
}
break;
./
Type: Signal;
/.
case $rule_number:
{
setErrorString(QStringLiteral("SIGNAL: Can only be used in class scope"));
return false;
}
break;
./
Type: Slot;
/.
case $rule_number:
{
setErrorString(QStringLiteral("SLOT: Can only be used in class scope"));
return false;
}
break;
./
Type: Prop;
/.
case $rule_number:
{
setErrorString(QStringLiteral("PROP: Can only be used in class scope"));
return false;
}
break;
./
Type: Model;
/.
case $rule_number:
{
setErrorString(QStringLiteral("MODEL: Can only be used in class scope"));
return false;
}
break;
./
Type: ChildRep;
/.
case $rule_number:
{
setErrorString(QStringLiteral("CLASS: Can only be used in class scope"));
return false;
}
break;
./
/.
} // switch
return true;
}
./