| // 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 <cctype> | |
| #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<std::string>; | |
| struct ExpressionWithSource { | |
| Expression* expression; | |
| std::string source; | |
| }; | |
| struct TypeswitchCase { | |
| SourcePosition pos; | |
| base::Optional<std::string> name; | |
| TypeExpression* type; | |
| Statement* block; | |
| }; | |
| enum class ParseResultHolderBase::TypeId { | |
| kStdString, | |
| kBool, | |
| kStdVectorOfString, | |
| kExpressionPtr, | |
| kLocationExpressionPtr, | |
| kStatementPtr, | |
| kDeclarationPtr, | |
| kTypeExpressionPtr, | |
| kLabelBlockPtr, | |
| kNameAndTypeExpression, | |
| kStdVectorOfNameAndTypeExpression, | |
| kIncrementDecrementOperator, | |
| kOptionalStdString, | |
| kStdVectorOfStatementPtr, | |
| kStdVectorOfDeclarationPtr, | |
| kStdVectorOfExpressionPtr, | |
| kExpressionWithSource, | |
| kParameterList, | |
| kRangeExpression, | |
| kOptionalRangeExpression, | |
| kTypeList, | |
| kOptionalTypeList, | |
| kLabelAndTypes, | |
| kStdVectorOfLabelAndTypes, | |
| kStdVectorOfLabelBlockPtr, | |
| kOptionalStatementPtr, | |
| kOptionalExpressionPtr, | |
| kTypeswitchCase, | |
| kStdVectorOfTypeswitchCase | |
| }; | |
| 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<LabelBlock*>::id = | |
| ParseResultTypeId::kLabelBlockPtr; | |
| template <> | |
| V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Expression*>::id = | |
| ParseResultTypeId::kExpressionPtr; | |
| template <> | |
| V8_EXPORT_PRIVATE const ParseResultTypeId | |
| ParseResultHolder<LocationExpression*>::id = | |
| ParseResultTypeId::kLocationExpressionPtr; | |
| 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<std::vector<NameAndTypeExpression>>::id = | |
| ParseResultTypeId::kStdVectorOfNameAndTypeExpression; | |
| 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<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<RangeExpression>::id = | |
| ParseResultTypeId::kRangeExpression; | |
| template <> | |
| V8_EXPORT_PRIVATE const ParseResultTypeId | |
| ParseResultHolder<base::Optional<RangeExpression>>::id = | |
| ParseResultTypeId::kOptionalRangeExpression; | |
| 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; | |
| namespace { | |
| base::Optional<ParseResult> AddGlobalDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto declaration = child_results->NextAs<Declaration*>(); | |
| CurrentAst::Get().declarations().push_back(declaration); | |
| return base::nullopt; | |
| } | |
| template <class T, class... Args> | |
| T* MakeNode(Args... args) { | |
| return CurrentAst::Get().AddNode(std::unique_ptr<T>( | |
| new T(CurrentSourcePosition::Get(), std::move(args)...))); | |
| } | |
| base::Optional<ParseResult> MakeCall(ParseResultIterator* child_results) { | |
| auto callee = child_results->NextAs<std::string>(); | |
| auto generic_args = child_results->NextAs<TypeList>(); | |
| auto args = child_results->NextAs<std::vector<Expression*>>(); | |
| auto labels = child_results->NextAs<std::vector<std::string>>(); | |
| Expression* result = | |
| MakeNode<CallExpression>(callee, false, generic_args, args, labels); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeBinaryOperator( | |
| ParseResultIterator* child_results) { | |
| auto left = child_results->NextAs<Expression*>(); | |
| auto op = child_results->NextAs<std::string>(); | |
| auto right = child_results->NextAs<Expression*>(); | |
| Expression* result = MakeNode<CallExpression>( | |
| op, true, TypeList{}, std::vector<Expression*>{left, right}, | |
| std::vector<std::string>{}); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeUnaryOperator( | |
| ParseResultIterator* child_results) { | |
| auto op = child_results->NextAs<std::string>(); | |
| auto e = child_results->NextAs<Expression*>(); | |
| Expression* result = MakeNode<CallExpression>(op, true, TypeList{}, | |
| std::vector<Expression*>{e}, | |
| std::vector<std::string>{}); | |
| return ParseResult{result}; | |
| } | |
| template <bool has_varargs> | |
| base::Optional<ParseResult> MakeParameterListFromTypes( | |
| ParseResultIterator* child_results) { | |
| auto types = child_results->NextAs<TypeList>(); | |
| ParameterList result; | |
| result.types = std::move(types); | |
| result.has_varargs = has_varargs; | |
| return ParseResult{std::move(result)}; | |
| } | |
| template <bool has_varargs> | |
| base::Optional<ParseResult> MakeParameterListFromNameAndTypeList( | |
| ParseResultIterator* child_results) { | |
| auto params = child_results->NextAs<std::vector<NameAndTypeExpression>>(); | |
| std::string arguments_variable = ""; | |
| if (child_results->HasNext()) { | |
| arguments_variable = child_results->NextAs<std::string>(); | |
| } | |
| ParameterList result; | |
| for (NameAndTypeExpression& pair : params) { | |
| result.names.push_back(std::move(pair.name)); | |
| result.types.push_back(pair.type); | |
| } | |
| result.has_varargs = has_varargs; | |
| result.arguments_variable = arguments_variable; | |
| return ParseResult{std::move(result)}; | |
| } | |
| base::Optional<ParseResult> MakeAssertStatement( | |
| ParseResultIterator* child_results) { | |
| auto kind = child_results->NextAs<std::string>(); | |
| 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<std::string>(); | |
| 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>(false, "void"); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeExternalMacro( | |
| ParseResultIterator* child_results) { | |
| auto operator_name = child_results->NextAs<base::Optional<std::string>>(); | |
| auto name = child_results->NextAs<std::string>(); | |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); | |
| auto args = child_results->NextAs<ParameterList>(); | |
| auto return_type = child_results->NextAs<TypeExpression*>(); | |
| auto labels = child_results->NextAs<LabelAndTypesVector>(); | |
| MacroDeclaration* macro = MakeNode<ExternalMacroDeclaration>( | |
| name, operator_name, args, return_type, labels); | |
| Declaration* result; | |
| if (generic_parameters.empty()) { | |
| result = MakeNode<StandardDeclaration>(macro, nullptr); | |
| } else { | |
| result = MakeNode<GenericDeclaration>(macro, generic_parameters); | |
| } | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeTorqueMacroDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto operator_name = child_results->NextAs<base::Optional<std::string>>(); | |
| auto name = child_results->NextAs<std::string>(); | |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); | |
| 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>( | |
| name, operator_name, args, return_type, labels); | |
| Declaration* result; | |
| if (generic_parameters.empty()) { | |
| if (!body) ReportError("A non-generic declaration needs a body."); | |
| result = MakeNode<StandardDeclaration>(macro, *body); | |
| } else { | |
| result = MakeNode<GenericDeclaration>(macro, generic_parameters, body); | |
| } | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeTorqueBuiltinDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto javascript_linkage = child_results->NextAs<bool>(); | |
| auto name = child_results->NextAs<std::string>(); | |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); | |
| 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>( | |
| 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<std::string>(); | |
| auto type = child_results->NextAs<TypeExpression*>(); | |
| auto expression = child_results->NextAs<Expression*>(); | |
| Declaration* result = | |
| MakeNode<ConstDeclaration>(std::move(name), type, expression); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeExternConstDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto type = child_results->NextAs<TypeExpression*>(); | |
| auto literal = child_results->NextAs<std::string>(); | |
| Declaration* result = MakeNode<ExternConstDeclaration>(std::move(name), type, | |
| std::move(literal)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeTypeAliasDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto type = child_results->NextAs<TypeExpression*>(); | |
| Declaration* result = MakeNode<TypeAliasDeclaration>(std::move(name), type); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeTypeDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto extends = child_results->NextAs<base::Optional<std::string>>(); | |
| auto generates = child_results->NextAs<base::Optional<std::string>>(); | |
| auto constexpr_generates = | |
| child_results->NextAs<base::Optional<std::string>>(); | |
| Declaration* result = MakeNode<TypeDeclaration>( | |
| std::move(name), std::move(extends), std::move(generates), | |
| std::move(constexpr_generates)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeExplicitModuleDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto declarations = child_results->NextAs<std::vector<Declaration*>>(); | |
| Declaration* result = MakeNode<ExplicitModuleDeclaration>( | |
| std::move(name), std::move(declarations)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeSpecializationDeclaration( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| 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*>(); | |
| 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<std::string>(); | |
| auto fields = child_results->NextAs<std::vector<NameAndTypeExpression>>(); | |
| Declaration* result = | |
| MakeNode<StructDeclaration>(std::move(name), std::move(fields)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeExternalBuiltin( | |
| ParseResultIterator* child_results) { | |
| auto js_linkage = child_results->NextAs<bool>(); | |
| auto name = child_results->NextAs<std::string>(); | |
| auto generic_parameters = child_results->NextAs<GenericParameters>(); | |
| auto args = child_results->NextAs<ParameterList>(); | |
| auto return_type = child_results->NextAs<TypeExpression*>(); | |
| BuiltinDeclaration* builtin = | |
| MakeNode<ExternalBuiltinDeclaration>(js_linkage, name, args, return_type); | |
| Declaration* result; | |
| if (generic_parameters.empty()) { | |
| result = MakeNode<StandardDeclaration>(builtin, nullptr); | |
| } else { | |
| result = MakeNode<GenericDeclaration>(builtin, generic_parameters); | |
| } | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeExternalRuntime( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto args = child_results->NextAs<ParameterList>(); | |
| auto return_type = child_results->NextAs<TypeExpression*>(); | |
| ExternalRuntimeDeclaration* runtime = | |
| MakeNode<ExternalRuntimeDeclaration>(name, args, return_type); | |
| Declaration* result = MakeNode<StandardDeclaration>(runtime, nullptr); | |
| 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 is_constexpr = child_results->NextAs<bool>(); | |
| auto name = child_results->NextAs<std::string>(); | |
| TypeExpression* result = | |
| MakeNode<BasicTypeExpression>(is_constexpr, std::move(name)); | |
| 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> 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"); | |
| } | |
| 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, "_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>("_value"); | |
| if (i >= 1) { | |
| value = | |
| MakeNode<AssumeTypeImpossibleExpression>(accumulated_types, value); | |
| } | |
| BlockStatement* case_block; | |
| if (i < cases.size() - 1) { | |
| value = MakeNode<CallExpression>( | |
| "cast", false, std::vector<TypeExpression*>{cases[i].type}, | |
| std::vector<Expression*>{value}, | |
| std::vector<std::string>{"_NextCase"}); | |
| 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, 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<TryLabelStatement>( | |
| case_block, std::vector<LabelBlock*>{MakeNode<LabelBlock>( | |
| "_NextCase", 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); | |
| 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<std::string>(); | |
| bool const_qualified = kind == "const"; | |
| if (!const_qualified) DCHECK_EQ("let", kind); | |
| auto name = child_results->NextAs<std::string>(); | |
| auto type = child_results->NextAs<TypeExpression*>(); | |
| base::Optional<Expression*> initializer; | |
| if (child_results->HasNext()) | |
| initializer = child_results->NextAs<Expression*>(); | |
| Statement* result = MakeNode<VarDeclarationStatement>( | |
| const_qualified, std::move(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<std::string>(); | |
| auto arguments = child_results->NextAs<std::vector<Expression*>>(); | |
| Statement* result = | |
| MakeNode<GotoStatement>(std::move(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*>>(); | |
| Statement* result = MakeNode<BlockStatement>(deferred, std::move(statements)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeTryLabelStatement( | |
| ParseResultIterator* child_results) { | |
| auto try_block = child_results->NextAs<Statement*>(); | |
| auto label_blocks = child_results->NextAs<std::vector<LabelBlock*>>(); | |
| Statement* result = | |
| MakeNode<TryLabelStatement>(try_block, std::move(label_blocks)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeForOfLoopStatement( | |
| ParseResultIterator* child_results) { | |
| auto var_decl = child_results->NextAs<Statement*>(); | |
| auto iterable = child_results->NextAs<Expression*>(); | |
| auto range = child_results->NextAs<base::Optional<RangeExpression>>(); | |
| auto body = child_results->NextAs<Statement*>(); | |
| Statement* result = | |
| MakeNode<ForOfLoopStatement>(var_decl, iterable, range, body); | |
| 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*>>(); | |
| auto body = child_results->NextAs<Statement*>(); | |
| Statement* result = MakeNode<ForLoopStatement>(var_decl, test, action, body); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeLabelBlock(ParseResultIterator* child_results) { | |
| auto label = child_results->NextAs<std::string>(); | |
| auto parameters = child_results->NextAs<ParameterList>(); | |
| auto body = child_results->NextAs<Statement*>(); | |
| LabelBlock* result = | |
| MakeNode<LabelBlock>(std::move(label), std::move(parameters), body); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeRangeExpression( | |
| ParseResultIterator* child_results) { | |
| auto begin = child_results->NextAs<base::Optional<Expression*>>(); | |
| auto end = child_results->NextAs<base::Optional<Expression*>>(); | |
| RangeExpression result = {begin, end}; | |
| 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> MakeIdentifierExpression( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto generic_arguments = | |
| child_results->NextAs<std::vector<TypeExpression*>>(); | |
| LocationExpression* result = MakeNode<IdentifierExpression>( | |
| std::move(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<std::string>(); | |
| LocationExpression* result = | |
| MakeNode<FieldAccessExpression>(object, std::move(field)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeElementAccessExpression( | |
| ParseResultIterator* child_results) { | |
| auto object = child_results->NextAs<Expression*>(); | |
| auto field = child_results->NextAs<Expression*>(); | |
| LocationExpression* result = MakeNode<ElementAccessExpression>(object, field); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeStructExpression( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto expressions = child_results->NextAs<std::vector<Expression*>>(); | |
| Expression* result = | |
| MakeNode<StructExpression>(std::move(name), std::move(expressions)); | |
| return ParseResult{result}; | |
| } | |
| base::Optional<ParseResult> MakeAssignmentExpression( | |
| ParseResultIterator* child_results) { | |
| auto location = child_results->NextAs<LocationExpression*>(); | |
| 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<LocationExpression*>(); | |
| 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<LocationExpression*>(); | |
| 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<std::string>(); | |
| auto types = child_results->NextAs<std::vector<TypeExpression*>>(); | |
| return ParseResult{LabelAndTypes{std::move(name), std::move(types)}}; | |
| } | |
| base::Optional<ParseResult> MakeNameAndType( | |
| ParseResultIterator* child_results) { | |
| auto name = child_results->NextAs<std::string>(); | |
| auto type = child_results->NextAs<TypeExpression*>(); | |
| return ParseResult{NameAndTypeExpression{std::move(name), type}}; | |
| } | |
| base::Optional<ParseResult> ExtractAssignmentOperator( | |
| ParseResultIterator* child_results) { | |
| auto op = child_results->NextAs<std::string>(); | |
| base::Optional<std::string> result = std::string(op.begin(), op.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) { | |
| if (!MatchChar(std::isalpha, pos)) return false; | |
| while (MatchChar(std::isalnum, pos) || MatchString("_", pos)) { | |
| } | |
| 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)}; | |
| // 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({CheckIf(Token("constexpr")), &identifier}, MakeBasicTypeExpression), | |
| Rule({Token("builtin"), Token("("), typeList, Token(")"), Token("=>"), | |
| &simpleType}, | |
| MakeFunctionTypeExpression)}; | |
| // Result: TypeExpression* | |
| Symbol type = {Rule({&simpleType}), Rule({&type, Token("|"), &simpleType}, | |
| MakeUnionTypeExpression)}; | |
| // Result: GenericParameters | |
| Symbol genericParameters = { | |
| Rule({Token("<"), | |
| List<std::string>( | |
| Sequence({&identifier, Token(":"), Token("type")}), Token(",")), | |
| Token(">")})}; | |
| // Result: TypeList | |
| Symbol genericSpecializationTypeList = { | |
| Rule({Token("<"), typeList, Token(">")})}; | |
| // Result: base::Optional<TypeList> | |
| Symbol* optionalGenericParameters = Optional<TypeList>(&genericParameters); | |
| // Result: ParameterList | |
| Symbol typeListMaybeVarArgs = { | |
| Rule({Token("("), List<TypeExpression*>(Sequence({&type, Token(",")})), | |
| Token("..."), Token(")")}, | |
| MakeParameterListFromTypes<true>), | |
| Rule({Token("("), typeList, Token(")")}, | |
| MakeParameterListFromTypes<false>)}; | |
| // Result: LabelAndTypes | |
| Symbol labelParameter = {Rule( | |
| {&identifier, | |
| 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<std::string> | |
| Symbol* optionalOtherwise{TryOrDefault<std::vector<std::string>>( | |
| Sequence({Token("otherwise"), | |
| NonemptyList<std::string>(&identifier, Token(","))}))}; | |
| // Result: NameAndTypeExpression | |
| Symbol nameAndType = { | |
| Rule({&identifier, Token(":"), &type}, MakeNameAndType)}; | |
| // Result: ParameterList | |
| Symbol parameterListNoVararg = { | |
| Rule({Token("("), List<NameAndTypeExpression>(&nameAndType, Token(",")), | |
| Token(")")}, | |
| MakeParameterListFromNameAndTypeList<false>)}; | |
| // Result: ParameterList | |
| Symbol parameterListAllowVararg = { | |
| Rule({¶meterListNoVararg}), | |
| Rule({Token("("), | |
| NonemptyList<NameAndTypeExpression>(&nameAndType, Token(",")), | |
| Token(","), Token("..."), &identifier, Token(")")}, | |
| MakeParameterListFromNameAndTypeList<true>)}; | |
| // Result: std::string | |
| Symbol* OneOf(std::vector<std::string> alternatives) { | |
| Symbol* result = NewSymbol(); | |
| for (const std::string& s : alternatives) { | |
| result->AddRule(Rule({Token(s)}, YieldMatchedInput)); | |
| } | |
| 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: LocationExpression* | |
| Symbol locationExpression = { | |
| Rule( | |
| {&identifier, TryOrDefault<TypeList>(&genericSpecializationTypeList)}, | |
| MakeIdentifierExpression), | |
| Rule({&primaryExpression, Token("."), &identifier}, | |
| MakeFieldAccessExpression), | |
| Rule({&primaryExpression, Token("["), expression, Token("]")}, | |
| MakeElementAccessExpression)}; | |
| // Result: std::vector<Expression*> | |
| Symbol argumentList = {Rule( | |
| {Token("("), List<Expression*>(expression, Token(",")), Token(")")})}; | |
| // Result: Expression* | |
| Symbol callExpression = { | |
| Rule({&identifier, TryOrDefault<TypeList>(&genericSpecializationTypeList), | |
| &argumentList, optionalOtherwise}, | |
| MakeCall)}; | |
| // Result: Expression* | |
| Symbol primaryExpression = { | |
| Rule({&callExpression}), | |
| Rule({&locationExpression}, | |
| CastParseResult<LocationExpression*, Expression*>), | |
| Rule({&decimalLiteral}, MakeNumberLiteralExpression), | |
| Rule({&stringLiteral}, MakeStringLiteralExpression), | |
| Rule({&identifier, Token("{"), List<Expression*>(expression, Token(",")), | |
| Token("}")}, | |
| MakeStructExpression), | |
| Rule({Token("("), expression, Token(")")})}; | |
| // Result: Expression* | |
| Symbol unaryExpression = { | |
| Rule({&primaryExpression}), | |
| Rule({OneOf({"+", "-", "!", "~"}), &unaryExpression}, MakeUnaryOperator), | |
| Rule({&incrementDecrementOperator, &locationExpression}, | |
| MakeIncrementDecrementExpressionPrefix), | |
| Rule({&locationExpression, &incrementDecrementOperator}, | |
| MakeIncrementDecrementExpressionPostfix)}; | |
| // Result: Expression* | |
| Symbol* multiplicativeExpression = | |
| BinaryOperator(&unaryExpression, OneOf({"*", "/", "%"})); | |
| // Result: Expression* | |
| Symbol* additiveExpression = | |
| BinaryOperator(multiplicativeExpression, OneOf({"+", "-"})); | |
| // Result: Expression* | |
| Symbol* shiftExpression = | |
| BinaryOperator(additiveExpression, OneOf({"<<", ">>", ">>>"})); | |
| // 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({&locationExpression, &assignmentOperator, &assignmentExpression}, | |
| MakeAssignmentExpression)}; | |
| // Result: Statement* | |
| Symbol block = {Rule({CheckIf(Token("deferred")), Token("{"), | |
| List<Statement*>(&statement), Token("}")}, | |
| MakeBlockStatement)}; | |
| // Result: LabelBlock* | |
| Symbol labelBlock = { | |
| Rule({Token("label"), &identifier, | |
| TryOrDefault<ParameterList>(¶meterListNoVararg), &block}, | |
| MakeLabelBlock)}; | |
| // Result: ExpressionWithSource | |
| Symbol expressionWithSource = {Rule({expression}, MakeExpressionWithSource)}; | |
| // Result: RangeExpression | |
| Symbol rangeSpecifier = { | |
| Rule({Token("["), Optional<Expression*>(expression), Token(":"), | |
| Optional<Expression*>(expression), Token("]")}, | |
| MakeRangeExpression)}; | |
| // Result: Statement* | |
| Symbol varDeclaration = { | |
| Rule({OneOf({"let", "const"}), &identifier, Token(":"), &type}, | |
| MakeVarDeclarationStatement)}; | |
| // Result: Statement* | |
| Symbol varDeclarationWithInitialization = { | |
| Rule({OneOf({"let", "const"}), &identifier, Token(":"), &type, Token("="), | |
| expression}, | |
| MakeVarDeclarationStatement)}; | |
| // Disallow ambiguous dangling else by only allowing an {atomarStatement} as | |
| // a then-clause. Result: Statement* | |
| Symbol atomarStatement = { | |
| Rule({&block}), | |
| Rule({expression, Token(";")}, MakeExpressionStatement), | |
| Rule({Token("return"), Optional<Expression*>(expression), Token(";")}, | |
| MakeReturnStatement), | |
| Rule({Token("tail"), &callExpression, Token(";")}, MakeTailCallStatement), | |
| Rule({Token("break"), Token(";")}, MakeBreakStatement), | |
| Rule({Token("continue"), Token(";")}, MakeContinueStatement), | |
| Rule({Token("goto"), &identifier, | |
| TryOrDefault<std::vector<Expression*>>(&argumentList), Token(";")}, | |
| MakeGotoStatement), | |
| Rule({OneOf({"debug", "unreachable"}), Token(";")}, MakeDebugStatement)}; | |
| // Result: Statement* | |
| Symbol statement = { | |
| Rule({&atomarStatement}), | |
| Rule({&varDeclaration, Token(";")}), | |
| Rule({&varDeclarationWithInitialization, Token(";")}), | |
| Rule({Token("if"), CheckIf(Token("constexpr")), Token("("), expression, | |
| Token(")"), &atomarStatement, | |
| Optional<Statement*>(Sequence({Token("else"), &statement}))}, | |
| MakeIfStatement), | |
| Rule( | |
| { | |
| Token("typeswitch"), Token("("), expression, Token(")"), | |
| Token("{"), NonemptyList<TypeswitchCase>(&typeswitchCase), | |
| Token("}"), | |
| }, | |
| MakeTypeswitchStatement), | |
| Rule({Token("try"), &block, NonemptyList<LabelBlock*>(&labelBlock)}, | |
| MakeTryLabelStatement), | |
| Rule({OneOf({"assert", "check"}), Token("("), &expressionWithSource, | |
| Token(")"), Token(";")}, | |
| MakeAssertStatement), | |
| Rule({Token("while"), Token("("), expression, Token(")"), | |
| &atomarStatement}, | |
| MakeWhileStatement), | |
| Rule({Token("for"), Token("("), &varDeclaration, Token("of"), expression, | |
| Optional<RangeExpression>(&rangeSpecifier), Token(")"), | |
| &atomarStatement}, | |
| MakeForOfLoopStatement), | |
| Rule({Token("for"), Token("("), | |
| Optional<Statement*>(&varDeclarationWithInitialization), Token(";"), | |
| Optional<Expression*>(expression), Token(";"), | |
| Optional<Expression*>(expression), Token(")"), &atomarStatement}, | |
| MakeForLoopStatement)}; | |
| // Result: TypeswitchCase | |
| Symbol typeswitchCase = { | |
| Rule({Token("case"), Token("("), | |
| Optional<std::string>(Sequence({&identifier, Token(":")})), &type, | |
| 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 declaration = { | |
| Rule({Token("const"), &identifier, Token(":"), &type, Token("="), | |
| expression, Token(";")}, | |
| MakeConstDeclaration), | |
| Rule({Token("const"), &identifier, Token(":"), &type, Token("generates"), | |
| &externalString, Token(";")}, | |
| MakeExternConstDeclaration), | |
| Rule({Token("type"), &identifier, | |
| Optional<std::string>(Sequence({Token("extends"), &identifier})), | |
| Optional<std::string>( | |
| Sequence({Token("generates"), &externalString})), | |
| Optional<std::string>( | |
| Sequence({Token("constexpr"), &externalString})), | |
| Token(";")}, | |
| MakeTypeDeclaration), | |
| Rule({Token("type"), &identifier, Token("="), &type, Token(";")}, | |
| MakeTypeAliasDeclaration), | |
| Rule({Token("extern"), | |
| Optional<std::string>( | |
| Sequence({Token("operator"), &externalString})), | |
| Token("macro"), &identifier, | |
| TryOrDefault<GenericParameters>(&genericParameters), | |
| &typeListMaybeVarArgs, &optionalReturnType, optionalLabelList, | |
| Token(";")}, | |
| MakeExternalMacro), | |
| Rule({Token("extern"), CheckIf(Token("javascript")), Token("builtin"), | |
| &identifier, TryOrDefault<GenericParameters>(&genericParameters), | |
| &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, | |
| MakeExternalBuiltin), | |
| Rule({Token("extern"), Token("runtime"), &identifier, | |
| &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, | |
| MakeExternalRuntime), | |
| Rule({Optional<std::string>( | |
| Sequence({Token("operator"), &externalString})), | |
| Token("macro"), &identifier, | |
| TryOrDefault<GenericParameters>(&genericParameters), | |
| ¶meterListNoVararg, &optionalReturnType, optionalLabelList, | |
| &optionalBody}, | |
| MakeTorqueMacroDeclaration), | |
| Rule({CheckIf(Token("javascript")), Token("builtin"), &identifier, | |
| TryOrDefault<GenericParameters>(&genericParameters), | |
| ¶meterListAllowVararg, &optionalReturnType, &optionalBody}, | |
| MakeTorqueBuiltinDeclaration), | |
| Rule({&identifier, &genericSpecializationTypeList, | |
| ¶meterListAllowVararg, &optionalReturnType, optionalLabelList, | |
| &block}, | |
| MakeSpecializationDeclaration), | |
| Rule({Token("struct"), &identifier, Token("{"), | |
| List<NameAndTypeExpression>(Sequence({&nameAndType, Token(";")})), | |
| Token("}")}, | |
| MakeStructDeclaration)}; | |
| // Result: Declaration* | |
| Symbol moduleDeclaration = { | |
| Rule({Token("module"), &identifier, Token("{"), | |
| List<Declaration*>(&declaration), Token("}")}, | |
| MakeExplicitModuleDeclaration)}; | |
| Symbol file = {Rule({&file, &moduleDeclaration}, AddGlobalDeclaration), | |
| Rule({&file, &declaration}, AddGlobalDeclaration), Rule({})}; | |
| }; | |
| } // namespace | |
| void ParseTorque(const std::string& input) { TorqueGrammar().Parse(input); } | |
| } // namespace torque | |
| } // namespace internal | |
| } // namespace v8 |