| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <algorithm> |
| #include <cctype> |
| #include <set> |
| #include <unordered_map> |
| |
| #include "src/common/globals.h" |
| #include "src/torque/constants.h" |
| #include "src/torque/declarations.h" |
| #include "src/torque/earley-parser.h" |
| #include "src/torque/torque-parser.h" |
| #include "src/torque/utils.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace torque { |
| |
| DEFINE_CONTEXTUAL_VARIABLE(CurrentAst) |
| |
| using TypeList = std::vector<TypeExpression*>; |
| using GenericParameters = std::vector<Identifier*>; |
| |
| struct ExpressionWithSource { |
| Expression* expression; |
| std::string source; |
| }; |
| |
| struct TypeswitchCase { |
| SourcePosition pos; |
| base::Optional<std::string> name; |
| TypeExpression* type; |
| Statement* block; |
| }; |
| |
| class BuildFlags : public ContextualClass<BuildFlags> { |
| public: |
| BuildFlags() { |
| build_flags_["V8_SFI_HAS_UNIQUE_ID"] = V8_SFI_HAS_UNIQUE_ID; |
| build_flags_["TAGGED_SIZE_8_BYTES"] = TAGGED_SIZE_8_BYTES; |
| build_flags_["V8_DOUBLE_FIELDS_UNBOXING"] = V8_DOUBLE_FIELDS_UNBOXING; |
| build_flags_["TRUE_FOR_TESTING"] = true; |
| build_flags_["FALSE_FOR_TESTING"] = false; |
| } |
| static bool GetFlag(const std::string& name, const char* production) { |
| auto it = Get().build_flags_.find(name); |
| if (it == Get().build_flags_.end()) { |
| ReportError("Unknown flag used in ", production, ": ", name, |
| ". Please add it to the list in BuildFlags."); |
| } |
| return it->second; |
| } |
| |
| private: |
| std::unordered_map<std::string, bool> build_flags_; |
| }; |
| DEFINE_CONTEXTUAL_VARIABLE(BuildFlags) |
| |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<std::string>::id = |
| ParseResultTypeId::kStdString; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<bool>::id = |
| ParseResultTypeId::kBool; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<std::string>>::id = |
| ParseResultTypeId::kStdVectorOfString; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Declaration*>::id = |
| ParseResultTypeId::kDeclarationPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<TypeExpression*>::id = |
| ParseResultTypeId::kTypeExpressionPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<TypeExpression*>>::id = |
| ParseResultTypeId::kOptionalTypeExpressionPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<LabelBlock*>::id = |
| ParseResultTypeId::kLabelBlockPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<LabelBlock*>>::id = |
| ParseResultTypeId::kOptionalLabelBlockPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Expression*>::id = |
| ParseResultTypeId::kExpressionPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Identifier*>::id = |
| ParseResultTypeId::kIdentifierPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<Identifier*>>::id = |
| ParseResultTypeId::kOptionalIdentifierPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Statement*>::id = |
| ParseResultTypeId::kStatementPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<NameAndTypeExpression>::id = |
| ParseResultTypeId::kNameAndTypeExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<NameAndExpression>::id = |
| ParseResultTypeId::kNameAndExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<ConditionalAnnotation>::id = |
| ParseResultTypeId::kConditionalAnnotation; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<ConditionalAnnotation>>::id = |
| ParseResultTypeId::kOptionalConditionalAnnotation; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<ClassFieldExpression>::id = |
| ParseResultTypeId::kClassFieldExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<StructFieldExpression>::id = |
| ParseResultTypeId::kStructFieldExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<NameAndTypeExpression>>::id = |
| ParseResultTypeId::kStdVectorOfNameAndTypeExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<ImplicitParameters>::id = |
| ParseResultTypeId::kImplicitParameters; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<ImplicitParameters>>::id = |
| ParseResultTypeId::kOptionalImplicitParameters; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<NameAndExpression>>::id = |
| ParseResultTypeId::kStdVectorOfNameAndExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<ClassFieldExpression>>::id = |
| ParseResultTypeId::kStdVectorOfClassFieldExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<StructFieldExpression>>::id = |
| ParseResultTypeId::kStdVectorOfStructFieldExpression; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<IncrementDecrementOperator>::id = |
| ParseResultTypeId::kIncrementDecrementOperator; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<std::string>>::id = |
| ParseResultTypeId::kOptionalStdString; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<Statement*>>::id = |
| ParseResultTypeId::kStdVectorOfStatementPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<Declaration*>>::id = |
| ParseResultTypeId::kStdVectorOfDeclarationPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<std::vector<Declaration*>>>::id = |
| ParseResultTypeId::kStdVectorOfStdVectorOfDeclarationPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<Expression*>>::id = |
| ParseResultTypeId::kStdVectorOfExpressionPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<ExpressionWithSource>::id = |
| ParseResultTypeId::kExpressionWithSource; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<ParameterList>::id = |
| ParseResultTypeId::kParameterList; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<TypeList>::id = |
| ParseResultTypeId::kTypeList; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<TypeList>>::id = |
| ParseResultTypeId::kOptionalTypeList; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<LabelAndTypes>::id = |
| ParseResultTypeId::kLabelAndTypes; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<LabelAndTypes>>::id = |
| ParseResultTypeId::kStdVectorOfLabelAndTypes; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<LabelBlock*>>::id = |
| ParseResultTypeId::kStdVectorOfLabelBlockPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<Statement*>>::id = |
| ParseResultTypeId::kOptionalStatementPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<base::Optional<Expression*>>::id = |
| ParseResultTypeId::kOptionalExpressionPtr; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<TypeswitchCase>::id = ParseResultTypeId::kTypeswitchCase; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<TypeswitchCase>>::id = |
| ParseResultTypeId::kStdVectorOfTypeswitchCase; |
| template <> |
| V8_EXPORT_PRIVATE const ParseResultTypeId |
| ParseResultHolder<std::vector<Identifier*>>::id = |
| ParseResultTypeId::kStdVectorOfIdentifierPtr; |
| |
| namespace { |
| |
| base::Optional<ParseResult> AddGlobalDeclarations( |
| ParseResultIterator* child_results) { |
| auto declarations = child_results->NextAs<std::vector<Declaration*>>(); |
| for (Declaration* declaration : declarations) { |
| CurrentAst::Get().declarations().push_back(declaration); |
| } |
| return base::nullopt; |
| } |
| |
| void NamingConventionError(const std::string& type, const std::string& name, |
| const std::string& convention, |
| SourcePosition pos = CurrentSourcePosition::Get()) { |
| Lint(type, " \"", name, "\" does not follow \"", convention, |
| "\" naming convention.") |
| .Position(pos); |
| } |
| |
| void NamingConventionError(const std::string& type, const Identifier* name, |
| const std::string& convention) { |
| NamingConventionError(type, name->value, convention, name->pos); |
| } |
| |
| void LintGenericParameters(const GenericParameters& parameters) { |
| for (auto parameter : parameters) { |
| if (!IsUpperCamelCase(parameter->value)) { |
| NamingConventionError("Generic parameter", parameter, "UpperCamelCase"); |
| } |
| } |
| } |
| |
| base::Optional<ParseResult> ConcatList(ParseResultIterator* child_results) { |
| auto list_of_lists = |
| child_results->NextAs<std::vector<std::vector<Declaration*>>>(); |
| std::vector<Declaration*> result; |
| for (auto& list : list_of_lists) { |
| result.insert(result.end(), list.begin(), list.end()); |
| } |
| return ParseResult{result}; |
| } |
| |
| void CheckNotDeferredStatement(Statement* statement) { |
| CurrentSourcePosition::Scope source_position(statement->pos); |
| if (BlockStatement* block = BlockStatement::DynamicCast(statement)) { |
| if (block->deferred) { |
| Lint( |
| "cannot use deferred with a statement block here, it will have no " |
| "effect"); |
| } |
| } |
| } |
| |
| Expression* MakeCall(IdentifierExpression* callee, |
| base::Optional<Expression*> target, |
| std::vector<Expression*> arguments, |
| const std::vector<Statement*>& otherwise) { |
| std::vector<Identifier*> labels; |
| |
| // All IdentifierExpressions are treated as label names and can be directly |
| // used as labels identifiers. All other statements in a call's otherwise |
| // must create intermediate Labels for the otherwise's statement code. |
| size_t label_id = 0; |
| std::vector<LabelBlock*> temp_labels; |
| for (auto* statement : otherwise) { |
| if (auto* e = ExpressionStatement::DynamicCast(statement)) { |
| if (auto* id = IdentifierExpression::DynamicCast(e->expression)) { |
| if (id->generic_arguments.size() != 0) { |
| ReportError("An otherwise label cannot have generic parameters"); |
| } |
| labels.push_back(id->name); |
| continue; |
| } |
| } |
| auto label_name = std::string("__label") + std::to_string(label_id++); |
| auto label_id = MakeNode<Identifier>(label_name); |
| label_id->pos = SourcePosition::Invalid(); |
| labels.push_back(label_id); |
| auto* label_block = |
| MakeNode<LabelBlock>(label_id, ParameterList::Empty(), statement); |
| temp_labels.push_back(label_block); |
| } |
| |
| // Create nested try-label expression for all of the temporary Labels that |
| // were created. |
| Expression* result = nullptr; |
| if (target) { |
| result = MakeNode<CallMethodExpression>(*target, callee, arguments, labels); |
| } else { |
| result = MakeNode<CallExpression>(callee, arguments, labels); |
| } |
| |
| for (auto* label : temp_labels) { |
| result = MakeNode<TryLabelExpression>(false, result, label); |
| } |
| return result; |
| } |
| |
| Expression* MakeCall(Identifier* callee, |
| const std::vector<TypeExpression*>& generic_arguments, |
| const std::vector<Expression*>& arguments, |
| const std::vector<Statement*>& otherwise) { |
| return MakeCall(MakeNode<IdentifierExpression>(callee, generic_arguments), |
| base::nullopt, arguments, otherwise); |
| } |
| |
| base::Optional<ParseResult> MakeCall(ParseResultIterator* child_results) { |
| auto callee = child_results->NextAs<Expression*>(); |
| auto args = child_results->NextAs<std::vector<Expression*>>(); |
| auto otherwise = child_results->NextAs<std::vector<Statement*>>(); |
| IdentifierExpression* target = IdentifierExpression::cast(callee); |
| return ParseResult{MakeCall(target, base::nullopt, args, otherwise)}; |
| } |
| |
| base::Optional<ParseResult> MakeMethodCall(ParseResultIterator* child_results) { |
| auto this_arg = child_results->NextAs<Expression*>(); |
| auto callee = child_results->NextAs<std::string>(); |
| auto args = child_results->NextAs<std::vector<Expression*>>(); |
| auto otherwise = child_results->NextAs<std::vector<Statement*>>(); |
| return ParseResult{ |
| MakeCall(MakeNode<IdentifierExpression>(MakeNode<Identifier>(callee)), |
| this_arg, args, otherwise)}; |
| } |
| |
| base::Optional<ParseResult> MakeNewExpression( |
| ParseResultIterator* child_results) { |
| auto type = child_results->NextAs<TypeExpression*>(); |
| auto initializers = child_results->NextAs<std::vector<NameAndExpression>>(); |
| Expression* result = MakeNode<NewExpression>(type, std::move(initializers)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeBinaryOperator( |
| ParseResultIterator* child_results) { |
| auto left = child_results->NextAs<Expression*>(); |
| auto op = child_results->NextAs<Identifier*>(); |
| auto right = child_results->NextAs<Expression*>(); |
| return ParseResult{MakeCall(op, TypeList{}, |
| std::vector<Expression*>{left, right}, |
| std::vector<Statement*>{})}; |
| } |
| |
| base::Optional<ParseResult> MakeIntrinsicCallExpression( |
| ParseResultIterator* child_results) { |
| auto callee = child_results->NextAs<std::string>(); |
| auto generic_arguments = |
| child_results->NextAs<std::vector<TypeExpression*>>(); |
| auto args = child_results->NextAs<std::vector<Expression*>>(); |
| Expression* result = |
| MakeNode<IntrinsicCallExpression>(callee, generic_arguments, args); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeUnaryOperator( |
| ParseResultIterator* child_results) { |
| auto op = child_results->NextAs<Identifier*>(); |
| auto e = child_results->NextAs<Expression*>(); |
| return ParseResult{MakeCall(op, TypeList{}, std::vector<Expression*>{e}, |
| std::vector<Statement*>{})}; |
| } |
| |
| base::Optional<ParseResult> MakeSpreadExpression( |
| ParseResultIterator* child_results) { |
| auto spreadee = child_results->NextAs<Expression*>(); |
| Expression* result = MakeNode<SpreadExpression>(spreadee); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeImplicitParameterList( |
| ParseResultIterator* child_results) { |
| auto kind = child_results->NextAs<Identifier*>(); |
| auto parameters = child_results->NextAs<std::vector<NameAndTypeExpression>>(); |
| return ParseResult{ImplicitParameters{kind, parameters}}; |
| } |
| |
| void AddParameter(ParameterList* parameter_list, |
| const NameAndTypeExpression& param) { |
| if (!IsLowerCamelCase(param.name->value)) { |
| NamingConventionError("Parameter", param.name, "lowerCamelCase"); |
| } |
| parameter_list->names.push_back(param.name); |
| parameter_list->types.push_back(param.type); |
| } |
| |
| template <bool has_varargs, bool has_explicit_parameter_names> |
| base::Optional<ParseResult> MakeParameterList( |
| ParseResultIterator* child_results) { |
| auto implicit_params = |
| child_results->NextAs<base::Optional<ImplicitParameters>>(); |
| ParameterList result; |
| result.has_varargs = has_varargs; |
| result.implicit_count = 0; |
| result.implicit_kind = ImplicitKind::kNoImplicit; |
| if (implicit_params) { |
| result.implicit_count = implicit_params->parameters.size(); |
| if (implicit_params->kind->value == "implicit") { |
| result.implicit_kind = ImplicitKind::kImplicit; |
| } else { |
| DCHECK_EQ(implicit_params->kind->value, "js-implicit"); |
| result.implicit_kind = ImplicitKind::kJSImplicit; |
| } |
| result.implicit_kind_pos = implicit_params->kind->pos; |
| for (NameAndTypeExpression& implicit_param : implicit_params->parameters) { |
| AddParameter(&result, implicit_param); |
| } |
| } |
| if (has_explicit_parameter_names) { |
| auto explicit_params = |
| child_results->NextAs<std::vector<NameAndTypeExpression>>(); |
| std::string arguments_variable = ""; |
| if (has_varargs) { |
| arguments_variable = child_results->NextAs<std::string>(); |
| } |
| for (NameAndTypeExpression& param : explicit_params) { |
| AddParameter(&result, param); |
| } |
| result.arguments_variable = arguments_variable; |
| } else { |
| auto explicit_types = child_results->NextAs<TypeList>(); |
| for (auto* explicit_type : explicit_types) { |
| result.types.push_back(explicit_type); |
| } |
| } |
| return ParseResult{std::move(result)}; |
| } |
| |
| base::Optional<ParseResult> MakeAssertStatement( |
| ParseResultIterator* child_results) { |
| auto kind = child_results->NextAs<Identifier*>()->value; |
| auto expr_with_source = child_results->NextAs<ExpressionWithSource>(); |
| DCHECK(kind == "assert" || kind == "check"); |
| Statement* result = MakeNode<AssertStatement>( |
| kind == "assert", expr_with_source.expression, expr_with_source.source); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeDebugStatement( |
| ParseResultIterator* child_results) { |
| auto kind = child_results->NextAs<Identifier*>()->value; |
| DCHECK(kind == "unreachable" || kind == "debug"); |
| Statement* result = MakeNode<DebugStatement>(kind, kind == "unreachable"); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeVoidType(ParseResultIterator* child_results) { |
| TypeExpression* result = MakeNode<BasicTypeExpression>( |
| std::vector<std::string>{}, "void", std::vector<TypeExpression*>{}); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeExternalMacro( |
| ParseResultIterator* child_results) { |
| auto transitioning = child_results->NextAs<bool>(); |
| auto operator_name = child_results->NextAs<base::Optional<std::string>>(); |
| auto external_assembler_name = |
| child_results->NextAs<base::Optional<std::string>>(); |
| auto name = child_results->NextAs<std::string>(); |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); |
| LintGenericParameters(generic_parameters); |
| |
| auto args = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| auto labels = child_results->NextAs<LabelAndTypesVector>(); |
| MacroDeclaration* macro = MakeNode<ExternalMacroDeclaration>( |
| transitioning, |
| external_assembler_name ? *external_assembler_name : "CodeStubAssembler", |
| name, operator_name, args, return_type, labels); |
| Declaration* result; |
| if (generic_parameters.empty()) { |
| result = MakeNode<StandardDeclaration>(macro, base::nullopt); |
| } else { |
| result = MakeNode<GenericDeclaration>(macro, generic_parameters); |
| } |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeIntrinsicDeclaration( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<std::string>(); |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); |
| LintGenericParameters(generic_parameters); |
| |
| auto args = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| auto body = child_results->NextAs<base::Optional<Statement*>>(); |
| LabelAndTypesVector labels; |
| CallableNode* callable = nullptr; |
| if (body) { |
| callable = MakeNode<TorqueMacroDeclaration>( |
| false, name, base::Optional<std::string>{}, args, return_type, labels, |
| false); |
| } else { |
| callable = MakeNode<IntrinsicDeclaration>(name, args, return_type); |
| } |
| Declaration* result; |
| if (generic_parameters.empty()) { |
| result = MakeNode<StandardDeclaration>(callable, body); |
| } else { |
| result = MakeNode<GenericDeclaration>(callable, generic_parameters, body); |
| } |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeTorqueMacroDeclaration( |
| ParseResultIterator* child_results) { |
| auto export_to_csa = child_results->NextAs<bool>(); |
| auto transitioning = child_results->NextAs<bool>(); |
| auto operator_name = child_results->NextAs<base::Optional<std::string>>(); |
| auto name = child_results->NextAs<std::string>(); |
| if (!IsUpperCamelCase(name)) { |
| NamingConventionError("Macro", name, "UpperCamelCase"); |
| } |
| |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); |
| LintGenericParameters(generic_parameters); |
| |
| auto args = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| auto labels = child_results->NextAs<LabelAndTypesVector>(); |
| auto body = child_results->NextAs<base::Optional<Statement*>>(); |
| MacroDeclaration* macro = |
| MakeNode<TorqueMacroDeclaration>(transitioning, name, operator_name, args, |
| return_type, labels, export_to_csa); |
| Declaration* result; |
| if (generic_parameters.empty()) { |
| if (!body) ReportError("A non-generic declaration needs a body."); |
| result = MakeNode<StandardDeclaration>(macro, *body); |
| } else { |
| if (export_to_csa) ReportError("Cannot export generics to CSA."); |
| result = MakeNode<GenericDeclaration>(macro, generic_parameters, body); |
| } |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeTorqueBuiltinDeclaration( |
| ParseResultIterator* child_results) { |
| auto transitioning = child_results->NextAs<bool>(); |
| auto javascript_linkage = child_results->NextAs<bool>(); |
| auto name = child_results->NextAs<std::string>(); |
| if (!IsUpperCamelCase(name)) { |
| NamingConventionError("Builtin", name, "UpperCamelCase"); |
| } |
| |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); |
| LintGenericParameters(generic_parameters); |
| |
| auto args = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| auto body = child_results->NextAs<base::Optional<Statement*>>(); |
| BuiltinDeclaration* builtin = MakeNode<TorqueBuiltinDeclaration>( |
| transitioning, javascript_linkage, name, args, return_type); |
| Declaration* result; |
| if (generic_parameters.empty()) { |
| if (!body) ReportError("A non-generic declaration needs a body."); |
| result = MakeNode<StandardDeclaration>(builtin, *body); |
| } else { |
| result = MakeNode<GenericDeclaration>(builtin, generic_parameters, body); |
| } |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeConstDeclaration( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| if (!IsValidNamespaceConstName(name->value)) { |
| NamingConventionError("Constant", name, "kUpperCamelCase"); |
| } |
| |
| auto type = child_results->NextAs<TypeExpression*>(); |
| auto expression = child_results->NextAs<Expression*>(); |
| Declaration* result = MakeNode<ConstDeclaration>(name, type, expression); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeExternConstDeclaration( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| auto type = child_results->NextAs<TypeExpression*>(); |
| auto literal = child_results->NextAs<std::string>(); |
| Declaration* result = |
| MakeNode<ExternConstDeclaration>(name, type, std::move(literal)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeTypeAliasDeclaration( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| auto type = child_results->NextAs<TypeExpression*>(); |
| Declaration* result = MakeNode<TypeAliasDeclaration>(name, type); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeAbstractTypeDeclaration( |
| ParseResultIterator* child_results) { |
| auto transient = child_results->NextAs<bool>(); |
| auto name = child_results->NextAs<Identifier*>(); |
| if (!IsValidTypeName(name->value)) { |
| NamingConventionError("Type", name, "UpperCamelCase"); |
| } |
| auto extends = child_results->NextAs<base::Optional<Identifier*>>(); |
| auto generates = child_results->NextAs<base::Optional<std::string>>(); |
| Declaration* decl = MakeNode<AbstractTypeDeclaration>( |
| name, transient, extends, std::move(generates)); |
| |
| auto constexpr_generates = |
| child_results->NextAs<base::Optional<std::string>>(); |
| std::vector<Declaration*> result{decl}; |
| |
| if (constexpr_generates) { |
| // Create a AbstractTypeDeclaration for the associated constexpr type. |
| Identifier* constexpr_name = |
| MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + name->value); |
| constexpr_name->pos = name->pos; |
| |
| base::Optional<Identifier*> constexpr_extends; |
| if (extends) { |
| constexpr_extends = |
| MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*extends)->value); |
| (*constexpr_extends)->pos = name->pos; |
| } |
| AbstractTypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>( |
| constexpr_name, transient, constexpr_extends, constexpr_generates); |
| constexpr_decl->pos = name->pos; |
| result.push_back(constexpr_decl); |
| } |
| |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeMethodDeclaration( |
| ParseResultIterator* child_results) { |
| auto transitioning = child_results->NextAs<bool>(); |
| auto operator_name = child_results->NextAs<base::Optional<std::string>>(); |
| auto name = child_results->NextAs<std::string>(); |
| if (!IsUpperCamelCase(name)) { |
| NamingConventionError("Method", name, "UpperCamelCase"); |
| } |
| |
| auto args = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| auto labels = child_results->NextAs<LabelAndTypesVector>(); |
| auto body = child_results->NextAs<Statement*>(); |
| MacroDeclaration* macro = MakeNode<TorqueMacroDeclaration>( |
| transitioning, name, operator_name, args, return_type, labels, false); |
| Declaration* result = MakeNode<StandardDeclaration>(macro, body); |
| return ParseResult{result}; |
| } |
| |
| class AnnotationSet { |
| public: |
| AnnotationSet(ParseResultIterator* iter, |
| const std::set<std::string>& allowed) { |
| auto list = iter->NextAs<std::vector<Identifier*>>(); |
| for (const Identifier* i : list) { |
| if (allowed.find(i->value) == allowed.end()) { |
| Lint("Annotation ", i->value, " is not allowed here").Position(i->pos); |
| } |
| if (!set_.insert(i->value).second) { |
| Lint("Duplicate annotation ", i->value).Position(i->pos); |
| } |
| } |
| } |
| |
| bool Contains(const std::string& s) { return set_.find(s) != set_.end(); } |
| |
| private: |
| std::set<std::string> set_; |
| }; |
| |
| base::Optional<ParseResult> MakeClassDeclaration( |
| ParseResultIterator* child_results) { |
| AnnotationSet annotations( |
| child_results, {"@generatePrint", "@noVerifier", "@abstract", |
| "@dirtyInstantiatedAbstractClass", |
| "@hasSameInstanceTypeAsParent", "@generateCppClass"}); |
| ClassFlags flags = ClassFlag::kNone; |
| bool generate_print = annotations.Contains("@generatePrint"); |
| if (generate_print) flags |= ClassFlag::kGeneratePrint; |
| bool generate_verify = !annotations.Contains("@noVerifier"); |
| if (generate_verify) flags |= ClassFlag::kGenerateVerify; |
| if (annotations.Contains("@abstract")) { |
| flags |= ClassFlag::kAbstract; |
| } |
| if (annotations.Contains("@dirtyInstantiatedAbstractClass")) { |
| flags |= ClassFlag::kInstantiatedAbstractClass; |
| } |
| if (annotations.Contains("@hasSameInstanceTypeAsParent")) { |
| flags |= ClassFlag::kHasSameInstanceTypeAsParent; |
| } |
| if (annotations.Contains("@generateCppClass")) { |
| flags |= ClassFlag::kGenerateCppClassDefinitions; |
| } |
| auto is_extern = child_results->NextAs<bool>(); |
| if (is_extern) flags |= ClassFlag::kExtern; |
| auto transient = child_results->NextAs<bool>(); |
| if (transient) flags |= ClassFlag::kTransient; |
| auto name = child_results->NextAs<Identifier*>(); |
| if (!IsValidTypeName(name->value)) { |
| NamingConventionError("Type", name, "UpperCamelCase"); |
| } |
| auto extends = child_results->NextAs<base::Optional<TypeExpression*>>(); |
| if (extends && !BasicTypeExpression::DynamicCast(*extends)) { |
| ReportError("Expected type name in extends clause."); |
| } |
| auto generates = child_results->NextAs<base::Optional<std::string>>(); |
| auto methods = child_results->NextAs<std::vector<Declaration*>>(); |
| auto fields_raw = child_results->NextAs<std::vector<ClassFieldExpression>>(); |
| |
| // Filter to only include fields that should be present based on decoration. |
| std::vector<ClassFieldExpression> fields; |
| std::copy_if(fields_raw.begin(), fields_raw.end(), std::back_inserter(fields), |
| [](const ClassFieldExpression& exp) { |
| if (!exp.conditional.has_value()) return true; |
| const ConditionalAnnotation& conditional = *exp.conditional; |
| return conditional.type == ConditionalAnnotationType::kPositive |
| ? BuildFlags::GetFlag(conditional.condition, "@if") |
| : !BuildFlags::GetFlag(conditional.condition, |
| "@ifnot"); |
| }); |
| |
| Declaration* result = MakeNode<ClassDeclaration>( |
| name, flags, std::move(extends), std::move(generates), std::move(methods), |
| fields); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeNamespaceDeclaration( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<std::string>(); |
| if (!IsSnakeCase(name)) { |
| NamingConventionError("Namespace", name, "snake_case"); |
| } |
| auto declarations = child_results->NextAs<std::vector<Declaration*>>(); |
| Declaration* result = |
| MakeNode<NamespaceDeclaration>(std::move(name), std::move(declarations)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeSpecializationDeclaration( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| auto generic_parameters = |
| child_results->NextAs<std::vector<TypeExpression*>>(); |
| auto parameters = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| auto labels = child_results->NextAs<LabelAndTypesVector>(); |
| auto body = child_results->NextAs<Statement*>(); |
| CheckNotDeferredStatement(body); |
| Declaration* result = MakeNode<SpecializationDeclaration>( |
| std::move(name), std::move(generic_parameters), std::move(parameters), |
| return_type, std::move(labels), body); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeStructDeclaration( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| if (!IsValidTypeName(name->value)) { |
| NamingConventionError("Struct", name, "UpperCamelCase"); |
| } |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); |
| LintGenericParameters(generic_parameters); |
| auto methods = child_results->NextAs<std::vector<Declaration*>>(); |
| auto fields = child_results->NextAs<std::vector<StructFieldExpression>>(); |
| Declaration* result = |
| MakeNode<StructDeclaration>(name, std::move(methods), std::move(fields), |
| std::move(generic_parameters)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeCppIncludeDeclaration( |
| ParseResultIterator* child_results) { |
| auto include_path = child_results->NextAs<std::string>(); |
| Declaration* result = |
| MakeNode<CppIncludeDeclaration>(std::move(include_path)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> ProcessTorqueImportDeclaration( |
| ParseResultIterator* child_results) { |
| auto import_path = child_results->NextAs<std::string>(); |
| if (!SourceFileMap::FileRelativeToV8RootExists(import_path)) { |
| Error("File '", import_path, "' not found."); |
| } |
| |
| auto import_id = SourceFileMap::GetSourceId(import_path); |
| if (!import_id.IsValid()) { |
| // TODO(szuend): Instead of reporting and error. Queue the file up |
| // for compilation. |
| Error("File '", import_path, "'is not part of the source set.").Throw(); |
| } |
| |
| CurrentAst::Get().DeclareImportForCurrentFile(import_id); |
| |
| return base::nullopt; |
| } |
| |
| base::Optional<ParseResult> MakeExternalBuiltin( |
| ParseResultIterator* child_results) { |
| auto transitioning = child_results->NextAs<bool>(); |
| auto js_linkage = child_results->NextAs<bool>(); |
| auto name = child_results->NextAs<std::string>(); |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); |
| LintGenericParameters(generic_parameters); |
| |
| auto args = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| BuiltinDeclaration* builtin = MakeNode<ExternalBuiltinDeclaration>( |
| transitioning, js_linkage, name, args, return_type); |
| Declaration* result; |
| if (generic_parameters.empty()) { |
| result = MakeNode<StandardDeclaration>(builtin, base::nullopt); |
| } else { |
| result = MakeNode<GenericDeclaration>(builtin, generic_parameters); |
| } |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeExternalRuntime( |
| ParseResultIterator* child_results) { |
| auto transitioning = child_results->NextAs<bool>(); |
| auto name = child_results->NextAs<std::string>(); |
| auto args = child_results->NextAs<ParameterList>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| ExternalRuntimeDeclaration* runtime = MakeNode<ExternalRuntimeDeclaration>( |
| transitioning, name, args, return_type); |
| Declaration* result = MakeNode<StandardDeclaration>(runtime, base::nullopt); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> StringLiteralUnquoteAction( |
| ParseResultIterator* child_results) { |
| return ParseResult{ |
| StringLiteralUnquote(child_results->NextAs<std::string>())}; |
| } |
| |
| base::Optional<ParseResult> MakeBasicTypeExpression( |
| ParseResultIterator* child_results) { |
| auto namespace_qualification = |
| child_results->NextAs<std::vector<std::string>>(); |
| auto is_constexpr = child_results->NextAs<bool>(); |
| auto name = child_results->NextAs<std::string>(); |
| auto generic_arguments = |
| child_results->NextAs<std::vector<TypeExpression*>>(); |
| TypeExpression* result = MakeNode<BasicTypeExpression>( |
| std::move(namespace_qualification), |
| is_constexpr ? GetConstexprName(name) : std::move(name), |
| std::move(generic_arguments)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeFunctionTypeExpression( |
| ParseResultIterator* child_results) { |
| auto parameters = child_results->NextAs<std::vector<TypeExpression*>>(); |
| auto return_type = child_results->NextAs<TypeExpression*>(); |
| TypeExpression* result = |
| MakeNode<FunctionTypeExpression>(std::move(parameters), return_type); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeReferenceTypeExpression( |
| ParseResultIterator* child_results) { |
| auto referenced_type = child_results->NextAs<TypeExpression*>(); |
| TypeExpression* result = MakeNode<ReferenceTypeExpression>(referenced_type); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeUnionTypeExpression( |
| ParseResultIterator* child_results) { |
| auto a = child_results->NextAs<TypeExpression*>(); |
| auto b = child_results->NextAs<TypeExpression*>(); |
| TypeExpression* result = MakeNode<UnionTypeExpression>(a, b); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeExpressionStatement( |
| ParseResultIterator* child_results) { |
| auto expression = child_results->NextAs<Expression*>(); |
| Statement* result = MakeNode<ExpressionStatement>(expression); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeIfStatement( |
| ParseResultIterator* child_results) { |
| auto is_constexpr = child_results->NextAs<bool>(); |
| auto condition = child_results->NextAs<Expression*>(); |
| auto if_true = child_results->NextAs<Statement*>(); |
| auto if_false = child_results->NextAs<base::Optional<Statement*>>(); |
| |
| if (if_false && !(BlockStatement::DynamicCast(if_true) && |
| (BlockStatement::DynamicCast(*if_false) || |
| IfStatement::DynamicCast(*if_false)))) { |
| ReportError("if-else statements require curly braces"); |
| } |
| |
| if (is_constexpr) { |
| CheckNotDeferredStatement(if_true); |
| if (if_false) CheckNotDeferredStatement(*if_false); |
| } |
| |
| Statement* result = |
| MakeNode<IfStatement>(is_constexpr, condition, if_true, if_false); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeTypeswitchStatement( |
| ParseResultIterator* child_results) { |
| auto expression = child_results->NextAs<Expression*>(); |
| auto cases = child_results->NextAs<std::vector<TypeswitchCase>>(); |
| CurrentSourcePosition::Scope current_source_position( |
| child_results->matched_input().pos); |
| |
| // typeswitch (expression) case (x1 : T1) { |
| // ...b1 |
| // } case (x2 : T2) { |
| // ...b2 |
| // } case (x3 : T3) { |
| // ...b3 |
| // } |
| // |
| // desugars to |
| // |
| // { |
| // const _value = expression; |
| // try { |
| // const x1 : T1 = cast<T1>(_value) otherwise _NextCase; |
| // ...b1 |
| // } label _NextCase { |
| // try { |
| // const x2 : T2 = cast<T2>(%assume_impossible<T1>(_value)); |
| // ...b2 |
| // } label _NextCase { |
| // const x3 : T3 = %assume_impossible<T1|T2>(_value); |
| // ...b3 |
| // } |
| // } |
| // } |
| |
| BlockStatement* current_block = MakeNode<BlockStatement>(); |
| Statement* result = current_block; |
| { |
| CurrentSourcePosition::Scope current_source_position(expression->pos); |
| current_block->statements.push_back(MakeNode<VarDeclarationStatement>( |
| true, MakeNode<Identifier>("__value"), base::nullopt, expression)); |
| } |
| |
| TypeExpression* accumulated_types; |
| for (size_t i = 0; i < cases.size(); ++i) { |
| CurrentSourcePosition::Scope current_source_position(cases[i].pos); |
| Expression* value = |
| MakeNode<IdentifierExpression>(MakeNode<Identifier>("__value")); |
| if (i >= 1) { |
| value = |
| MakeNode<AssumeTypeImpossibleExpression>(accumulated_types, value); |
| } |
| BlockStatement* case_block; |
| if (i < cases.size() - 1) { |
| value = MakeCall(MakeNode<Identifier>("Cast"), |
| std::vector<TypeExpression*>{cases[i].type}, |
| std::vector<Expression*>{value}, |
| std::vector<Statement*>{MakeNode<ExpressionStatement>( |
| MakeNode<IdentifierExpression>( |
| MakeNode<Identifier>(kNextCaseLabelName)))}); |
| case_block = MakeNode<BlockStatement>(); |
| } else { |
| case_block = current_block; |
| } |
| std::string name = "__case_value"; |
| if (cases[i].name) name = *cases[i].name; |
| case_block->statements.push_back(MakeNode<VarDeclarationStatement>( |
| true, MakeNode<Identifier>(name), cases[i].type, value)); |
| case_block->statements.push_back(cases[i].block); |
| if (i < cases.size() - 1) { |
| BlockStatement* next_block = MakeNode<BlockStatement>(); |
| current_block->statements.push_back( |
| MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>( |
| false, MakeNode<StatementExpression>(case_block), |
| MakeNode<LabelBlock>(MakeNode<Identifier>(kNextCaseLabelName), |
| ParameterList::Empty(), next_block)))); |
| current_block = next_block; |
| } |
| accumulated_types = |
| i > 0 ? MakeNode<UnionTypeExpression>(accumulated_types, cases[i].type) |
| : cases[i].type; |
| } |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeTypeswitchCase( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<base::Optional<std::string>>(); |
| auto type = child_results->NextAs<TypeExpression*>(); |
| auto block = child_results->NextAs<Statement*>(); |
| return ParseResult{TypeswitchCase{child_results->matched_input().pos, |
| std::move(name), type, block}}; |
| } |
| |
| base::Optional<ParseResult> MakeWhileStatement( |
| ParseResultIterator* child_results) { |
| auto condition = child_results->NextAs<Expression*>(); |
| auto body = child_results->NextAs<Statement*>(); |
| Statement* result = MakeNode<WhileStatement>(condition, body); |
| CheckNotDeferredStatement(result); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeReturnStatement( |
| ParseResultIterator* child_results) { |
| auto value = child_results->NextAs<base::Optional<Expression*>>(); |
| Statement* result = MakeNode<ReturnStatement>(value); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeTailCallStatement( |
| ParseResultIterator* child_results) { |
| auto value = child_results->NextAs<Expression*>(); |
| Statement* result = MakeNode<TailCallStatement>(CallExpression::cast(value)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeVarDeclarationStatement( |
| ParseResultIterator* child_results) { |
| auto kind = child_results->NextAs<Identifier*>(); |
| bool const_qualified = kind->value == "const"; |
| if (!const_qualified) DCHECK_EQ("let", kind->value); |
| auto name = child_results->NextAs<Identifier*>(); |
| if (!IsLowerCamelCase(name->value)) { |
| NamingConventionError("Variable", name, "lowerCamelCase"); |
| } |
| |
| auto type = child_results->NextAs<base::Optional<TypeExpression*>>(); |
| base::Optional<Expression*> initializer; |
| if (child_results->HasNext()) |
| initializer = child_results->NextAs<Expression*>(); |
| if (!initializer && !type) { |
| ReportError("Declaration is missing a type."); |
| } |
| Statement* result = MakeNode<VarDeclarationStatement>(const_qualified, name, |
| type, initializer); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeBreakStatement( |
| ParseResultIterator* child_results) { |
| Statement* result = MakeNode<BreakStatement>(); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeContinueStatement( |
| ParseResultIterator* child_results) { |
| Statement* result = MakeNode<ContinueStatement>(); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeGotoStatement( |
| ParseResultIterator* child_results) { |
| auto label = child_results->NextAs<Identifier*>(); |
| auto arguments = child_results->NextAs<std::vector<Expression*>>(); |
| Statement* result = MakeNode<GotoStatement>(label, std::move(arguments)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeBlockStatement( |
| ParseResultIterator* child_results) { |
| auto deferred = child_results->NextAs<bool>(); |
| auto statements = child_results->NextAs<std::vector<Statement*>>(); |
| for (Statement* statement : statements) { |
| CheckNotDeferredStatement(statement); |
| } |
| Statement* result = MakeNode<BlockStatement>(deferred, std::move(statements)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeTryLabelExpression( |
| ParseResultIterator* child_results) { |
| auto try_block = child_results->NextAs<Statement*>(); |
| CheckNotDeferredStatement(try_block); |
| Statement* result = try_block; |
| auto label_blocks = child_results->NextAs<std::vector<LabelBlock*>>(); |
| auto catch_block = child_results->NextAs<base::Optional<LabelBlock*>>(); |
| for (auto block : label_blocks) { |
| result = MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>( |
| false, MakeNode<StatementExpression>(result), block)); |
| } |
| if (catch_block) { |
| result = MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>( |
| true, MakeNode<StatementExpression>(result), *catch_block)); |
| } |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeForLoopStatement( |
| ParseResultIterator* child_results) { |
| auto var_decl = child_results->NextAs<base::Optional<Statement*>>(); |
| auto test = child_results->NextAs<base::Optional<Expression*>>(); |
| auto action = child_results->NextAs<base::Optional<Expression*>>(); |
| base::Optional<Statement*> action_stmt; |
| if (action) action_stmt = MakeNode<ExpressionStatement>(*action); |
| auto body = child_results->NextAs<Statement*>(); |
| CheckNotDeferredStatement(body); |
| Statement* result = |
| MakeNode<ForLoopStatement>(var_decl, test, action_stmt, body); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeLabelBlock(ParseResultIterator* child_results) { |
| auto label = child_results->NextAs<Identifier*>(); |
| if (!IsUpperCamelCase(label->value)) { |
| NamingConventionError("Label", label, "UpperCamelCase"); |
| } |
| auto parameters = child_results->NextAs<ParameterList>(); |
| auto body = child_results->NextAs<Statement*>(); |
| LabelBlock* result = MakeNode<LabelBlock>(label, std::move(parameters), body); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeCatchBlock(ParseResultIterator* child_results) { |
| auto variable = child_results->NextAs<std::string>(); |
| auto body = child_results->NextAs<Statement*>(); |
| if (!IsLowerCamelCase(variable)) { |
| NamingConventionError("Exception", variable, "lowerCamelCase"); |
| } |
| ParameterList parameters; |
| parameters.names.push_back(MakeNode<Identifier>(variable)); |
| parameters.types.push_back(MakeNode<BasicTypeExpression>( |
| std::vector<std::string>{}, "Object", std::vector<TypeExpression*>{})); |
| parameters.has_varargs = false; |
| LabelBlock* result = MakeNode<LabelBlock>( |
| MakeNode<Identifier>(kCatchLabelName), std::move(parameters), body); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeExpressionWithSource( |
| ParseResultIterator* child_results) { |
| auto e = child_results->NextAs<Expression*>(); |
| return ParseResult{ |
| ExpressionWithSource{e, child_results->matched_input().ToString()}}; |
| } |
| |
| base::Optional<ParseResult> MakeIdentifier(ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<std::string>(); |
| Identifier* result = MakeNode<Identifier>(std::move(name)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeIdentifierFromMatchedInput( |
| ParseResultIterator* child_results) { |
| return ParseResult{ |
| MakeNode<Identifier>(child_results->matched_input().ToString())}; |
| } |
| |
| base::Optional<ParseResult> MakeRightShiftIdentifier( |
| ParseResultIterator* child_results) { |
| std::string str = child_results->matched_input().ToString(); |
| for (auto character : str) { |
| if (character != '>') { |
| ReportError("right-shift operators may not contain any whitespace"); |
| } |
| } |
| return ParseResult{MakeNode<Identifier>(str)}; |
| } |
| |
| base::Optional<ParseResult> MakeIdentifierExpression( |
| ParseResultIterator* child_results) { |
| auto namespace_qualification = |
| child_results->NextAs<std::vector<std::string>>(); |
| auto name = child_results->NextAs<Identifier*>(); |
| auto generic_arguments = |
| child_results->NextAs<std::vector<TypeExpression*>>(); |
| Expression* result = MakeNode<IdentifierExpression>( |
| std::move(namespace_qualification), name, std::move(generic_arguments)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeFieldAccessExpression( |
| ParseResultIterator* child_results) { |
| auto object = child_results->NextAs<Expression*>(); |
| auto field = child_results->NextAs<Identifier*>(); |
| Expression* result = MakeNode<FieldAccessExpression>(object, field); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeElementAccessExpression( |
| ParseResultIterator* child_results) { |
| auto object = child_results->NextAs<Expression*>(); |
| auto field = child_results->NextAs<Expression*>(); |
| Expression* result = MakeNode<ElementAccessExpression>(object, field); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeDereferenceExpression( |
| ParseResultIterator* child_results) { |
| auto reference = child_results->NextAs<Expression*>(); |
| Expression* result = MakeNode<DereferenceExpression>(reference); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeStructExpression( |
| ParseResultIterator* child_results) { |
| auto type = child_results->NextAs<TypeExpression*>(); |
| auto initializers = child_results->NextAs<std::vector<NameAndExpression>>(); |
| Expression* result = |
| MakeNode<StructExpression>(type, std::move(initializers)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeAssignmentExpression( |
| ParseResultIterator* child_results) { |
| auto location = child_results->NextAs<Expression*>(); |
| auto op = child_results->NextAs<base::Optional<std::string>>(); |
| auto value = child_results->NextAs<Expression*>(); |
| Expression* result = |
| MakeNode<AssignmentExpression>(location, std::move(op), value); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeNumberLiteralExpression( |
| ParseResultIterator* child_results) { |
| auto number = child_results->NextAs<std::string>(); |
| Expression* result = MakeNode<NumberLiteralExpression>(std::move(number)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeStringLiteralExpression( |
| ParseResultIterator* child_results) { |
| auto literal = child_results->NextAs<std::string>(); |
| Expression* result = MakeNode<StringLiteralExpression>(std::move(literal)); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeIncrementDecrementExpressionPostfix( |
| ParseResultIterator* child_results) { |
| auto location = child_results->NextAs<Expression*>(); |
| auto op = child_results->NextAs<IncrementDecrementOperator>(); |
| Expression* result = |
| MakeNode<IncrementDecrementExpression>(location, op, true); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeIncrementDecrementExpressionPrefix( |
| ParseResultIterator* child_results) { |
| auto op = child_results->NextAs<IncrementDecrementOperator>(); |
| auto location = child_results->NextAs<Expression*>(); |
| Expression* result = |
| MakeNode<IncrementDecrementExpression>(location, op, false); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeLogicalOrExpression( |
| ParseResultIterator* child_results) { |
| auto left = child_results->NextAs<Expression*>(); |
| auto right = child_results->NextAs<Expression*>(); |
| Expression* result = MakeNode<LogicalOrExpression>(left, right); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeLogicalAndExpression( |
| ParseResultIterator* child_results) { |
| auto left = child_results->NextAs<Expression*>(); |
| auto right = child_results->NextAs<Expression*>(); |
| Expression* result = MakeNode<LogicalAndExpression>(left, right); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeConditionalExpression( |
| ParseResultIterator* child_results) { |
| auto condition = child_results->NextAs<Expression*>(); |
| auto if_true = child_results->NextAs<Expression*>(); |
| auto if_false = child_results->NextAs<Expression*>(); |
| Expression* result = |
| MakeNode<ConditionalExpression>(condition, if_true, if_false); |
| return ParseResult{result}; |
| } |
| |
| base::Optional<ParseResult> MakeLabelAndTypes( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| if (!IsUpperCamelCase(name->value)) { |
| NamingConventionError("Label", name, "UpperCamelCase"); |
| } |
| auto types = child_results->NextAs<std::vector<TypeExpression*>>(); |
| return ParseResult{LabelAndTypes{name, std::move(types)}}; |
| } |
| |
| base::Optional<ParseResult> MakeNameAndType( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| auto type = child_results->NextAs<TypeExpression*>(); |
| return ParseResult{NameAndTypeExpression{name, type}}; |
| } |
| |
| base::Optional<ParseResult> MakeNameAndExpression( |
| ParseResultIterator* child_results) { |
| auto name = child_results->NextAs<Identifier*>(); |
| auto expression = child_results->NextAs<Expression*>(); |
| return ParseResult{NameAndExpression{name, expression}}; |
| } |
| |
| base::Optional<ParseResult> MakeNameAndExpressionFromExpression( |
| ParseResultIterator* child_results) { |
| auto expression = child_results->NextAs<Expression*>(); |
| if (auto* id = IdentifierExpression::DynamicCast(expression)) { |
| if (!id->generic_arguments.empty() || |
| !id->namespace_qualification.empty()) { |
| ReportError("expected a plain identifier without qualification"); |
| } |
| return ParseResult{NameAndExpression{id->name, id}}; |
| } |
| ReportError("Constructor parameters need to be named."); |
| } |
| |
| base::Optional<ParseResult> MakeConditionalAnnotation( |
| ParseResultIterator* child_results) { |
| auto type_str = child_results->NextAs<Identifier*>()->value; |
| DCHECK(type_str == "@if" || type_str == "@ifnot"); |
| ConditionalAnnotationType type = type_str == "@if" |
| ? ConditionalAnnotationType::kPositive |
| : ConditionalAnnotationType::kNegative; |
| auto condition = child_results->NextAs<std::string>(); |
| return ParseResult{ConditionalAnnotation{condition, type}}; |
| } |
| |
| base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) { |
| auto conditional = |
| child_results->NextAs<base::Optional<ConditionalAnnotation>>(); |
| AnnotationSet annotations(child_results, {"@noVerifier"}); |
| bool generate_verify = !annotations.Contains("@noVerifier"); |
| auto weak = child_results->NextAs<bool>(); |
| auto const_qualified = child_results->NextAs<bool>(); |
| auto name = child_results->NextAs<Identifier*>(); |
| auto index = child_results->NextAs<base::Optional<std::string>>(); |
| auto type = child_results->NextAs<TypeExpression*>(); |
| return ParseResult{ClassFieldExpression{{name, type}, |
| index, |
| conditional, |
| weak, |
| const_qualified, |
| generate_verify}}; |
| } |
| |
| base::Optional<ParseResult> MakeStructField( |
| ParseResultIterator* child_results) { |
| auto const_qualified = child_results->NextAs<bool>(); |
| auto name = child_results->NextAs<Identifier*>(); |
| auto type = child_results->NextAs<TypeExpression*>(); |
| return ParseResult{StructFieldExpression{{name, type}, const_qualified}}; |
| } |
| |
| base::Optional<ParseResult> ExtractAssignmentOperator( |
| ParseResultIterator* child_results) { |
| auto op = child_results->NextAs<Identifier*>(); |
| base::Optional<std::string> result = |
| std::string(op->value.begin(), op->value.end() - 1); |
| return ParseResult(std::move(result)); |
| } |
| |
| struct TorqueGrammar : Grammar { |
| static bool MatchWhitespace(InputPosition* pos) { |
| while (true) { |
| if (MatchChar(std::isspace, pos)) continue; |
| if (MatchString("//", pos)) { |
| while (MatchChar([](char c) { return c != '\n'; }, pos)) { |
| } |
| continue; |
| } |
| return true; |
| } |
| } |
| |
| static bool MatchIdentifier(InputPosition* pos) { |
| InputPosition current = *pos; |
| MatchString("_", ¤t); |
| if (!MatchChar(std::isalpha, ¤t)) return false; |
| while (MatchChar(std::isalnum, ¤t) || MatchString("_", ¤t)) { |
| } |
| *pos = current; |
| return true; |
| } |
| |
| static bool MatchAnnotation(InputPosition* pos) { |
| InputPosition current = *pos; |
| if (!MatchString("@", ¤t)) return false; |
| if (!MatchIdentifier(¤t)) return false; |
| *pos = current; |
| return true; |
| } |
| |
| static bool MatchIntrinsicName(InputPosition* pos) { |
| InputPosition current = *pos; |
| if (!MatchString("%", ¤t)) return false; |
| if (!MatchIdentifier(¤t)) return false; |
| *pos = current; |
| return true; |
| } |
| |
| static bool MatchStringLiteral(InputPosition* pos) { |
| InputPosition current = *pos; |
| if (MatchString("\"", ¤t)) { |
| while ( |
| (MatchString("\\", ¤t) && MatchAnyChar(¤t)) || |
| MatchChar([](char c) { return c != '"' && c != '\n'; }, ¤t)) { |
| } |
| if (MatchString("\"", ¤t)) { |
| *pos = current; |
| return true; |
| } |
| } |
| current = *pos; |
| if (MatchString("'", ¤t)) { |
| while ( |
| (MatchString("\\", ¤t) && MatchAnyChar(¤t)) || |
| MatchChar([](char c) { return c != '\'' && c != '\n'; }, ¤t)) { |
| } |
| if (MatchString("'", ¤t)) { |
| *pos = current; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| static bool MatchHexLiteral(InputPosition* pos) { |
| InputPosition current = *pos; |
| MatchString("-", ¤t); |
| if (MatchString("0x", ¤t) && MatchChar(std::isxdigit, ¤t)) { |
| while (MatchChar(std::isxdigit, ¤t)) { |
| } |
| *pos = current; |
| return true; |
| } |
| return false; |
| } |
| |
| static bool MatchDecimalLiteral(InputPosition* pos) { |
| InputPosition current = *pos; |
| bool found_digit = false; |
| MatchString("-", ¤t); |
| while (MatchChar(std::isdigit, ¤t)) found_digit = true; |
| MatchString(".", ¤t); |
| while (MatchChar(std::isdigit, ¤t)) found_digit = true; |
| if (!found_digit) return false; |
| *pos = current; |
| if ((MatchString("e", ¤t) || MatchString("E", ¤t)) && |
| (MatchString("+", ¤t) || MatchString("-", ¤t) || true) && |
| MatchChar(std::isdigit, ¤t)) { |
| while (MatchChar(std::isdigit, ¤t)) { |
| } |
| *pos = current; |
| return true; |
| } |
| return true; |
| } |
| |
| TorqueGrammar() : Grammar(&file) { SetWhitespace(MatchWhitespace); } |
| |
| // Result: std::string |
| Symbol identifier = {Rule({Pattern(MatchIdentifier)}, YieldMatchedInput), |
| Rule({Token("runtime")}, YieldMatchedInput)}; |
| |
| // Result: Identifier* |
| Symbol name = {Rule({&identifier}, MakeIdentifier)}; |
| |
| // Result: Identifier* |
| Symbol annotation = { |
| Rule({Pattern(MatchAnnotation)}, MakeIdentifierFromMatchedInput)}; |
| |
| // Result: std::vector<Identifier*> |
| Symbol* annotations = List<Identifier*>(&annotation); |
| |
| // Result: std::string |
| Symbol intrinsicName = { |
| Rule({Pattern(MatchIntrinsicName)}, YieldMatchedInput)}; |
| |
| // Result: std::string |
| Symbol stringLiteral = { |
| Rule({Pattern(MatchStringLiteral)}, YieldMatchedInput)}; |
| |
| // Result: std::string |
| Symbol externalString = {Rule({&stringLiteral}, StringLiteralUnquoteAction)}; |
| |
| // Result: std::string |
| Symbol decimalLiteral = { |
| Rule({Pattern(MatchDecimalLiteral)}, YieldMatchedInput), |
| Rule({Pattern(MatchHexLiteral)}, YieldMatchedInput)}; |
| |
| // Result: TypeList |
| Symbol* typeList = List<TypeExpression*>(&type, Token(",")); |
| |
| // Result: TypeExpression* |
| Symbol simpleType = { |
| Rule({Token("("), &type, Token(")")}), |
| Rule({List<std::string>(Sequence({&identifier, Token("::")})), |
| CheckIf(Token("constexpr")), &identifier, |
| TryOrDefault<std::vector<TypeExpression*>>( |
| &genericSpecializationTypeList)}, |
| MakeBasicTypeExpression), |
| Rule({Token("builtin"), Token("("), typeList, Token(")"), Token("=>"), |
| &simpleType}, |
| MakeFunctionTypeExpression), |
| Rule({Token("&"), &simpleType}, MakeReferenceTypeExpression)}; |
| |
| // Result: TypeExpression* |
| Symbol type = {Rule({&simpleType}), Rule({&type, Token("|"), &simpleType}, |
| MakeUnionTypeExpression)}; |
| |
| // Result: GenericParameters |
| Symbol genericParameters = { |
| Rule({Token("<"), |
| List<Identifier*>(Sequence({&name, Token(":"), Token("type")}), |
| Token(",")), |
| Token(">")})}; |
| |
| // Result: TypeList |
| Symbol genericSpecializationTypeList = { |
| Rule({Token("<"), typeList, Token(">")})}; |
| |
| // Result: base::Optional<TypeList> |
| Symbol* optionalGenericParameters = Optional<TypeList>(&genericParameters); |
| |
| Symbol implicitParameterList{ |
| Rule({Token("("), OneOf({"implicit", "js-implicit"}), |
| List<NameAndTypeExpression>(&nameAndType, Token(",")), Token(")")}, |
| MakeImplicitParameterList)}; |
| |
| Symbol* optionalImplicitParameterList{ |
| Optional<ImplicitParameters>(&implicitParameterList)}; |
| |
| // Result: ParameterList |
| Symbol typeListMaybeVarArgs = { |
| Rule({optionalImplicitParameterList, Token("("), |
| List<TypeExpression*>(Sequence({&type, Token(",")})), Token("..."), |
| Token(")")}, |
| MakeParameterList<true, false>), |
| Rule({optionalImplicitParameterList, Token("("), typeList, Token(")")}, |
| MakeParameterList<false, false>)}; |
| |
| // Result: LabelAndTypes |
| Symbol labelParameter = {Rule( |
| {&name, |
| TryOrDefault<TypeList>(Sequence({Token("("), typeList, Token(")")}))}, |
| MakeLabelAndTypes)}; |
| |
| // Result: TypeExpression* |
| Symbol optionalReturnType = {Rule({Token(":"), &type}), |
| Rule({}, MakeVoidType)}; |
| |
| // Result: LabelAndTypesVector |
| Symbol* optionalLabelList{TryOrDefault<LabelAndTypesVector>( |
| Sequence({Token("labels"), |
| NonemptyList<LabelAndTypes>(&labelParameter, Token(","))}))}; |
| |
| // Result: std::vector<Statement*> |
| Symbol* optionalOtherwise{TryOrDefault<std::vector<Statement*>>( |
| Sequence({Token("otherwise"), |
| NonemptyList<Statement*>(&atomarStatement, Token(","))}))}; |
| |
| // Result: NameAndTypeExpression |
| Symbol nameAndType = {Rule({&name, Token(":"), &type}, MakeNameAndType)}; |
| |
| Symbol* optionalArraySpecifier = |
| Optional<std::string>(Sequence({Token("["), &identifier, Token("]")})); |
| |
| // Result: ConditionalAnnotation |
| Symbol conditionalAnnotation = { |
| Rule({OneOf({"@if", "@ifnot"}), Token("("), &identifier, Token(")")}, |
| MakeConditionalAnnotation)}; |
| |
| Symbol classField = { |
| Rule({Optional<ConditionalAnnotation>(&conditionalAnnotation), |
| annotations, CheckIf(Token("weak")), CheckIf(Token("const")), &name, |
| optionalArraySpecifier, Token(":"), &type, Token(";")}, |
| MakeClassField)}; |
| |
| Symbol structField = { |
| Rule({CheckIf(Token("const")), &name, Token(":"), &type, Token(";")}, |
| MakeStructField)}; |
| |
| // Result: ParameterList |
| Symbol parameterListNoVararg = { |
| Rule({optionalImplicitParameterList, Token("("), |
| List<NameAndTypeExpression>(&nameAndType, Token(",")), Token(")")}, |
| MakeParameterList<false, true>)}; |
| |
| // Result: ParameterList |
| Symbol parameterListAllowVararg = { |
| Rule({¶meterListNoVararg}), |
| Rule({optionalImplicitParameterList, Token("("), |
| List<NameAndTypeExpression>(Sequence({&nameAndType, Token(",")})), |
| Token("..."), &identifier, Token(")")}, |
| MakeParameterList<true, true>)}; |
| |
| // Result: Identifier* |
| Symbol* OneOf(const std::vector<std::string>& alternatives) { |
| Symbol* result = NewSymbol(); |
| for (const std::string& s : alternatives) { |
| result->AddRule(Rule({Token(s)}, MakeIdentifierFromMatchedInput)); |
| } |
| return result; |
| } |
| |
| // Result: Expression* |
| Symbol* BinaryOperator(Symbol* nextLevel, Symbol* op) { |
| Symbol* result = NewSymbol(); |
| *result = {Rule({nextLevel}), |
| Rule({result, op, nextLevel}, MakeBinaryOperator)}; |
| return result; |
| } |
| |
| // Result: Expression* |
| Symbol* expression = &assignmentExpression; |
| |
| // Result: IncrementDecrementOperator |
| Symbol incrementDecrementOperator = { |
| Rule({Token("++")}, |
| YieldIntegralConstant<IncrementDecrementOperator, |
| IncrementDecrementOperator::kIncrement>), |
| Rule({Token("--")}, |
| YieldIntegralConstant<IncrementDecrementOperator, |
| IncrementDecrementOperator::kDecrement>)}; |
| |
| // Result: Expression* |
| Symbol identifierExpression = { |
| Rule({List<std::string>(Sequence({&identifier, Token("::")})), &name, |
| TryOrDefault<TypeList>(&genericSpecializationTypeList)}, |
| MakeIdentifierExpression), |
| }; |
| |
| // Result: std::vector<Expression*> |
| Symbol argumentList = {Rule( |
| {Token("("), List<Expression*>(expression, Token(",")), Token(")")})}; |
| |
| // Result: Expression* |
| Symbol callExpression = {Rule( |
| {&identifierExpression, &argumentList, optionalOtherwise}, MakeCall)}; |
| |
| // Result: Expression* |
| Symbol callMethodExpression = { |
| Rule({&primaryExpression, Token("."), &identifier, &argumentList, |
| optionalOtherwise}, |
| MakeMethodCall)}; |
| |
| // Result: NameAndExpression |
| Symbol namedExpression = { |
| Rule({&name, Token(":"), expression}, MakeNameAndExpression), |
| Rule({expression}, MakeNameAndExpressionFromExpression)}; |
| |
| // Result: std::vector<NameAndExpression> |
| Symbol initializerList = { |
| Rule({Token("{"), List<NameAndExpression>(&namedExpression, Token(",")), |
| Token("}")})}; |
| |
| // Result: Expression* |
| Symbol intrinsicCallExpression = {Rule( |
| {&intrinsicName, TryOrDefault<TypeList>(&genericSpecializationTypeList), |
| &argumentList}, |
| MakeIntrinsicCallExpression)}; |
| |
| // Result: Expression* |
| Symbol primaryExpression = { |
| Rule({&callExpression}), |
| Rule({&callMethodExpression}), |
| Rule({&intrinsicCallExpression}), |
| Rule({&identifierExpression}), |
| Rule({&primaryExpression, Token("."), &name}, MakeFieldAccessExpression), |
| Rule({&primaryExpression, Token("["), expression, Token("]")}, |
| MakeElementAccessExpression), |
| Rule({&decimalLiteral}, MakeNumberLiteralExpression), |
| Rule({&stringLiteral}, MakeStringLiteralExpression), |
| Rule({&simpleType, &initializerList}, MakeStructExpression), |
| Rule({Token("new"), &simpleType, &initializerList}, MakeNewExpression), |
| Rule({Token("("), expression, Token(")")})}; |
| |
| // Result: Expression* |
| Symbol unaryExpression = { |
| Rule({&primaryExpression}), |
| Rule({OneOf({"+", "-", "!", "~", "&"}), &unaryExpression}, |
| MakeUnaryOperator), |
| Rule({Token("*"), &unaryExpression}, MakeDereferenceExpression), |
| Rule({Token("..."), &unaryExpression}, MakeSpreadExpression), |
| Rule({&incrementDecrementOperator, &unaryExpression}, |
| MakeIncrementDecrementExpressionPrefix), |
| Rule({&unaryExpression, &incrementDecrementOperator}, |
| MakeIncrementDecrementExpressionPostfix)}; |
| |
| // Result: Expression* |
| Symbol* multiplicativeExpression = |
| BinaryOperator(&unaryExpression, OneOf({"*", "/", "%"})); |
| |
| // Result: Expression* |
| Symbol* additiveExpression = |
| BinaryOperator(multiplicativeExpression, OneOf({"+", "-"})); |
| |
| // Result: Identifier* |
| Symbol shiftOperator = { |
| Rule({Token("<<")}, MakeIdentifierFromMatchedInput), |
| Rule({Token(">"), Token(">")}, MakeRightShiftIdentifier), |
| Rule({Token(">"), Token(">"), Token(">")}, MakeRightShiftIdentifier)}; |
| |
| // Result: Expression* |
| Symbol* shiftExpression = BinaryOperator(additiveExpression, &shiftOperator); |
| |
| // Do not allow expressions like a < b > c because this is never |
| // useful and ambiguous with template parameters. |
| // Result: Expression* |
| Symbol relationalExpression = { |
| Rule({shiftExpression}), |
| Rule({shiftExpression, OneOf({"<", ">", "<=", ">="}), shiftExpression}, |
| MakeBinaryOperator)}; |
| |
| // Result: Expression* |
| Symbol* equalityExpression = |
| BinaryOperator(&relationalExpression, OneOf({"==", "!="})); |
| |
| // Result: Expression* |
| Symbol* bitwiseExpression = |
| BinaryOperator(equalityExpression, OneOf({"&", "|"})); |
| |
| // Result: Expression* |
| Symbol logicalAndExpression = { |
| Rule({bitwiseExpression}), |
| Rule({&logicalAndExpression, Token("&&"), bitwiseExpression}, |
| MakeLogicalAndExpression)}; |
| |
| // Result: Expression* |
| Symbol logicalOrExpression = { |
| Rule({&logicalAndExpression}), |
| Rule({&logicalOrExpression, Token("||"), &logicalAndExpression}, |
| MakeLogicalOrExpression)}; |
| |
| // Result: Expression* |
| Symbol conditionalExpression = { |
| Rule({&logicalOrExpression}), |
| Rule({&logicalOrExpression, Token("?"), expression, Token(":"), |
| &conditionalExpression}, |
| MakeConditionalExpression)}; |
| |
| // Result: base::Optional<std::string> |
| Symbol assignmentOperator = { |
| Rule({Token("=")}, YieldDefaultValue<base::Optional<std::string>>), |
| Rule({OneOf({"*=", "/=", "%=", "+=", "-=", "<<=", ">>=", ">>>=", "&=", |
| "^=", "|="})}, |
| ExtractAssignmentOperator)}; |
| |
| // Result: Expression* |
| Symbol assignmentExpression = { |
| Rule({&conditionalExpression}), |
| Rule({&conditionalExpression, &assignmentOperator, &assignmentExpression}, |
| MakeAssignmentExpression)}; |
| |
| // Result: Statement* |
| Symbol block = {Rule({CheckIf(Token("deferred")), Token("{"), |
| List<Statement*>(&statement), Token("}")}, |
| MakeBlockStatement)}; |
| |
| // Result: LabelBlock* |
| Symbol labelBlock = { |
| Rule({Token("label"), &name, |
| TryOrDefault<ParameterList>(¶meterListNoVararg), &block}, |
| MakeLabelBlock)}; |
| |
| Symbol catchBlock = { |
| Rule({Token("catch"), Token("("), &identifier, Token(")"), &block}, |
| MakeCatchBlock)}; |
| |
| // Result: ExpressionWithSource |
| Symbol expressionWithSource = {Rule({expression}, MakeExpressionWithSource)}; |
| |
| Symbol* optionalTypeSpecifier = |
| Optional<TypeExpression*>(Sequence({Token(":"), &type})); |
| |
| // Result: Statement* |
| Symbol varDeclaration = { |
| Rule({OneOf({"let", "const"}), &name, optionalTypeSpecifier}, |
| MakeVarDeclarationStatement)}; |
| |
| // Result: Statement* |
| Symbol varDeclarationWithInitialization = { |
| Rule({OneOf({"let", "const"}), &name, optionalTypeSpecifier, Token("="), |
| expression}, |
| MakeVarDeclarationStatement)}; |
| |
| // Result: Statement* |
| Symbol atomarStatement = { |
| Rule({expression}, MakeExpressionStatement), |
| Rule({Token("return"), Optional<Expression*>(expression)}, |
| MakeReturnStatement), |
| Rule({Token("tail"), &callExpression}, MakeTailCallStatement), |
| Rule({Token("break")}, MakeBreakStatement), |
| Rule({Token("continue")}, MakeContinueStatement), |
| Rule({Token("goto"), &name, |
| TryOrDefault<std::vector<Expression*>>(&argumentList)}, |
| MakeGotoStatement), |
| Rule({OneOf({"debug", "unreachable"})}, MakeDebugStatement)}; |
| |
| // Result: Statement* |
| Symbol statement = { |
| Rule({&block}), |
| Rule({&atomarStatement, Token(";")}), |
| Rule({&varDeclaration, Token(";")}), |
| Rule({&varDeclarationWithInitialization, Token(";")}), |
| Rule({Token("if"), CheckIf(Token("constexpr")), Token("("), expression, |
| Token(")"), &statement, |
| Optional<Statement*>(Sequence({Token("else"), &statement}))}, |
| MakeIfStatement), |
| Rule( |
| { |
| Token("typeswitch"), Token("("), expression, Token(")"), |
| Token("{"), NonemptyList<TypeswitchCase>(&typeswitchCase), |
| Token("}"), |
| }, |
| MakeTypeswitchStatement), |
| Rule({Token("try"), &block, List<LabelBlock*>(&labelBlock), |
| Optional<LabelBlock*>(&catchBlock)}, |
| MakeTryLabelExpression), |
| Rule({OneOf({"assert", "check"}), Token("("), &expressionWithSource, |
| Token(")"), Token(";")}, |
| MakeAssertStatement), |
| Rule({Token("while"), Token("("), expression, Token(")"), &statement}, |
| MakeWhileStatement), |
| Rule({Token("for"), Token("("), |
| Optional<Statement*>(&varDeclarationWithInitialization), Token(";"), |
| Optional<Expression*>(expression), Token(";"), |
| Optional<Expression*>(expression), Token(")"), &statement}, |
| MakeForLoopStatement)}; |
| |
| // Result: TypeswitchCase |
| Symbol typeswitchCase = { |
| Rule({Token("case"), Token("("), |
| Optional<std::string>(Sequence({&identifier, Token(":")})), &type, |
| Token(")"), Token(":"), &block}, |
| MakeTypeswitchCase)}; |
| |
| // Result: base::Optional<Statement*> |
| Symbol optionalBody = { |
| Rule({&block}, CastParseResult<Statement*, base::Optional<Statement*>>), |
| Rule({Token(";")}, YieldDefaultValue<base::Optional<Statement*>>)}; |
| |
| // Result: Declaration* |
| Symbol method = {Rule( |
| {CheckIf(Token("transitioning")), |
| Optional<std::string>(Sequence({Token("operator"), &externalString})), |
| &identifier, ¶meterListNoVararg, &optionalReturnType, |
| optionalLabelList, &block}, |
| MakeMethodDeclaration)}; |
| |
| // Result: std::vector<Declaration*> |
| Symbol declaration = { |
| Rule({Token("const"), &name, Token(":"), &type, Token("="), expression, |
| Token(";")}, |
| AsSingletonVector<Declaration*, MakeConstDeclaration>()), |
| Rule({Token("const"), &name, Token(":"), &type, Token("generates"), |
| &externalString, Token(";")}, |
| AsSingletonVector<Declaration*, MakeExternConstDeclaration>()), |
| Rule({annotations, CheckIf(Token("extern")), CheckIf(Token("transient")), |
| Token("class"), &name, |
| Optional<TypeExpression*>(Sequence({Token("extends"), &type})), |
| Optional<std::string>( |
| Sequence({Token("generates"), &externalString})), |
| Token("{"), List<Declaration*>(&method), |
| List<ClassFieldExpression>(&classField), Token("}")}, |
| AsSingletonVector<Declaration*, MakeClassDeclaration>()), |
| Rule({Token("struct"), &name, |
| TryOrDefault<GenericParameters>(&genericParameters), Token("{"), |
| List<Declaration*>(&method), |
| List<StructFieldExpression>(&structField), Token("}")}, |
| AsSingletonVector<Declaration*, MakeStructDeclaration>()), |
| Rule({CheckIf(Token("transient")), Token("type"), &name, |
| Optional<Identifier*>(Sequence({Token("extends"), &name})), |
| Optional<std::string>( |
| Sequence({Token("generates"), &externalString})), |
| Optional<std::string>( |
| Sequence({Token("constexpr"), &externalString})), |
| Token(";")}, |
| MakeAbstractTypeDeclaration), |
| Rule({Token("type"), &name, Token("="), &type, Token(";")}, |
| AsSingletonVector<Declaration*, MakeTypeAliasDeclaration>()), |
| Rule({Token("intrinsic"), &intrinsicName, |
| TryOrDefault<GenericParameters>(&genericParameters), |
| ¶meterListNoVararg, &optionalReturnType, &optionalBody}, |
| AsSingletonVector<Declaration*, MakeIntrinsicDeclaration>()), |
| Rule({Token("extern"), CheckIf(Token("transitioning")), |
| Optional<std::string>( |
| Sequence({Token("operator"), &externalString})), |
| Token("macro"), |
| Optional<std::string>(Sequence({&identifier, Token("::")})), |
| &identifier, TryOrDefault<GenericParameters>(&genericParameters), |
| &typeListMaybeVarArgs, &optionalReturnType, optionalLabelList, |
| Token(";")}, |
| AsSingletonVector<Declaration*, MakeExternalMacro>()), |
| Rule({Token("extern"), CheckIf(Token("transitioning")), |
| CheckIf(Token("javascript")), Token("builtin"), &identifier, |
| TryOrDefault<GenericParameters>(&genericParameters), |
| &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, |
| AsSingletonVector<Declaration*, MakeExternalBuiltin>()), |
| Rule( |
| {Token("extern"), CheckIf(Token("transitioning")), Token("runtime"), |
| &identifier, &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, |
| AsSingletonVector<Declaration*, MakeExternalRuntime>()), |
| Rule({CheckIf(Token("@export")), CheckIf(Token("transitioning")), |
| Optional<std::string>( |
| Sequence({Token("operator"), &externalString})), |
| Token("macro"), &identifier, |
| TryOrDefault<GenericParameters>(&genericParameters), |
| ¶meterListNoVararg, &optionalReturnType, optionalLabelList, |
| &optionalBody}, |
| AsSingletonVector<Declaration*, MakeTorqueMacroDeclaration>()), |
| Rule({CheckIf(Token("transitioning")), CheckIf(Token("javascript")), |
| Token("builtin"), &identifier, |
| TryOrDefault<GenericParameters>(&genericParameters), |
| ¶meterListAllowVararg, &optionalReturnType, &optionalBody}, |
| AsSingletonVector<Declaration*, MakeTorqueBuiltinDeclaration>()), |
| Rule({&name, &genericSpecializationTypeList, ¶meterListAllowVararg, |
| &optionalReturnType, optionalLabelList, &block}, |
| AsSingletonVector<Declaration*, MakeSpecializationDeclaration>()), |
| Rule({Token("#include"), &externalString}, |
| AsSingletonVector<Declaration*, MakeCppIncludeDeclaration>())}; |
| |
| // Result: std::vector<Declaration*> |
| Symbol declarationList = { |
| Rule({List<std::vector<Declaration*>>(&declaration)}, ConcatList)}; |
| |
| // Result: std::vector<Declaration*> |
| Symbol namespaceDeclaration = { |
| Rule({Token("namespace"), &identifier, Token("{"), &declarationList, |
| Token("}")}, |
| AsSingletonVector<Declaration*, MakeNamespaceDeclaration>())}; |
| |
| Symbol file = {Rule({&file, Token("import"), &externalString}, |
| ProcessTorqueImportDeclaration), |
| Rule({&file, &namespaceDeclaration}, AddGlobalDeclarations), |
| Rule({&file, &declaration}, AddGlobalDeclarations), Rule({})}; |
| }; |
| |
| } // namespace |
| |
| void ParseTorque(const std::string& input) { |
| BuildFlags::Scope build_flags_scope; |
| TorqueGrammar().Parse(input); |
| } |
| |
| } // namespace torque |
| } // namespace internal |
| } // namespace v8 |