diff --git a/sonar-keyware-plugins-cxx/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java b/sonar-keyware-plugins-cxx/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java new file mode 100644 index 0000000..6be2a59 --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java @@ -0,0 +1,2479 @@ +package org.sonar.cxx.parser; + +import static com.sonar.cxx.sslr.api.GenericTokenType.EOF; +import static com.sonar.cxx.sslr.api.GenericTokenType.IDENTIFIER; + +import com.sonar.cxx.sslr.api.Grammar; +import org.sonar.cxx.config.CxxSquidConfiguration; + +import static org.sonar.cxx.parser.CxxTokenType.CHARACTER; +import static org.sonar.cxx.parser.CxxTokenType.NUMBER; +import static org.sonar.cxx.parser.CxxTokenType.STRING; + +import org.sonar.cxx.sslr.grammar.GrammarRuleKey; +import org.sonar.cxx.sslr.grammar.LexerfulGrammarBuilder; + +/** + * 解析表达式语法(PEG)
+ * 上下文无关语法和解析表达式语法之间的根本区别在于 PEG 的选择运算符是有序的。 + * 如果第一个备选方案成功,则忽略第二个备选方案。 + * 其结果是,如果将 CFG 直接音译为 PEG,则通过确定性地从可能的解析中选取一个解析树来解决前者中的任何歧义。
+ * 通过仔细选择指定语法替代项的顺序,程序员可以在很大程度上控制选择哪个解析树。额外的语法糖,如'next','nextNot'可以提供帮助。
+ * 基于 C++ 标准,附录 A + */ +@SuppressWarnings({"squid:S00115", "squid:S00103", "java:S138"}) +public enum CxxGrammarImpl implements GrammarRuleKey { + // 杂项 + BOOL, // 布尔值 + NULLPTR, // 空指针常量 + LITERAL, // 文字字面量 + + // 顶级组件 + translationUnit, // 转译单位 + + /** + * Expressions + */ + primaryExpression, // 基本表达式 + idExpression, // id表达式 + unqualifiedId, // 未限定的id + qualifiedId, // 限定的id + nestedNameSpecifier, // 嵌套名称规范 + lambdaExpression, // lambda表达式 + lambdaIntroducer, // lambda引入子 + lambdaCapture, // lambda捕获 + captureDefault, // 默认捕获 + captureList, // 捕获列表 + capture, // 捕获 + simpleCapture, // 简单捕获 + initCapture, // 初始化捕获 + lambdaDeclarator, // lambda声明器 + foldExpression, // 折叠表达式 + foldOperator, // 折叠操作符 + requiresExpression, // requires表达式 + requirementParameterList, // requirement参数列表 + requirementBody, // requirement主体 + requirementSeq, // requirement序列 + requirement, // requirement语句 + simpleRequirement, // 简单requirement语句 + typeRequirement, // typerequirement语句 + compoundRequirement, // 复合requirement语句 + returnTypeRequirement, // 返回类型requirement语句 + nestedRequirement, // 嵌套requirement语句 + postfixExpression, // 后缀表达式 + expressionList, // 表达式列表 + unaryExpression, // 一元表达式 + unaryOperator, // 一元操作符 + awaitExpression, // await表达式 + newExpression, // new表达式 + newPlacement, // new放置 + newTypeId, // new类型id + newDeclarator, // new声明器 + noptrNewDeclarator, // noptr new声明器 + newInitializer, // new初始化器 + deleteExpression, // delete表达式 + noexceptExpression, // noexcept表达式 + castExpression, // 转型表达式 + pmExpression, // pm表达式 + multiplicativeExpression, // 乘法表达式 + additiveExpression, // 加法表达式 + shiftExpression, // 位移表达式 + compareExpression, // 比较表达式 + relationalExpression, // 相关表达式 + equalityExpression, // 平等表达式 + andExpression, // 与表达式 + exclusiveOrExpression, // 排它或表达式 + inclusiveOrExpression, // 含义或表达式 + logicalAndExpression, // 逻辑与表达式 + logicalOrExpression, // 逻辑或表达式 + conditionalExpression, // 条件表达式 + yieldExpression, // yield表达式 + assignmentExpression, // 赋值表达式 + assignmentOperator, // 赋值操作符 + expression, // 表达式 + constantExpression, // 常量表达式 + // 语句 + statement, // 语句 + labeledStatement, // 标号语句 + expressionStatement, // 表达式语句 + compoundStatement, // 复合语句 + statementSeq, // 语句序列 + condition, // 条件 + selectionStatement, // 选择语句 + iterationStatement, // 循环语句 + initStatement, // 初始化语句 + forRangeDeclaration, // for范围声明 + forRangeInitializer, // for范围初始化 + jumpStatement, // 跳转语句 + coroutineReturnStatement, // 协程返回语句 + declarationStatement, // 声明语句 + + /** + * 声明 + */ + declarationSeq, // 声明序列 + declaration, // 声明 + blockDeclaration, // 块声明 + nodeclspecFunctionDeclaration, // 无类型声明的函数声明 + aliasDeclaration, // 别名声明 + simpleDeclaration, // 简单声明 + staticAssertDeclaration, // 静态断言声明 + emptyDeclaration, // 空声明 + attributeDeclaration, // 属性声明 + declSpecifier, // 声明限定符 + recoveredDeclaration, // 恢复声明 + conditionDeclSpecifierSeq, // 带条件限定符序列的声明 + forRangeDeclSpecifierSeq, // for范围限定符序列的声明 + parameterDeclSpecifierSeq, // 参数限定符序列的声明 + functionDeclSpecifierSeq, // 函数限定符序列的声明 + declSpecifierSeq, // 限定符序列 + memberDeclSpecifierSeq, // 成员限定符序列的声明 + identifierList, // 标识符列表 + storageClassSpecifier, // 存储类限定符 + functionSpecifier, // 函数限定符 + explicitSpecifier, // 显式限定符 + typedefName, // 类型定义名 + typeSpecifier, // 类型限定符 + typeSpecifierSeq, // 类型限定符序列 + definingTypeSpecifier, // 定义类型限定符 + definingTypeSpecifierSeq, // 定义类型限定符序列 + simpleTypeSpecifier, // 简单类型限定符 + typeName, // 类型名 + decltypeSpecifier, // decltype 限定符 + placeholderTypeSpecifier, // 占位类型限定符 + elaboratedTypeSpecifier, // 复杂类型限定符 + elaboratedEnumSpecifier, // 复杂枚举限定符 + enumName, // 枚举名称 + enumSpecifier, // 枚举指定符 + enumHead, // 枚举头部 + enumHeadName, // 枚举头部名称 + opaqueEnumDeclaration, // 不透明枚举声明 + enumKey, // 枚举键 + enumBase, // 枚举基数 + enumeratorList, // 枚举器列表 + enumeratorDefinition, // 枚举器定义 + enumerator, // 枚举器 + usingEnumDeclaration, // 使用枚举声明 + namespaceName, // 命名空间名称 + namespaceDefinition, // 命名空间定义 + namedNamespaceDefinition, // 命名的命名空间定义 + unnamedNamespaceDefinition, // 无名命名空间定义 + nestedNamespaceDefinition, // 嵌套的命名空间定义 + enclosingNamespaceSpecifier, // 包含的命名空间指定符 + namespaceBody, // 命名空间主体 + namespaceAlias, // 命名空间别名 + namespaceAliasDefinition, // 命名空间别名定义 + qualifiedNamespaceSpecifier, // 限定的命名空间指定符 + usingDeclaration, // 使用声明 + usingDeclaratorList, // 使用声明器列表 + usingDeclarator, // 使用声明器 + usingDirective, // 使用指令 + asmDeclaration, // asm声明 + asmLabel, // asm标签 + linkageSpecification, // 链接指定符 + attributeSpecifierSeq, // 属性指定符序列 + attributeSpecifier, // 属性指定符 + alignmentSpecifier, // 对齐指定符 + attributeUsingPrefix, // 属性使用前缀 + attributeList, // 属性列表 + attribute, // 属性 + attributeToken, // 属性令牌 + attributeScopedToken, // 有作用域的属性令牌 + attributeNamespace, // 属性命名空间 + attributeArgumentClause, // 属性参数子句 + balancedTokenSeq, // 平衡的令牌序列 + balancedToken, // 平衡的令牌 + /** + * 声明符 + */ + initDeclaratorList, // 初始化声明器列表 + initDeclarator, // 初始化声明器 + declarator, // 声明器 + ptrDeclarator, // 指针声明器 + noptrDeclarator, // 无指针声明器 + parametersAndQualifiers, // 参数和限定符 + trailingReturnType, // 尾部返回类型 + ptrOperator, // 指针操作符 + cvQualifierSeq, // cv限定符序列 + cvQualifier, // cv限定符 + refQualifier, // 引用限定符 + declaratorId, // 声明器ID + typeId, // 类型ID + definingTypeId, // 定义类型ID + typeIdEnclosed, // 闭合类型ID + abstractDeclarator, // 抽象声明器 + ptrAbstractDeclarator, // 指针抽象声明器 + noptrAbstractDeclarator, // 无指针抽象声明器 + abstractPackDeclarator, // 抽象打包声明器 + noptrAbstractPackDeclarator, // 无指针抽象打包声明器 + parameterDeclarationClause, // 参数声明子句 + parameterDeclarationList, // 参数声明列表 + parameterDeclaration, // 参数声明 + functionDefinition, // 函数定义 + functionBody, // 函数主体 + initializer, // 初始化器 + braceOrEqualInitializer, // 大括号或赋值初始化器 + initializerClause, // 初始化子句 + initializerList, // 初始化列表 + designatedInitializerList, // 指定的初始化列表 + designatedInitializerClause, // 指定的初始化子句 + designator, // 设计指示器 + bracedInitList, // 大括号初始化列表 + exprOrBracedInitList, // 表达式或大括号初始化列表 + // Modules + moduleDeclaration, // 模块声明 + moduleName, // 模块名称 + modulePartition, // 模块分区 + moduleNameQualifier, // 模块名称限定符 + exportDeclaration, // 导出声明 + moduleImportDeclaration, // 模块导入声明 + globalModuleFragment, // 全局模块片段 + privateModuleFragment, // 私有模块片段 + /** + * 类 + */ + className, // 类名 + classSpecifier, // 类声明 + classHead, // 类头部 + classHeadName, // 类名 + classVirtSpecifier, // 类虚函数指定符 + classKey, // 类键 + memberSpecification, // 成员规格化 + memberDeclaration, // 成员声明 + memberDeclaratorList, // 成员声明器列表 + memberDeclarator, // 成员声明器 + virtSpecifierSeq, // 虚函数指定符序列 + virtSpecifier, // 虚函数指定符 + pureSpecifier, // 纯指定符 + + /** + * 派生类 + */ + baseClause, // 基类条款 + baseSpecifierList, // 基类声明符列表 + baseSpecifier, // 基类声明符 + classOrDecltype, // 类或decltype + accessSpecifier, // 访问指定符 + + /** + * 特殊成员函数 + */ + conversionFunctionId, // 转换函数ID + conversionTypeId, // 转换类型ID + conversionDeclarator, // 转换声明器 + ctorInitializer, // 构造函数初始化器 + memInitializerList, // 成员初始化列表 + memInitializer, // 成员初始化器 + memInitializerId, // 成员初始化器ID + + /** + * 重载 + */ + operatorFunctionId, // 运算符函数ID + operator, // 运算符 + literalOperatorId, // 字面量运算符ID + + /** + * 模板 + */ + templateDeclaration, // 模板声明 + templateHead, // 模板头部 + templateParameterList, // 模板参数列表 + requiresClause, // 需要条款 + constraintLogicalOrExpression, // 约束逻辑或表达式 + constraintLogicalAndExpression, // 约束逻辑与表达式 + templateParameter, // 模板参数 + typeParameter, // 类型参数 + typeTraits, // 类型特性 + typeParameterKey, // 类型参数键 + typeConstraint, // 类型约束 + simpleTemplateId, // 简单模板ID + templateId, // 模板ID + templateName, // 模板名 + templateArgumentList, // 模板参数列表 + templateArgument, // 模板参数 + constraintExpression, // 约束表达式 + conceptDefinition, // 概念定义 + conceptName, // 概念名 + typenameSpecifier, // 类型名指定符 + explicitInstantiation, // 显式实例化 + explicitSpecialization, // 显式特殊化 + deductionGuide, // 推导向导 + /** + * 异常处理 + */ + tryBlock, // 尝试块 + functionTryBlock, // 函数尝试块 + handlerSeq, // 处理器序列 + handler, // 处理器 + exceptionDeclaration, // 异常声明 + throwExpression, // 抛出表达式 + typeIdList, // 类型ID列表 + noexceptSpecifier, // noexcept指定器 + + /** + * Microsoft 扩展:C++/CLI + */ + cliTopLevelVisibility, // CLI的顶层可见性 + cliFinallyClause, // CLI的finally子句 + cliFunctionModifiers, // CLI的函数修饰符 + cliFunctionModifier, // CLI的函数修饰符 + cliEventDefinition, // CLI的事件定义 + cliEventModifiers, // CLI的事件修饰符 + cliPropertyOrEventName, // CLI的属性或事件名称 + cliEventType, // CLI的事件类型 + cliParameterArray, // CLI的参数数组 + cliPropertyDefinition, // CLI的属性定义 + cliPropertyDeclSpecifierSeq, // CLI的属性声明限定符序列 + cliPropertyBody, // CLI的属性体 + cliPropertyModifiers, // CLI的属性修饰符 + cliPropertyIndexes, // CLI的属性索引列表 + cliPropertyIndexParameterList, // CLI的属性索引参数列表 + cliAccessorSpecification, // CLI的访问器规范 + cliAccessorDeclaration, // CLI的访问器声明 + cliDelegateSpecifier, // CLI的委托指定器 + cliDelegateDeclSpecifierSeq, // CLI的委托声明限定符序列 + cliGenericDeclaration, // CLI的泛型声明 + cliGenericParameterList, // CLI的泛型参数列表 + cliConstraintClauseList, // CLI的约束子句列表 + cliConstraintItemList, // CLI的约束项列表 + cliGenericParameter, // CLI的泛型参数 + cliGenericId, // CLI的泛型ID + cliGenericName, // CLI的泛型名称 + cliGenericArgumentList, // CLI的泛型参数列表 + cliGenericArgument, // CLI的泛型参数 + cliConstraintClause, // CLI的约束子句 + cliConstraintItem, // CLI的约束项 + cliAttributes, // CLI的属性 + cliAttributeSection, // CLI的属性节 + cliAttributeTargetSpecifier, // CLI的属性目标指定器 + cliAttributeTarget, // CLI的属性目标 + cliAttributeList, // CLI的属性列表 + cliAttribute, // CLI的属性 + cliAttributeArguments, // CLI的属性参数 + cliPositionArgumentList, // CLI的位置参数列表 + cliNamedArgumentList, // CLI的命名参数列表 + cliPositionArgument, // CLI的位置参数 + cliNamedArgument, // CLI的命名参数 + cliAttributeArgumentExpression, // CLI的属性参数表达式 + + /** + * Microsoft 扩展:特性化 ATL + */ + vcAtlDeclaration, // Visual C++ ATL的声明 + vcAtlAttribute, // Visual C++ ATL的属性 + + /** + * CUDA扩展 + */ + cudaKernel; // CUDA的内核 + + + public static Grammar create(CxxSquidConfiguration squidConfig) { + var b = LexerfulGrammarBuilder.create(); + + toplevel(b, squidConfig); + expressions(b); + statements(b); + declarations(b); + modules(b); + classes(b); + properties(b); + overloading(b); + templates(b); + generics(b); + exceptionHandling(b); + cliAttributes(b); + + misc(b); + vcAttributedAtl(b); + + b.setRootRule(translationUnit); + + return b.buildWithMemoizationOfMatchesForAllRules(); + } + + private static void misc(LexerfulGrammarBuilder b) { + + b.rule(identifierList).is( + IDENTIFIER, b.zeroOrMore(",", IDENTIFIER) //C++ + ); + + // C++ Boolean literals [lex.bool] + b.rule(BOOL).is( + b.firstOf( + CxxKeyword.TRUE, + CxxKeyword.FALSE + ) + ); + + // C++ Pointer literals [lex.nullptr] + b.rule(NULLPTR).is( + CxxKeyword.NULLPTR + ); + + // C++ Kinds of literals [lex.literal.kinds] + b.rule(LITERAL).is( + b.firstOf( + CHARACTER, // character-literal, including user-defined-literal + STRING, // string-literal, including user-defined-string-literal + NUMBER, // integer-literal, floating-literal, including user-defined-literal + BOOL, // boolean-literal + NULLPTR // pointer-literal + ) + ).skip(); + } + + private static void vcAttributedAtl(LexerfulGrammarBuilder b) { + + b.rule(vcAtlAttribute).is( + "[", b.oneOrMore(b.anyTokenButNot("]")), "]" + ); + b.rule(vcAtlDeclaration).is(vcAtlAttribute, ";"); + } + + // **A.3 Basics [gram.basic]** + // + private static void toplevel(LexerfulGrammarBuilder b, CxxSquidConfiguration squidConfig) { + if (squidConfig.getBoolean(CxxSquidConfiguration.SONAR_PROJECT_PROPERTIES, + CxxSquidConfiguration.ERROR_RECOVERY_ENABLED).orElse(Boolean.TRUE)) { + // + // parsing with error recovery + // + b.rule(translationUnit).is( + b.firstOf( + b.sequence(b.optional(globalModuleFragment), + moduleDeclaration, + b.zeroOrMore( + b.firstOf( + declaration, + recoveredDeclaration) + ), + b.optional(privateModuleFragment)), + b.zeroOrMore( + b.firstOf( + declaration, + recoveredDeclaration) + ) + ), + EOF + ); + + // eat all tokens until the next declaration is recognized + // this works only on top level!!! + b.rule(recoveredDeclaration).is( + b.oneOrMore( + b.nextNot( + b.firstOf( + declaration, + EOF + ) + ), b.anyToken() + ) + ); + } else { + b.rule(translationUnit).is( + b.firstOf( + b.sequence(b.optional(globalModuleFragment), + moduleDeclaration, + b.zeroOrMore(declaration), + b.optional(privateModuleFragment)), // C++ + b.zeroOrMore(declaration) // C++ + ), + EOF + ); + } + } + + // **A.4 Expressions [gram.expr]** + // + private static void expressions(LexerfulGrammarBuilder b) { + b.rule(primaryExpression).is( + b.firstOf( + LITERAL, // C++ + CxxKeyword.THIS, // C++ + // EXTENSION: gcc's statement expression: a compound statement enclosed in parentheses may appear as an expression + b.sequence("(", + b.firstOf( + expression, + compoundStatement + ), ")" + ), // C++: ( expression ) + idExpression, // C++ + lambdaExpression, // C++ + foldExpression, // C++ + requiresExpression // C++ + ) + ).skipIfOneChild(); + + b.rule(idExpression).is( + b.firstOf( + qualifiedId, // C++ + unqualifiedId // C++ (PEG: different order) + ) + ).skip(); + + b.rule(unqualifiedId).is( + b.firstOf( + // mitigate ambiguity between relational operators < > and angular brackets by looking ahead + b.sequence(templateId, b.nextNot(b.firstOf("<", ">"))), // C++ + IDENTIFIER, // C++ + operatorFunctionId, // C++ + conversionFunctionId, // C++ + literalOperatorId, // C++ + b.sequence("~", typeName), // C++ + b.sequence("~", decltypeSpecifier), // C++ + //---- + b.sequence("!", className), // C++/CLI + cliGenericId, // C++/CLI + CxxKeyword.DEFAULT // C++/CLI + ) + ).skipIfOneChild(); + + b.rule(qualifiedId).is( + nestedNameSpecifier, b.optional(CxxKeyword.TEMPLATE), unqualifiedId // C++ + ); + + b.rule(nestedNameSpecifier).is( + b.firstOf( + "::", // C++ + b.sequence(typeName, "::"), // C++ + b.sequence(namespaceName, "::"), // C++ + b.sequence(decltypeSpecifier, "::") // C++ + ), + b.zeroOrMore( + b.firstOf( + b.sequence(IDENTIFIER, "::"), // C++ + b.sequence(b.optional(CxxKeyword.TEMPLATE), simpleTemplateId, "::") // C++ + ) + ) + ); + + b.rule(lambdaExpression).is( + lambdaIntroducer, // C++ + b.optional( + b.sequence("<", templateParameterList, ">", b.optional(requiresClause)) // C++ + ), + b.optional(lambdaDeclarator), // C++ + compoundStatement // C++ + ); + + b.rule(lambdaIntroducer).is( + "[", b.optional(lambdaCapture), "]" // C++ + ); + + b.rule(lambdaDeclarator).is( + "(", parameterDeclarationClause, ")", b.optional(declSpecifierSeq), b.optional(noexceptSpecifier), + b.optional(attributeSpecifierSeq), b.optional(trailingReturnType), b.optional(requiresClause) // C++ + ); + + b.rule(lambdaCapture).is( + b.firstOf( + b.sequence(captureDefault, b.optional(",", captureList)), // C++ + captureList // C++ + ) + ); + + b.rule(captureDefault).is( + b.firstOf( + "&", + "=" + ), // C++ + b.nextNot(capture) + ); + + b.rule(captureList).is( + b.sequence(capture, b.zeroOrMore(",", capture)) // C++ + ); + + b.rule(capture).is( + b.firstOf( + b.sequence(simpleCapture, b.nextNot("=")), // C++ + initCapture // C++ + ) + ).skip(); + + b.rule(simpleCapture).is( + b.firstOf( + b.sequence(IDENTIFIER, b.optional("...")), // C++ + b.sequence("&", IDENTIFIER, b.optional("...")), // C++ + CxxKeyword.THIS, // C++ + b.sequence("*", CxxKeyword.THIS) // C++ + ) + ); + + b.rule(initCapture).is( + b.firstOf( + b.sequence(b.optional("..."), IDENTIFIER, initializer), // C++ + b.sequence("&", b.optional("..."), IDENTIFIER, initializer) // C++ + ) + ); + + b.rule(foldExpression).is( + "(", + b.firstOf( + b.sequence(castExpression, foldOperator, "...", b.optional(foldOperator, castExpression)), // C++ + b.sequence("...", foldOperator, castExpression) // C++ + ), + ")" + ); + + b.rule(foldOperator).is( + b.firstOf( // C++ + "+", "-", "*", "/", "%", "ˆ", "&", "|", "<<", ">>", + "+=", "-=", "*=", "/=", "%=", "ˆ=", "&=", "|=", "<<=", ">>=", "=", + "==", "!=", "<", ">", "<=", ">=", "&&", "||", ",", ".*", "->*", + //---- + CxxKeyword.XOR, CxxKeyword.BITAND, CxxKeyword.BITOR, CxxKeyword.XOR_EQ, CxxKeyword.AND_EQ, CxxKeyword.OR_EQ, + CxxKeyword.NOT_EQ, CxxKeyword.AND, CxxKeyword.OR + ) + ); + + b.rule(requiresExpression).is( + CxxKeyword.REQUIRES, b.optional(requirementParameterList), requirementBody // C++ + ); + + b.rule(requirementParameterList).is( + "(", b.optional(parameterDeclarationClause), ")" // C++ + ); + + b.rule(requirementBody).is( + "{", requirementSeq, "}" // C++ + ); + + b.rule(requirementSeq).is( + b.oneOrMore(requirement) // C++ + ); + + b.rule(requirement).is( + b.firstOf( + simpleRequirement, // C++ + typeRequirement, // C++ + compoundRequirement, // C++ + nestedRequirement // C++ + ) + ); + + b.rule(simpleRequirement).is( + expression, ";" // C++ + ); + + b.rule(typeRequirement).is( + CxxKeyword.TYPENAME, b.optional(nestedNameSpecifier), typeName, ";" // C++ + ); + + b.rule(compoundRequirement).is( + "{", expression, "}", b.optional(CxxKeyword.NOEXCEPT), b.optional(returnTypeRequirement), ";" // C++ + ); + + b.rule(returnTypeRequirement).is( + "->", typeConstraint // C++ + ); + + b.rule(nestedRequirement).is( + CxxKeyword.REQUIRES, constraintExpression, ";" // C++ + ); + + b.rule(postfixExpression).is( + b.firstOf( + b.sequence( + typenameSpecifier, + b.firstOf( + b.sequence("::", CxxKeyword.TYPEID), // C++/CLI + b.sequence(b.optional(cudaKernel), "(", b.optional(expressionList), ")"), // C++ + bracedInitList // C++ + ) + ), + b.sequence( + simpleTypeSpecifier, + b.firstOf( + b.sequence("::", CxxKeyword.TYPEID), // C++/CLI + b.sequence(b.optional(cudaKernel), "(", b.optional(expressionList), ")"), // C++ + bracedInitList // C++ + ) + ), + primaryExpression, // C++ (PEG: different order) + b.sequence(CxxKeyword.DYNAMIC_CAST, typeIdEnclosed, "(", expression, ")"), // C++ + b.sequence(CxxKeyword.STATIC_CAST, typeIdEnclosed, "(", expression, ")"), // C++ + b.sequence(CxxKeyword.REINTERPRET_CAST, typeIdEnclosed, "(", expression, ")"), // C++ + b.sequence(CxxKeyword.CONST_CAST, typeIdEnclosed, "(", expression, ")"), //C++ + b.sequence( + CxxKeyword.TYPEID, + "(", + b.firstOf( + expression, // C++ + typeId // C++ + ), + ")" + ) + ), + b.zeroOrMore( + b.firstOf( + b.sequence("[", exprOrBracedInitList, "]"), // C++ + b.sequence("(", b.optional(expressionList), ")"), // C++ + b.sequence( + b.firstOf( + ".", + "->" + ), + b.sequence(b.optional(CxxKeyword.TEMPLATE), idExpression) // C++ + ), + "++", // C++ + "--" // C++ + ) + ) + ).skipIfOneChild(); + + b.rule(cudaKernel).is( + b.sequence("<<", "<", b.optional(expressionList), ">>", ">") // CUDA + ); + + b.rule(typeIdEnclosed).is( // todo + "<", typeId, ">" + ); + + b.rule(expressionList).is( + initializerList // C++ + ); + + b.rule(unaryExpression).is( + b.firstOf( + b.sequence(unaryOperator, castExpression), // C++ (PEG: different order) + newExpression, // C++ + postfixExpression, // C++ + b.sequence("++", castExpression), // C++ + b.sequence("--", castExpression), // C++ + awaitExpression, // C++ + b.sequence( + CxxKeyword.SIZEOF, + b.firstOf( + unaryExpression, // C++ + b.sequence("(", typeId, ")"), // C++ + b.sequence("...", "(", IDENTIFIER, ")") // C++ + ) + ), + b.sequence(CxxKeyword.ALIGNOF, "(", typeId, ")"), // C++ + noexceptExpression, // C++ + deleteExpression // C++ + ) + ).skipIfOneChild(); + + b.rule(unaryOperator).is( + b.firstOf("*", "&", "+", "-", "!", "~", CxxKeyword.NOT, CxxKeyword.COMPL) // C++ + ); + + b.rule(awaitExpression).is( + CxxKeyword.CO_AWAIT, castExpression // C++ + ); + + b.rule(noexceptExpression).is( + CxxKeyword.NOEXCEPT, "(", expression, ")" // C++ + ); + + b.rule(newExpression).is( + b.sequence( + b.optional("::"), // C++ + b.firstOf( + CxxKeyword.NEW, // C++ + "gcnew" // C++/CLI + ), + b.firstOf( + // PEG: different order + b.sequence(newPlacement, "(", typeId, ")"), // C++ + b.sequence(newPlacement, newTypeId), // C++ + b.sequence("(", typeId, ")"), // C++ + newTypeId // C++ + ), + b.optional(newInitializer) // C++ + ) + ); + + b.rule(newPlacement).is( + "(", expressionList, ")" // C++ + ); + + b.rule(newTypeId).is( + typeSpecifierSeq, b.optional(newDeclarator) // C++ + ); + + b.rule(newDeclarator).is( + b.firstOf( + b.sequence(ptrOperator, b.optional(newDeclarator)), // C++ + noptrNewDeclarator // C++ + ) + ); + + b.rule(noptrNewDeclarator).is( + "[", b.optional(expression), "]", b.optional(attributeSpecifierSeq), // C++ + b.zeroOrMore("[", constantExpression, "]", b.optional(attributeSpecifierSeq)) // C++ + ); + + b.rule(newInitializer).is( + b.firstOf( + b.sequence("(", b.optional(expressionList), ")"), // C++ + bracedInitList // C++ + ) + ); + + b.rule(deleteExpression).is( + b.optional("::"), CxxKeyword.DELETE, b.optional("[", "]"), castExpression // C++ + ); + + b.rule(castExpression).is( + b.firstOf( + b.sequence("(", typeId, ")", + b.firstOf( + castExpression, // C++ + bracedInitList // C-COMPATIBILITY: C99 compound literals + ) + ), + unaryExpression // C++ (PEG: different order) + ) + ).skipIfOneChild(); + + b.rule(pmExpression).is( + castExpression, b.zeroOrMore(b.firstOf(".*", "->*"), castExpression) // C++ + ).skipIfOneChild(); + + b.rule(multiplicativeExpression).is( + pmExpression, b.zeroOrMore(b.firstOf("*", "/", "%"), pmExpression) // C++ + ).skipIfOneChild(); + + b.rule(additiveExpression).is( + multiplicativeExpression, b.zeroOrMore(b.firstOf("+", "-"), multiplicativeExpression) // C++ + ).skipIfOneChild(); + + b.rule(shiftExpression).is( + additiveExpression, b.zeroOrMore(b.firstOf("<<", ">>"), additiveExpression) // C++ + ).skipIfOneChild(); + + b.rule(compareExpression).is( + shiftExpression, b.zeroOrMore("<=>", shiftExpression) + ).skipIfOneChild(); + + b.rule(relationalExpression).is( + compareExpression, // C++ + b.zeroOrMore( + b.firstOf( + "<", b.sequence(">", b.nextNot("::", "type")), "<=", ">="), // C++ + compareExpression // C++ + ) + ).skipIfOneChild(); + + b.rule(equalityExpression).is( + relationalExpression, b.zeroOrMore(b.firstOf("==", "!=", CxxKeyword.NOT_EQ), relationalExpression) // C++ + ).skipIfOneChild(); + + b.rule(andExpression).is( + equalityExpression, b.zeroOrMore(b.firstOf("&", CxxKeyword.BITAND), equalityExpression) // C++ + ).skipIfOneChild(); + + b.rule(exclusiveOrExpression).is( + andExpression, b.zeroOrMore(b.firstOf("^", CxxKeyword.XOR), andExpression) // C++ + ).skipIfOneChild(); + + b.rule(inclusiveOrExpression).is( + exclusiveOrExpression, b.zeroOrMore(b.firstOf("|", CxxKeyword.BITOR), exclusiveOrExpression) // C++ + ).skipIfOneChild(); + + b.rule(logicalAndExpression).is( + inclusiveOrExpression, b.zeroOrMore(b.firstOf("&&", CxxKeyword.AND), inclusiveOrExpression) // C++ + ).skipIfOneChild(); + + b.rule(logicalOrExpression).is( + logicalAndExpression, b.zeroOrMore(b.firstOf("||", CxxKeyword.OR), logicalAndExpression) // C++ + ).skipIfOneChild(); + + b.rule(conditionalExpression).is( + // EXTENSION: gcc's conditional with omitted operands: the expression is optional + logicalOrExpression, b.optional("?", b.optional(expression), ":", assignmentExpression) // C++ + ).skipIfOneChild(); + + b.rule(yieldExpression).is( + CxxKeyword.CO_YIELD, b.firstOf(assignmentExpression, bracedInitList) // C++ + ); + + b.rule(throwExpression).is( + CxxKeyword.THROW, b.optional(assignmentExpression) // C++ + ); + + b.rule(assignmentExpression).is( + b.firstOf( + b.sequence(conditionalExpression, b.nextNot(assignmentOperator)), // C++ + yieldExpression, // C++ + throwExpression, // C++ + b.sequence(logicalOrExpression, assignmentOperator, initializerClause) // C++ + ) + ).skipIfOneChild(); + + b.rule(assignmentOperator).is( + b.firstOf("=", "*=", "/=", "%=", "+=", "-=", ">>=", "<<=", "&=", "^=", "|=", + CxxKeyword.AND_EQ, CxxKeyword.XOR_EQ, CxxKeyword.OR_EQ) // C++ + ); + + b.rule(expression).is( + assignmentExpression, b.zeroOrMore(",", assignmentExpression) // C++ + ); + + b.rule(constantExpression).is( + conditionalExpression // C++ + ); + } + + // **A.5 Statements [gram.stmt]** + // + private static void statements(LexerfulGrammarBuilder b) { + + b.rule(statement).is( + b.firstOf( + labeledStatement, // C++ + b.sequence(b.optional(attributeSpecifierSeq), expressionStatement), // C++ + b.sequence(b.optional(attributeSpecifierSeq), compoundStatement), // C++ + b.sequence(b.optional(attributeSpecifierSeq), selectionStatement), // C++ + b.sequence(b.optional(attributeSpecifierSeq), iterationStatement), // C++ + b.sequence(b.optional(attributeSpecifierSeq), jumpStatement), // C++ + declarationStatement, // C++ + b.sequence(b.optional(attributeSpecifierSeq), tryBlock) // C++ + ) + ); + + b.rule(initStatement).is( + b.firstOf( + expressionStatement, // C++ + simpleDeclaration // C++ + ) + ); + + b.rule(condition).is( + b.firstOf( + b.sequence(b.optional(attributeSpecifierSeq), conditionDeclSpecifierSeq, declarator, braceOrEqualInitializer), // C++ + expression // C++ (PEG: different order) + ) + ); + + b.rule(labeledStatement).is( + b.firstOf( + b.sequence(b.optional(attributeSpecifierSeq), IDENTIFIER, ":", statement), // C++ + b.sequence( + b.optional(attributeSpecifierSeq), CxxKeyword.CASE, constantExpression, + b.firstOf( + b.sequence(":", statement), // C++ + b.sequence("...", constantExpression, ":", statement) // EXTENSION: gcc's case range + ) + ), + b.sequence(b.optional(attributeSpecifierSeq), CxxKeyword.DEFAULT, ":", statement) // C++ + ) + ); + + b.rule(expressionStatement).is( + b.optional(expression), ";" // C++ + ); + + b.rule(compoundStatement).is( + "{", b.optional(statementSeq), "}" // C++ + ); + + b.rule(statementSeq).is( + b.oneOrMore(statement) // C++ + ); + + b.rule(selectionStatement).is( + b.firstOf( + b.sequence(CxxKeyword.IF, b.optional(CxxKeyword.CONSTEXPR), "(", b.optional(initStatement), condition, ")", + statement, b.optional(CxxKeyword.ELSE, statement)), // C++ + b.sequence(CxxKeyword.SWITCH, "(", b.optional(initStatement), condition, ")", statement) + ) + ); + + b.rule(conditionDeclSpecifierSeq).is( // decl-specifier-seq + b.oneOrMore( + b.nextNot(declarator, b.firstOf("=", "{")), + declSpecifier + ), + b.optional(attributeSpecifierSeq) + ).skipIfOneChild(); + + b.rule(iterationStatement).is( + b.firstOf( + b.sequence(CxxKeyword.WHILE, "(", condition, ")", + statement), // C++ + b.sequence(CxxKeyword.DO, statement, CxxKeyword.WHILE, "(", expression, ")", ";"), // C++ + b.sequence(CxxKeyword.FOR, "(", initStatement, b.optional(condition), ";", b.optional(expression), ")", + statement), // C++ + b.sequence(CxxKeyword.FOR, "(", b.optional(initStatement), forRangeDeclaration, ":", forRangeInitializer, ")", + statement), // C++ + b.sequence(CxxKeyword.FOR, "each", "(", forRangeDeclaration, "in", forRangeInitializer, ")", + statement) // C++/CLI + ) + ); + + b.rule(forRangeDeclaration).is( + b.optional(attributeSpecifierSeq), + b.firstOf( + b.sequence(forRangeDeclSpecifierSeq, declarator), // C++ + b.sequence(declSpecifierSeq, b.optional(refQualifier), "[", identifierList, "]") // C++ todo declSpecifierSeq? + ) + ); + + b.rule(forRangeDeclSpecifierSeq).is( // decl-specifier-seq + b.oneOrMore( + b.nextNot(b.optional(declarator), b.firstOf(":", "in")), + declSpecifier + ), + b.optional(attributeSpecifierSeq) + ).skipIfOneChild(); + + b.rule(forRangeInitializer).is( + exprOrBracedInitList // C++ + ); + + b.rule(jumpStatement).is( + b.firstOf( + b.sequence(CxxKeyword.BREAK, ";"), // C++ + b.sequence(CxxKeyword.CONTINUE, ";"), // C++ + b.sequence(CxxKeyword.RETURN, b.optional(exprOrBracedInitList), ";"), // C++ + coroutineReturnStatement, // C++ + b.sequence(CxxKeyword.GOTO, IDENTIFIER, ";") // C++ + ) + ); + + b.rule(coroutineReturnStatement).is( + CxxKeyword.CO_RETURN, b.optional(exprOrBracedInitList), ";" + ); + + b.rule(declarationStatement).is( + blockDeclaration // C++ + ); + } + + // **A.6 Declarations [gram.dcl]** + // + private static void declarations(LexerfulGrammarBuilder b) { + + b.rule(declarationSeq).is( + b.oneOrMore(declaration) // C++ + ).skipIfOneChild(); + + b.rule(declaration).is( + b.firstOf( + // identifiers with special meaning: import and module => must be placed before rules that start with an identifier! + moduleImportDeclaration, // C++ import ... + + blockDeclaration, // C++ + nodeclspecFunctionDeclaration, // C++ + functionDefinition, // C++ + templateDeclaration, // C++ + deductionGuide, // C++ + cliGenericDeclaration, // C++/CLI + explicitInstantiation, // C++ + explicitSpecialization, // C++ + exportDeclaration, // C++ + linkageSpecification, // C++ + namespaceDefinition, // C++ + emptyDeclaration, // C++ + attributeDeclaration, // C++ + + vcAtlDeclaration // Attributted-ATL + ) + ); + + b.rule(blockDeclaration).is( + b.firstOf( + simpleDeclaration, // C++ + asmDeclaration, // C++ + namespaceAliasDefinition, // C++ + usingDeclaration, // C++ + usingEnumDeclaration, // C++ + usingDirective, // C++ + staticAssertDeclaration, // C++ + aliasDeclaration, // C++ + opaqueEnumDeclaration // C++ + ) + ).skip(); + + b.rule(nodeclspecFunctionDeclaration).is( + b.optional(attributeSpecifierSeq), declarator, ";" // C++ + ); + + b.rule(aliasDeclaration).is( + CxxKeyword.USING, IDENTIFIER, b.optional(attributeSpecifierSeq), "=", definingTypeId, ";" // C++ + ); + + b.rule(simpleDeclaration).is( + b.firstOf( + b.sequence( // todo + b.optional(cliAttributes), + b.optional(attributeSpecifierSeq), + b.firstOf( + b.sequence(declSpecifierSeq, b.optional(initDeclaratorList)), + b.sequence(b.optional(declSpecifierSeq), initDeclaratorList) + ), + ";" + ), // C++, C++/CLI + b.sequence(b.optional(attributeSpecifierSeq), declSpecifierSeq, b.optional(refQualifier), + "[", identifierList, "]", initializer, ";") // C++ + ) + ); + + b.rule(staticAssertDeclaration).is( + CxxKeyword.STATIC_ASSERT, "(", constantExpression, b.optional(",", STRING), ")", ";" // C++ + ); + + b.rule(emptyDeclaration).is( + ";" // C++ + ); + + b.rule(attributeDeclaration).is( + attributeSpecifierSeq, ";" // C++ + ); + + b.rule(declSpecifier).is( + b.firstOf( + storageClassSpecifier, // C++ + definingTypeSpecifier, // C++ + functionSpecifier, // C++ + CxxKeyword.FRIEND, // C++ + CxxKeyword.TYPEDEF, // C++ + CxxKeyword.CONSTEXPR, // C++ + CxxKeyword.CONSTEVAL, // C++ + CxxKeyword.CONSTINIT, // C++ + CxxKeyword.INLINE // C++ + ) + ); + + b.rule(declSpecifierSeq).is( + b.oneOrMore( + b.nextNot( // simpleDeclaration + b.optional(initDeclaratorList), ";" + ), + declSpecifier // C++ + ), + b.optional(attributeSpecifierSeq) // C++ + ).skipIfOneChild(); + + b.rule(storageClassSpecifier).is( + b.firstOf( + CxxKeyword.REGISTER, // C++11, C++14, deprecated with C++17 + CxxKeyword.STATIC, // C++ + CxxKeyword.THREAD_LOCAL, // C++ + CxxKeyword.EXTERN, // C++ + CxxKeyword.MUTABLE // C++ + ) + ); + + b.rule(functionSpecifier).is( + b.firstOf( + CxxKeyword.VIRTUAL, // C++ + explicitSpecifier // C++ + ) + ); + + b.rule(explicitSpecifier).is( + CxxKeyword.EXPLICIT, + b.optional("(", constantExpression, ")") + ); + + b.rule(typedefName).is( + b.firstOf( + b.sequence(IDENTIFIER, b.nextNot("<")), // C++ + simpleTemplateId // C++ + ) + ); + + b.rule(typeSpecifier).is( // todo wrong + b.firstOf( + classSpecifier, // ??? + enumSpecifier, // ??? + simpleTypeSpecifier, // C++ + elaboratedTypeSpecifier, // C++ + typenameSpecifier, // C++ + cvQualifier, // C++ + cliDelegateSpecifier // C++/CLI + ) + ).skip(); + + b.rule(typeSpecifierSeq).is( + b.oneOrMore(typeSpecifier), // C++ + b.optional(attributeSpecifierSeq) // C++ + ).skipIfOneChild(); + + b.rule(definingTypeSpecifier).is( + b.firstOf( + typeSpecifier, // C++ + classSpecifier, // C++ + enumSpecifier // C++ + ) + ).skip(); + + b.rule(definingTypeSpecifierSeq).is( + b.oneOrMore(definingTypeSpecifier), // C++ + b.optional(attributeSpecifierSeq) // C++ + ).skipIfOneChild(); + + b.rule(simpleTypeSpecifier).is( + b.firstOf( + b.sequence(b.optional(nestedNameSpecifier), typeName), // C++ + b.sequence(nestedNameSpecifier, CxxKeyword.TEMPLATE, simpleTemplateId), // C++ + placeholderTypeSpecifier, // C++ + b.sequence(b.optional(nestedNameSpecifier), templateName), // C++ + CxxKeyword.CHAR, // C++ + CxxKeyword.CHAR8_T, // C++ + CxxKeyword.CHAR16_T, // C++ + CxxKeyword.CHAR32_T, // C++ + CxxKeyword.WCHAR_T, // C++ + CxxKeyword.BOOL, // C++ + CxxKeyword.SHORT, // C++ + CxxKeyword.INT, // C++ + CxxKeyword.LONG, // C++ + CxxKeyword.SIGNED, // C++ + CxxKeyword.UNSIGNED, // C++ + CxxKeyword.FLOAT, // C++ + CxxKeyword.DOUBLE, // C++ + CxxKeyword.VOID, // C++ + decltypeSpecifier // C++ (PEG: different order) + ) + ).skipIfOneChild(); + + b.rule(typeName).is( + b.firstOf( + className, // C++ + enumName, // C++ + typedefName // C++ + ) + ); + + b.rule(elaboratedTypeSpecifier).is( + b.optional(cliAttributes), + b.firstOf( // PEG: different order + b.sequence( + classKey, + b.firstOf( + simpleTemplateId, // C++ + b.sequence(nestedNameSpecifier, b.optional(CxxKeyword.TEMPLATE), simpleTemplateId), // C++ + b.sequence(b.optional(attributeSpecifierSeq), b.optional(nestedNameSpecifier), IDENTIFIER) // C++ + ) + ), + elaboratedEnumSpecifier // C++ + ) + ); + + b.rule(elaboratedEnumSpecifier).is( + CxxKeyword.ENUM, b.optional(nestedNameSpecifier), IDENTIFIER // C++ + ); + + b.rule(decltypeSpecifier).is( + CxxKeyword.DECLTYPE, "(", + b.firstOf( + expression, // C++ + CxxKeyword.AUTO // C++ (keep for backward compatibility) + ), + ")" + ); + + b.rule(placeholderTypeSpecifier).is( + b.optional(typeConstraint), // C++ + b.firstOf( + CxxKeyword.AUTO, // C++ + b.sequence(CxxKeyword.DECLTYPE, "(", CxxKeyword.AUTO, ")") // C++ + ) + ); + + b.rule(initDeclaratorList).is( + initDeclarator, b.zeroOrMore(",", initDeclarator) // C++ + ); + + b.rule(initDeclarator).is( + declarator, // C++ + b.firstOf( + requiresClause, // C++ + b.sequence(b.optional(asmLabel), b.optional(initializer)) // C++ (asmLabel: GCC ASM label) + ) + ); + + b.rule(declarator).is( + b.firstOf( + b.sequence(ptrDeclarator, b.nextNot(parametersAndQualifiers)), // C++ + b.sequence(noptrDeclarator, parametersAndQualifiers, trailingReturnType) // C++ + ) + ); + + b.rule(ptrDeclarator).is( + b.firstOf( + b.sequence(ptrOperator, ptrDeclarator), // C++ + noptrDeclarator // C++ (PEG: different order) + ) + ).skipIfOneChild(); + + b.rule(noptrDeclarator).is( + b.firstOf( + b.sequence(declaratorId, b.optional(attributeSpecifierSeq)), // C++ + b.sequence("(", ptrDeclarator, ")") // C++ + ), + b.zeroOrMore( + b.firstOf( + b.sequence(parametersAndQualifiers, b.nextNot(trailingReturnType)), + b.sequence("[", b.optional(constantExpression), "]", b.optional(attributeSpecifierSeq)) + ) + ) + ).skipIfOneChild(); + + b.rule(parametersAndQualifiers).is( + "(", parameterDeclarationClause, ")", // C++ + b.optional(cvQualifierSeq), // C++ + b.optional(cliFunctionModifiers), // C++/CLI + b.optional(refQualifier), // C++ + b.optional(noexceptSpecifier), // C++ + b.optional(attributeSpecifierSeq) // C++ + ); + + b.rule(trailingReturnType).is( + "->", typeId // C++ + ); + + b.rule(ptrOperator).is( + b.firstOf( + b.sequence("*", b.optional(attributeSpecifierSeq), b.optional(cvQualifierSeq)), // C++ + b.sequence("&", b.optional(attributeSpecifierSeq)), // C++ + b.sequence("&&", b.optional(attributeSpecifierSeq)), // C++ + b.sequence(nestedNameSpecifier, "*", b.optional(attributeSpecifierSeq), b.optional(cvQualifierSeq)), //C++ + //C++/CLI handle reference + b.sequence("^", b.optional(attributeSpecifierSeq), b.optional(cvQualifierSeq)), // C++/CLI + b.sequence("%", b.optional(attributeSpecifierSeq)), // C++/CLI + // C++/CLI tracking reference + b.sequence("^%", b.optional(attributeSpecifierSeq)) // C++/CLI + ) + ); + + b.rule(cvQualifierSeq).is( + b.oneOrMore(cvQualifier) // C++ + ).skipIfOneChild(); + + b.rule(cvQualifier).is( + b.firstOf( + CxxKeyword.CONST, // C++ + CxxKeyword.VOLATILE // C++ + ) + ); + + b.rule(refQualifier).is( + b.firstOf( + "&", // C++ + "&&" // C++ + ) + ); + + b.rule(declaratorId).is( + b.sequence(b.optional("..."), idExpression) // C++ + ); + + b.rule(typeId).is( + typeSpecifierSeq, b.optional(abstractDeclarator) // C++ + ).skip(); + + b.rule(definingTypeId).is( + definingTypeSpecifierSeq, b.optional(abstractDeclarator) // C++ + ); + + b.rule(abstractDeclarator).is( + b.firstOf( + ptrAbstractDeclarator, // C++ + b.sequence(b.optional(noptrAbstractDeclarator), parametersAndQualifiers, trailingReturnType), // C++ + abstractPackDeclarator // C++ + ) + ); + + b.rule(ptrAbstractDeclarator).is( + b.oneOrMore( + b.firstOf( + noptrAbstractDeclarator, // C++ + b.sequence(ptrOperator, b.optional(noptrAbstractDeclarator)) // C++ + ) + ) + ); + + b.rule(noptrAbstractDeclarator).is( + b.oneOrMore( + b.firstOf( + parametersAndQualifiers, // C++ + b.sequence("[", b.optional(constantExpression), "]", b.optional(attributeSpecifierSeq)), // C++ + b.sequence("(", ptrAbstractDeclarator, ")") // C++ + ) + ) + ); + + b.rule(abstractPackDeclarator).is( + b.firstOf( + noptrAbstractPackDeclarator, // C++ + b.sequence(ptrOperator, abstractPackDeclarator) // C++ + ) + ); + + b.rule(noptrAbstractPackDeclarator).is( + b.oneOrMore( + b.firstOf( + parametersAndQualifiers, // C++ + b.sequence("[", b.optional(constantExpression), "]", b.optional(attributeSpecifierSeq)), // C++ + "..." // C++ + ) + ) + ); + + b.rule(parameterDeclarationClause).is( + b.firstOf( + b.sequence(parameterDeclarationList, ",", "..."), // C++ + b.sequence(b.optional(parameterDeclarationList), b.optional("...")), // C++ (PEG: different order) + cliParameterArray // C++/CLI + ) + ); + + b.rule(cliParameterArray).is( + b.optional(attribute), "...", parameterDeclaration // C++/CLI + ); + + b.rule(parameterDeclarationList).is( + parameterDeclaration, b.zeroOrMore(",", parameterDeclaration) // C++ + ); + + b.rule(parameterDeclaration).is( + b.firstOf( + // solve issue in templateParameter, conflict in initializerClause, relationalExpression (>), + // sample: template string f(); + b.sequence(b.optional(attributeSpecifierSeq), parameterDeclSpecifierSeq, declarator, + "=", LITERAL), // syntax sugar + b.sequence(b.optional(attributeSpecifierSeq), b.optional(vcAtlAttribute), parameterDeclSpecifierSeq, declarator, + b.optional("=", initializerClause)), // C++ + b.sequence(b.optional(attributeSpecifierSeq), parameterDeclSpecifierSeq, b.optional(abstractDeclarator), + b.optional("=", initializerClause))) // C++ + ); + + b.rule(parameterDeclSpecifierSeq).is( // is decl-specifier-seq + b.zeroOrMore( + b.nextNot(b.optional(declarator), b.firstOf("=", ")", ",")), declSpecifier, b.optional("...") // todo wrong ... + ), + b.optional(attributeSpecifierSeq) + ).skipIfOneChild(); + + b.rule(initializer).is( + b.firstOf( + braceOrEqualInitializer, // C++ + b.sequence("(", expressionList, ")") // C++ + ) + ); + + b.rule(braceOrEqualInitializer).is( + b.firstOf( + b.sequence("=", initializerClause), // C++ + bracedInitList // C++ + ) + ).skip(); + + b.rule(initializerClause).is( + b.firstOf( + assignmentExpression, // C++ + bracedInitList // C++ + ) + ).skipIfOneChild(); + + b.rule(bracedInitList).is( + "{", + b.firstOf( + b.sequence(LITERAL, b.oneOrMore(",", LITERAL), "}"), // syntax sugar: speed-up initialisation of big arrays + b.sequence(initializerList, b.optional(","), "}"), // C++ + b.sequence(designatedInitializerList, b.optional(","), "}"), // C++ + "}" // C++ + ) + ); + + b.rule(initializerList).is( + initializerClause, b.optional("..."), b.zeroOrMore(",", initializerClause, b.optional("...")) // C++ + ); + + b.rule(designatedInitializerList).is( + designatedInitializerClause, b.zeroOrMore(",", designatedInitializerClause) // C++ + ); + + b.rule(designatedInitializerClause).is( + b.firstOf( + b.sequence(designator, braceOrEqualInitializer), // C++ + initializerClause // C99 mixed + ) + ); + + b.rule(designator).is( + b.firstOf( + b.oneOrMore(b.sequence(".", IDENTIFIER)), // C++ & C99 + b.sequence("[", constantExpression, "]", b.zeroOrMore(".", IDENTIFIER)), // C99 designated initializers + b.sequence("[", constantExpression, "...", constantExpression, "]") // EXTENSION: gcc's designated initializers range + ) + ); + + b.rule(exprOrBracedInitList).is( + b.firstOf( + expression, // C++ + bracedInitList // C++ + ) + ).skip(); + + b.rule(functionDefinition).is( + b.optional(attributeSpecifierSeq), // C++ + b.optional(cliAttributes), // C++/CLI + b.optional(functionDeclSpecifierSeq), // C++ + declarator, //C++ + b.firstOf( + requiresClause, + b.optional(virtSpecifierSeq) // C++ + ), + functionBody // C++ + ); + + b.rule(functionDeclSpecifierSeq).is( // is decl-specifier-seq + b.oneOrMore( + b.nextNot( // see functionDefinition + declarator, + b.firstOf( + requiresClause, + b.optional(virtSpecifierSeq) + ), + functionBody + ), + declSpecifier // C++ + ), + b.optional(attributeSpecifierSeq) + ).skipIfOneChild(); + + b.rule(functionBody).is( + b.firstOf( + b.sequence(b.optional(ctorInitializer), compoundStatement), // C++ + functionTryBlock, // C++ + b.sequence("=", CxxKeyword.DELETE, ";"), // C++ + b.sequence("=", CxxKeyword.DEFAULT, ";") // C++ + ) + ); + + b.rule(enumName).is( + IDENTIFIER, b.nextNot("<") // C++ + ); + + b.rule(enumSpecifier).is( + b.firstOf( + b.sequence(enumHead, "{", b.optional(enumeratorList), "}"), // C++ + b.sequence(enumHead, "{", enumeratorList, ",", "}") // C++ + ) + ); + + b.rule(enumHead).is( + b.optional(vcAtlAttribute), b.optional(cliTopLevelVisibility), enumKey, b.optional(attributeSpecifierSeq), + b.optional(enumHeadName), b.optional(enumBase) // C++ + ); + + b.rule(enumHeadName).is( + b.optional(nestedNameSpecifier), IDENTIFIER // C++ + ); + + b.rule(opaqueEnumDeclaration).is( + enumKey, b.optional(attributeSpecifierSeq), enumHeadName, b.optional(enumBase), ";" // C++ + ); + + b.rule(enumKey).is( + CxxKeyword.ENUM, b.optional(b.firstOf(CxxKeyword.CLASS, CxxKeyword.STRUCT)) // C++ + ); + + b.rule(enumBase).is( + ":", typeSpecifierSeq // C++ + ); + + b.rule(enumeratorList).is( + enumeratorDefinition, b.zeroOrMore(",", enumeratorDefinition) // C++ + ); + + b.rule(enumeratorDefinition).is( + enumerator, b.optional("=", constantExpression) // C++ + ); + + b.rule(enumerator).is( + IDENTIFIER, b.optional(attributeSpecifierSeq) // C++ + ); + + b.rule(usingEnumDeclaration).is( + CxxKeyword.USING, elaboratedEnumSpecifier, ";" + ); + + b.rule(namespaceName).is( + b.firstOf( + IDENTIFIER, // C++ + namespaceAlias // C++ + ) + ); + + b.rule(namespaceDefinition).is( + b.firstOf( + namedNamespaceDefinition, // C++ + unnamedNamespaceDefinition, // C++ + nestedNamespaceDefinition // C++ + ) + ); + + b.rule(namedNamespaceDefinition).is( + b.optional(CxxKeyword.INLINE), CxxKeyword.NAMESPACE, b.optional(attributeSpecifierSeq), IDENTIFIER, + "{", namespaceBody, "}" // C++ + ); + + b.rule(unnamedNamespaceDefinition).is( + b.optional(CxxKeyword.INLINE), CxxKeyword.NAMESPACE, b.optional(attributeSpecifierSeq), + "{", namespaceBody, "}" // C++ + ); + + b.rule(nestedNamespaceDefinition).is( + CxxKeyword.NAMESPACE, enclosingNamespaceSpecifier, "::", b.optional(CxxKeyword.INLINE), IDENTIFIER, + "{", namespaceBody, "}" // C++ + ); + + b.rule(enclosingNamespaceSpecifier).is( + IDENTIFIER, b.zeroOrMore("::", b.optional(CxxKeyword.INLINE), IDENTIFIER, b.nextNot("{")) // C++ + ); + + b.rule(namespaceBody).is( + b.optional(declarationSeq) // C++ + ); + + b.rule(namespaceAlias).is( + IDENTIFIER // C++ + ); + + b.rule(namespaceAliasDefinition).is( + CxxKeyword.NAMESPACE, IDENTIFIER, "=", qualifiedNamespaceSpecifier, ";" // C++ + ); + + b.rule(qualifiedNamespaceSpecifier).is( + b.optional(nestedNameSpecifier), namespaceName // C++ + ); + + b.rule(usingDirective).is( + b.optional(attributeSpecifierSeq), CxxKeyword.USING, CxxKeyword.NAMESPACE, b.optional(nestedNameSpecifier), + namespaceName, ";" // C++ + ); + + b.rule(usingDeclaration).is( + CxxKeyword.USING, usingDeclaratorList, ";" // C++ + ); + + b.rule(usingDeclaratorList).is( + usingDeclarator, b.optional("..."), b.zeroOrMore(",", usingDeclarator, b.optional("...")) // C++ + ); + + b.rule(usingDeclarator).is( + b.optional(CxxKeyword.TYPENAME), nestedNameSpecifier, unqualifiedId // C++ + ); + + b.rule(asmDeclaration).is( + b.firstOf( + b.sequence( + b.optional(attributeSpecifierSeq), + b.firstOf(CxxKeyword.ASM, "__asm__"), // C++ asm; GCC: __asm__ + b.optional(b.firstOf(CxxKeyword.VIRTUAL, CxxKeyword.INLINE, "__virtual__")), // GCC asm qualifiers + "(", STRING, ")", ";" + ), + b.sequence(b.firstOf("__asm", CxxKeyword.ASM), b.firstOf( // VS + b.sequence("{", b.oneOrMore(b.nextNot(b.firstOf("}", EOF)), b.anyToken()), "}", b.optional(";")), // VS __asm block + b.sequence(b.oneOrMore(b.nextNot(b.firstOf(";", EOF)), b.anyToken()), ";") // VS __asm ... ; + ) + ) + ) + ); + + b.rule(asmLabel).is( + b.firstOf(CxxKeyword.ASM, "__asm__"), "(", STRING, ")" // GCC ASM label + ); + + b.rule(linkageSpecification).is( + CxxKeyword.EXTERN, STRING, + b.firstOf( + b.sequence("{", b.optional(declarationSeq), "}"), // C++ + declaration // C++ + ) + ); + + b.rule(attributeSpecifierSeq).is( + b.oneOrMore(attributeSpecifier) // C++ + ).skipIfOneChild(); + + b.rule(attributeSpecifier).is( + b.firstOf( + b.sequence("[", "[", b.optional(attributeUsingPrefix), attributeList, "]", "]"), // C++ + alignmentSpecifier // C++ + )); + + b.rule(alignmentSpecifier).is( + b.firstOf( + b.sequence(CxxKeyword.ALIGNAS, "(", typeId, b.optional("..."), ")"), // C++ + b.sequence(CxxKeyword.ALIGNAS, "(", constantExpression, b.optional("..."), ")"), // C++ + b.sequence(attributeUsingPrefix, ":"), // C++ + b.sequence(CxxKeyword.USING, attributeNamespace, ":") // C++ + )); + + b.rule(attributeUsingPrefix).is( + CxxKeyword.USING, attributeNamespace, ":" // C++ + ); + + b.rule(attributeList).is( + b.optional(attribute, b.optional("...")), // C++ + b.zeroOrMore( + ",", b.optional(attribute, b.optional("...")) // C++ + ) + ); + + b.rule(attribute).is( + attributeToken, b.optional(attributeArgumentClause) // C++ + ); + + b.rule(attributeToken).is( + b.firstOf( + b.sequence(IDENTIFIER, b.nextNot("::")), // C++ + attributeScopedToken // C++ + ) + ); + + b.rule(attributeScopedToken).is( + attributeNamespace, "::", IDENTIFIER // C++ + ); + + b.rule(attributeNamespace).is( + IDENTIFIER // C++ + ); + + b.rule(attributeArgumentClause).is( + "(", b.optional(balancedTokenSeq), ")" // C++ + ); + + b.rule(balancedTokenSeq).is( + b.oneOrMore(balancedToken) // C++ + ).skipIfOneChild(); + + b.rule(balancedToken).is( + b.firstOf( + b.sequence("(", b.optional(balancedTokenSeq), ")"), // C++ + b.sequence("{", b.optional(balancedTokenSeq), "}"), // C++ + b.sequence("[", b.optional(balancedTokenSeq), "]"), // C++ + b.oneOrMore(b.nextNot(b.firstOf("(", ")", "{", "}", "[", "]", EOF)), b.anyToken()) // C++ + ) + ); + } + + // **A.7 Modules [gram.module]** + // + private static void modules(LexerfulGrammarBuilder b) { + + b.rule(moduleDeclaration).is( + b.optional("export"), "module", moduleName, + b.optional(modulePartition), b.optional(attributeSpecifierSeq), ";" // C++ + ); + + b.rule(moduleName).is( + b.optional(moduleNameQualifier), IDENTIFIER // C++ + ); + + b.rule(modulePartition).is( + ":", b.optional(moduleNameQualifier), IDENTIFIER // C++ + ); + + b.rule(moduleNameQualifier).is( + IDENTIFIER, ".", b.zeroOrMore(IDENTIFIER, ".") // C++ + ); + + b.rule(exportDeclaration).is( // C++ + "export", + b.firstOf( + declaration, + b.sequence("{", b.optional(declarationSeq), "}"), + moduleImportDeclaration + ) + ); + + b.rule(moduleImportDeclaration).is( // C++ + "import", + b.firstOf( + moduleName, + modulePartition + //####todo headerName + ), + b.optional(attributeSpecifierSeq), + ";" + ); + + b.rule(globalModuleFragment).is( + "module", ";", b.optional(declarationSeq) // C++ + ); + + b.rule(privateModuleFragment).is( + "module", ":", "private", ";", b.optional(declarationSeq) // C++ + ); + } + + // **A.8 Classes [gram.class]** + // + private static void classes(LexerfulGrammarBuilder b) { + b.rule(className).is( + b.firstOf( + b.sequence(IDENTIFIER, b.nextNot("<")), // C++ + simpleTemplateId // C++ + ) + ); + + b.rule(classSpecifier).is( + b.optional(vcAtlAttribute), classHead, "{", b.optional(memberSpecification), "}" // C++ + ); + + b.rule(classHead).is( + b.optional(cliTopLevelVisibility), b.optional(vcAtlAttribute), classKey, b.optional(attributeSpecifierSeq), + b.firstOf( + b.sequence(classHeadName, b.optional(classVirtSpecifier), b.optional(baseClause), // C++ + b.optional(attributeSpecifierSeq)), // Microsoft: attributeSpecifierSeq + b.optional(baseClause) // C++ + ) + ); + + b.rule(classHeadName).is( + b.optional(nestedNameSpecifier), className // C++ + ); + + b.rule(cliTopLevelVisibility).is( // C++/CLI + b.firstOf( + CxxKeyword.PUBLIC, + CxxKeyword.PRIVATE + ) + ); + + b.rule(classVirtSpecifier).is( + b.firstOf( + "final", // C++ + "sealed", // C++/CLI + "abstract" // C++/CLI + ) + ); + + b.rule(classKey).is( + b.firstOf( + b.sequence(b.optional(b.firstOf("ref", "value", "interface")), CxxKeyword.CLASS), // C++, C++/CLI + b.sequence(b.optional(b.firstOf("ref", "value", "interface")), CxxKeyword.STRUCT), // C++, C++/CLI + CxxKeyword.UNION // C++, C++/CLI + ) + ); + + b.rule(memberSpecification).is( + b.oneOrMore( + b.firstOf( + memberDeclaration, // C++ + b.sequence(accessSpecifier, ":") // C++ + ) + ) + ); + + b.rule(memberDeclaration).is( // todo + b.firstOf( + functionDefinition, // C++ + b.sequence( + b.optional(attributeSpecifierSeq), + b.optional(b.firstOf(cliAttributes, vcAtlAttribute)), + b.optional(b.firstOf("initonly", "literal")), + b.optional(memberDeclSpecifierSeq), // is decl-specifier-seqopt + b.optional(memberDeclaratorList), + ";" + ), + usingDeclaration, // C++ + usingEnumDeclaration, // C++ + staticAssertDeclaration, // C++ + templateDeclaration, // C++ + explicitSpecialization, // C++ + deductionGuide, // C++ + aliasDeclaration, // C++ + opaqueEnumDeclaration, // C++ + emptyDeclaration, // C++ + //---- + cliGenericDeclaration, // C++/CLI + cliDelegateSpecifier, // C++/CLI + cliEventDefinition, // C++/CLI + cliPropertyDefinition // C++/CLI + ) + ); + + b.rule(cliDelegateDeclSpecifierSeq).is( // C++/CLI + b.oneOrMore( + b.nextNot(b.optional(declarator), emptyDeclaration), + declSpecifier + ) + ).skipIfOneChild(); + + b.rule(cliDelegateSpecifier).is( // C++/CLI + b.optional(cliAttributes), b.optional(cliTopLevelVisibility), "delegate", cliDelegateDeclSpecifierSeq, declarator, + emptyDeclaration + ); + + b.rule(memberDeclSpecifierSeq).is( // is decl-specifier-seqopt + b.oneOrMore( + b.nextNot(b.optional(memberDeclaratorList), emptyDeclaration), declSpecifier + ), + b.optional(attributeSpecifierSeq) + ).skipIfOneChild(); + + b.rule(memberDeclaratorList).is( + memberDeclarator, b.zeroOrMore(",", memberDeclarator) // C++ + ); + + b.rule(memberDeclarator).is( + b.firstOf( + b.sequence(declarator, requiresClause), // C++ + b.sequence(declarator, braceOrEqualInitializer), // C++ + b.sequence(b.optional(IDENTIFIER), b.optional(attributeSpecifierSeq), ":", constantExpression, + b.optional(braceOrEqualInitializer)), // C++ (PEG) + b.sequence(declarator, b.optional(virtSpecifierSeq), b.optional(cliFunctionModifiers), + b.optional(pureSpecifier)) // C++ + ) + ); + + b.rule(virtSpecifierSeq).is( + b.oneOrMore(virtSpecifier) // C++ + ).skipIfOneChild(); + + b.rule(virtSpecifier).is( + b.firstOf( + "override", // C++ + "final" // C++ + ) + ); + + b.rule(pureSpecifier).is( + "=", "0" // C++ + ); + + b.rule(cliFunctionModifiers).is( + b.oneOrMore(cliFunctionModifier) // C++/CLI + ); + + b.rule(cliFunctionModifier).is( + b.firstOf("abstract", CxxKeyword.NEW, "sealed") // C++/CLI + ); + + b.rule(conversionFunctionId).is( + CxxKeyword.OPERATOR, conversionTypeId // C++ + ); + + b.rule(conversionTypeId).is( + typeSpecifierSeq, b.optional(conversionDeclarator) // C++ + ); + + b.rule(conversionDeclarator).is( + b.oneOrMore(ptrOperator) // C++ + ); + + b.rule(baseClause).is( + ":", baseSpecifierList // C++ + ); + + b.rule(baseSpecifierList).is( + baseSpecifier, b.optional("..."), b.zeroOrMore(",", baseSpecifier, b.optional("...")) // C++ + ); + + b.rule(baseSpecifier).is( + b.optional(attributeSpecifierSeq), + b.firstOf( + classOrDecltype, // C++ + b.sequence(CxxKeyword.VIRTUAL, b.optional(accessSpecifier), classOrDecltype), // C++ + b.sequence(accessSpecifier, b.optional(CxxKeyword.VIRTUAL), classOrDecltype) // C++ + ) + ); + + b.rule(classOrDecltype).is( + b.firstOf( + b.sequence(b.optional(nestedNameSpecifier), typeName), // C++ + b.sequence(b.optional(nestedNameSpecifier), CxxKeyword.TEMPLATE, simpleTemplateId), // C++ + decltypeSpecifier // C++ + ) + ); + + b.rule(accessSpecifier).is( + b.firstOf( + b.sequence(CxxKeyword.PROTECTED, CxxKeyword.PUBLIC), // C++/CLI + b.sequence(CxxKeyword.PUBLIC, CxxKeyword.PROTECTED), // C++/CLI + b.sequence(CxxKeyword.PROTECTED, CxxKeyword.PRIVATE), // C++/CLI + b.sequence(CxxKeyword.PRIVATE, CxxKeyword.PROTECTED), // C++/CLI + CxxKeyword.PRIVATE, // C++ + CxxKeyword.PROTECTED, // C++ + CxxKeyword.PUBLIC, // C++ + "internal" // C++/CLI + ) + ); + + b.rule(ctorInitializer).is( + ":", memInitializerList // C++ + ); + + b.rule(memInitializerList).is( + memInitializer, b.optional("..."), b.zeroOrMore(",", memInitializer, b.optional("...")) // C++ + ); + + b.rule(memInitializer).is( + b.firstOf( + b.sequence(memInitializerId, "(", b.optional(expressionList), ")"), // C++ + b.sequence(memInitializerId, bracedInitList) // C++ + ) + ); + + b.rule(memInitializerId).is( + b.firstOf( + classOrDecltype, // C++ + IDENTIFIER // C++ + ) + ); + + } + + // **A.9 Overloading [gram.over]** + // + private static void overloading(LexerfulGrammarBuilder b) { + b.rule(operatorFunctionId).is( + CxxKeyword.OPERATOR, operator + ); + + b.rule(operator).is( + b.firstOf( + b.sequence(CxxKeyword.NEW, b.optional("[", "]")), b.sequence(CxxKeyword.DELETE, b.optional("[", "]")), + CxxKeyword.CO_AWAIT, b.sequence("(", ")"), b.sequence("[", "]"), "->", "->*", + "~", "!", "+", "-", "*", "/", "%", "^", "&", + "|", "=", "+=", "-=", "*=", "/=", "%=", "^=", "&=", + "|=", "==", "!=", "<", ">", "<=", ">=", "<=>", "&&", + "||", "<<", ">>", "<<=", ">>=", "++", "--", ",", + //--- alternative tokens + CxxKeyword.XOR, CxxKeyword.BITAND, CxxKeyword.BITOR, CxxKeyword.COMPL, CxxKeyword.NOT, CxxKeyword.XOR_EQ, + CxxKeyword.AND_EQ, CxxKeyword.OR_EQ, CxxKeyword.NOT_EQ, CxxKeyword.AND, CxxKeyword.OR + ) + ); + + b.rule(literalOperatorId).is( + CxxKeyword.OPERATOR, STRING, b.optional(IDENTIFIER) // C++ (string-literal and user-defined-string-literal is both STRING) + ); + } + + private static void properties(LexerfulGrammarBuilder b) { + b.rule(cliPropertyOrEventName).is( + b.firstOf( + IDENTIFIER, + CxxKeyword.DEFAULT + ) + ).skip(); + + b.rule(cliPropertyDeclSpecifierSeq).is( + b.oneOrMore( + b.nextNot(declarator, b.optional(cliPropertyBody), b.optional(";")), typeSpecifier + ) + ).skipIfOneChild(); + + b.rule(cliPropertyDefinition).is( + b.optional(cliAttributes), + b.optional(cliPropertyModifiers), + "property", + b.firstOf( + cliPropertyDeclSpecifierSeq, + b.sequence(b.optional(nestedNameSpecifier), b.optional(cliPropertyOrEventName)) + ), + declarator, + b.firstOf( + emptyDeclaration, + cliPropertyBody) + ); + + b.rule(cliPropertyBody).is( + b.optional(cliPropertyIndexes), "{", cliAccessorSpecification, "}" + ); + + b.rule(cliPropertyModifiers).is( + b.oneOrMore(b.firstOf(CxxKeyword.VIRTUAL, CxxKeyword.STATIC)) + ); + + b.rule(cliPropertyIndexes).is( + "[", cliPropertyIndexParameterList, "]" + ); + + b.rule(cliPropertyIndexParameterList).is( + typeId, b.zeroOrMore(",", typeId) + ); + + b.rule(cliAccessorSpecification).is( + b.zeroOrMore(b.optional(accessSpecifier, ":"), cliAccessorDeclaration) + ); + + b.rule(cliAccessorDeclaration).is( + b.firstOf( + functionDefinition, + b.sequence(b.optional(attribute), b.optional(declSpecifierSeq), b.optional(memberDeclaratorList), ";") + ) + ); + + b.rule(cliEventDefinition).is( + b.optional(cliAttributes), + b.optional(cliEventModifiers), + "event", + cliEventType, + IDENTIFIER, + b.firstOf( + emptyDeclaration, + b.sequence("{", cliAccessorSpecification, "}") + ) + ); + + b.rule(cliEventModifiers).is( + b.oneOrMore(b.firstOf(CxxKeyword.VIRTUAL, CxxKeyword.STATIC)) + ); + + b.rule(cliEventType).is( + b.firstOf( + b.sequence(b.optional("::"), b.optional(nestedNameSpecifier), typeName, b.optional("^")), + b.sequence(b.optional("::"), b.optional(nestedNameSpecifier), CxxKeyword.TEMPLATE, templateId, "^") + ) + ); + } + + // **A.10 Templates [gram.temp]** + // + private static void templates(LexerfulGrammarBuilder b) { + b.rule(templateDeclaration).is( + templateHead, + b.firstOf( + declaration, // C++ + conceptDefinition // C++ + ) + ); + + b.rule(templateHead).is( + CxxKeyword.TEMPLATE, "<", templateParameterList, ">", b.optional(requiresClause) + ); + + b.rule(templateParameterList).is( + templateParameter, b.zeroOrMore(",", templateParameter) // C++ + ); + + b.rule(requiresClause).is( + CxxKeyword.REQUIRES, constraintLogicalOrExpression + ); + + b.rule(constraintLogicalOrExpression).is( + constraintLogicalAndExpression, b.zeroOrMore("||", constraintLogicalAndExpression) + ).skipIfOneChild(); + + b.rule(constraintLogicalAndExpression).is( + primaryExpression, b.zeroOrMore("&&", primaryExpression) + ).skipIfOneChild(); + + b.rule(templateParameter).is( + b.firstOf( + // syntax sugar: support macros and function calls as template parameter, e.g. template + b.sequence(b.optional("::"), b.zeroOrMore(IDENTIFIER, "::"), typeName, + "(", b.optional(parameterDeclarationClause), ")"), + typeParameter, // C++ + parameterDeclaration // C++ + ) + ); + + b.rule(typeParameter).is( // todo + b.firstOf( + b.sequence( + typeParameterKey, + b.firstOf( + typeTraits, // syntax sugar to handle type traits ... ::type + b.sequence(b.optional(IDENTIFIER), "=", typeId), // C++ + b.sequence(b.optional("..."), b.optional(IDENTIFIER)) // C++ (PEG: different order) + ) + ), + b.sequence( + templateHead, + typeParameterKey, + b.firstOf( + b.sequence(b.optional(IDENTIFIER), "=", idExpression), // C++ + b.sequence(b.optional("..."), b.optional(IDENTIFIER)) // C++ (PEG: different order) + ) + ), + b.sequence( // C++ (PEG: different order) todo one up + typeConstraint, + b.firstOf( + b.sequence(b.optional(IDENTIFIER), "=", typeId), // C++ + // syntax sugar to handle type traits providing type name (e.g. std::enable_if_t<>=0, std::enable_if_t<>*=nullptr) + b.sequence(b.optional("*"), "=", LITERAL), + // syntax sugar in case type is an identifier, e.g. 'size_t s = 0' (PEG conflict with parameterDeclaration) + b.sequence(IDENTIFIER, "=", initializerClause), + b.sequence(b.optional("..."), b.optional(IDENTIFIER)) // C++ (PEG: different order) + ) + ) + ) + ); + + b.rule(typeTraits).is( // syntax sugar to handle type traits ...::type (not part of C++ grammar) + b.zeroOrMore(b.sequence(IDENTIFIER, "::")), + simpleTemplateId, "::", "type", b.optional("*"), + b.optional("=", LITERAL) + ); + + b.rule(typeParameterKey).is( + b.firstOf( + CxxKeyword.CLASS, // C++ + CxxKeyword.TYPENAME // C++ + ) + ); + + b.rule(typeConstraint).is( + b.optional(nestedNameSpecifier), // C++ + conceptName, // C++ + b.optional(b.sequence("<", b.optional(templateArgumentList), ">")) // C++ + ); + + b.rule(simpleTemplateId).is( + templateName, "<", b.optional(templateArgumentList), ">" + ); + + b.rule(templateId).is( + b.firstOf( + simpleTemplateId, // C++ + b.sequence( + b.firstOf( + operatorFunctionId, + literalOperatorId + ), + "<", b.optional(templateArgumentList), ">" // C++ + ) + ) + ); + + b.rule(templateName).is( + IDENTIFIER // C++ + ); + + b.rule(templateArgumentList).is( + templateArgument, b.optional("..."), b.zeroOrMore(",", templateArgument, b.optional("...")) // C++ + ); + + b.rule(templateArgument).is( + b.firstOf( + b.sequence(typeId, b.next(b.firstOf(">", ",", "..."))), // C++ + // FIXME: workaround to parse stuff like "carray" actually, it should be covered by the next rule (constantExpression) + // but it doesnt work because of ambiguity template syntax <--> relationalExpression + b.sequence(shiftExpression, b.next(b.firstOf(">", ",", "..."))), + b.sequence(constantExpression, b.next(b.firstOf(">", ",", "..."))), // C++ + b.sequence(idExpression, b.next(b.firstOf(">", ",", "..."))) // C++ + ) + ); + + b.rule(constraintExpression).is( + logicalOrExpression // C++ + ); + + b.rule(deductionGuide).is( + b.optional(explicitSpecifier), templateName, "(", parameterDeclarationClause, ")", "->", simpleTemplateId, ";" // C++ + ); + + b.rule(conceptDefinition).is( + CxxKeyword.CONCEPT, conceptName, "=", constraintExpression, ";" // C++ + ); + + b.rule(conceptName).is( + IDENTIFIER // C++ + ); + + b.rule(typenameSpecifier).is( + b.firstOf( + b.sequence( + CxxKeyword.TYPENAME, // C++ + b.firstOf( + b.sequence( + nestedNameSpecifier, // C++ + b.firstOf( + b.sequence(b.optional(CxxKeyword.TEMPLATE), simpleTemplateId), // C++ + IDENTIFIER // C++ + )), + IDENTIFIER // C++ syntax sugar to avoid syntax errors in case of types without a declaration + ) + ), + b.sequence(IDENTIFIER, b.next("::", "typeid")) // special cases ... ::typeid (C++/CLI) + ) + ); + + b.rule(explicitInstantiation).is( + b.optional(CxxKeyword.EXTERN), CxxKeyword.TEMPLATE, declaration // C++ + ); + + b.rule(explicitSpecialization).is( + CxxKeyword.TEMPLATE, "<", ">", declaration // C++ + ); + + } + + private static void generics(LexerfulGrammarBuilder b) { + b.rule(cliGenericDeclaration).is( + "generic", "<", cliGenericParameterList, ">", b.optional(cliConstraintClauseList), declaration + ); + + b.rule(cliGenericParameterList).is( + cliGenericParameter, b.zeroOrMore(",", cliGenericParameter) + ); + + b.rule(cliGenericParameter).is( + b.optional(attribute), b.firstOf(CxxKeyword.CLASS, CxxKeyword.TYPENAME), IDENTIFIER + ); + + b.rule(cliGenericId).is( + cliGenericName, "<", cliGenericArgumentList, ">" + ); + + b.rule(cliGenericName).is( + b.firstOf(IDENTIFIER, operatorFunctionId) + ); + + b.rule(cliGenericArgumentList).is( + cliGenericArgument, b.zeroOrMore(",", cliGenericArgument) + ); + + b.rule(cliGenericArgument).is( + typeId + ); + + b.rule(cliConstraintClauseList).is( + cliConstraintClause, b.zeroOrMore(cliConstraintClause) + ); + + b.rule(cliConstraintClause).is( + "where", IDENTIFIER, ":", cliConstraintItemList + ); + + b.rule(cliConstraintItemList).is( + cliConstraintItem, b.zeroOrMore(",", cliConstraintItem) + ); + + b.rule(cliConstraintItem).is( + b.firstOf( + typeId, + b.sequence(b.firstOf("ref", "value"), b.firstOf(CxxKeyword.CLASS, CxxKeyword.STRUCT)), + "gcnew" + ) + ); + } + + // **A.11 Exception handling [gram.except]** + // + private static void exceptionHandling(LexerfulGrammarBuilder b) { + + b.rule(tryBlock).is( + CxxKeyword.TRY, compoundStatement, // C++ + b.firstOf( + b.sequence(handlerSeq, b.optional(cliFinallyClause)), // C++: handlerSeq; C++/CLI: cliFinallyClause + cliFinallyClause // C++/CLI + ) + ); + + b.rule(functionTryBlock).is( + CxxKeyword.TRY, b.optional(ctorInitializer), compoundStatement, // C++ + b.firstOf( + b.sequence(handlerSeq, b.optional(cliFinallyClause)), // C++: handlerSeq; C++/CLI: cliFinallyClause + cliFinallyClause // C++/CLI + ) + ); + + b.rule(handlerSeq).is( + b.oneOrMore(handler) // C++ + ).skipIfOneChild(); + + b.rule(cliFinallyClause).is( + "finally", compoundStatement // C++/CLI + ); + + b.rule(handler).is( + CxxKeyword.CATCH, "(", exceptionDeclaration, ")", compoundStatement // C++ + ); + + b.rule(exceptionDeclaration).is( + b.firstOf( + b.sequence( + b.optional(attributeSpecifierSeq), typeSpecifierSeq, + b.firstOf( + declarator, // C++ + b.optional(abstractDeclarator) // C++ + ) + ), + "..." // C++ + ) + ); + + b.rule(noexceptSpecifier).is( + b.firstOf( + b.sequence(CxxKeyword.NOEXCEPT, "(", constantExpression, ")"), // C++ + CxxKeyword.NOEXCEPT, // C++ + // removed with C++20, keep it for backward compatibility (C++ / Microsoft: typeIdList) + b.sequence(CxxKeyword.THROW, "(", b.optional(typeIdList), ")") + ) + ); + + b.rule(typeIdList).is( + b.firstOf( + b.sequence(typeId, b.optional("..."), b.zeroOrMore(",", typeId, b.optional("..."))), // C++ + "..." // Microsoft extension + ) + ); + + } + + private static void cliAttributes(LexerfulGrammarBuilder b) { + b.rule(cliAttributes).is( + b.oneOrMore(cliAttributeSection) + ); + + b.rule(cliAttributeSection).is( + "[", b.optional(cliAttributeTargetSpecifier), cliAttributeList, "]" + ); + + b.rule(cliAttributeTargetSpecifier).is( + cliAttributeTarget, ":" + ); + + b.rule(cliAttributeTarget).is( + b.firstOf( + "assembly", CxxKeyword.CLASS, "constructor", "delegate", CxxKeyword.ENUM, "event", "field", + "interface", "method", "parameter", "property", "returnvalue", CxxKeyword.STRUCT + )); + + b.rule(cliAttributeList).is( + cliAttribute, b.zeroOrMore(",", cliAttribute) + ); + + b.rule(cliAttribute).is( + b.optional(nestedNameSpecifier), typeName, b.optional(cliAttributeArguments) + ); + + b.rule(cliAttributeArguments).is( + "(", + b.firstOf( + b.optional(cliPositionArgumentList), + b.sequence(cliPositionArgumentList, ",", cliNamedArgumentList), + cliNamedArgumentList + ), + ")" + ); + + b.rule(cliPositionArgumentList).is( + cliPositionArgument, b.zeroOrMore(",", cliPositionArgument) + ); + + b.rule(cliPositionArgument).is( + cliAttributeArgumentExpression + ); + + b.rule(cliNamedArgumentList).is( + cliNamedArgument, b.zeroOrMore(",", cliNamedArgument) + ); + + b.rule(cliNamedArgument).is( + IDENTIFIER, "=", cliAttributeArgumentExpression + ); + + b.rule(cliAttributeArgumentExpression).is( + assignmentExpression + ); + + } + +}