Implements part of the legacy "DEC structures" feature from VMS Fortran. STRUCTUREs are processed as if they were derived types with SEQUENCE. DATA-like object entity initialization is supported as well (e.g., INTEGER FOO/666/) since it was used for default component initialization in structures. Anonymous components (named %FILL) are also supported. These features, and UNION/MAP, were already being parsed. An omission in the collection of structure field names in the case of nested structures with entity declarations was fixed in the parser. Structures are supported in modules, but this is mostly for testing purposes. The names of fields in structures accessed via USE association cannot appear with dot notation in client code (at least not yet). DEC structures antedate Fortran 90, so their actual use in applications should not involve modules. This patch does not implement UNION/MAP, since that feature would impose difficulties later in lowering them to MLIR types. In the meantime, if they appear, semantics will issue a "not yet implemented" error message. Differential Revision: https://reviews.llvm.org/D117151
110 lines
3.3 KiB
C++
110 lines
3.3 KiB
C++
//===-- lib/Parser/user-state.cpp -----------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Parser/user-state.h"
|
|
#include "stmt-parser.h"
|
|
#include "type-parsers.h"
|
|
#include "flang/Parser/parse-state.h"
|
|
#include <optional>
|
|
|
|
namespace Fortran::parser {
|
|
|
|
std::optional<Success> StartNewSubprogram::Parse(ParseState &state) {
|
|
if (auto *ustate{state.userState()}) {
|
|
ustate->NewSubprogram();
|
|
}
|
|
return Success{};
|
|
}
|
|
|
|
std::optional<CapturedLabelDoStmt::resultType> CapturedLabelDoStmt::Parse(
|
|
ParseState &state) {
|
|
static constexpr auto parser{statement(indirect(Parser<LabelDoStmt>{}))};
|
|
auto result{parser.Parse(state)};
|
|
if (result) {
|
|
if (auto *ustate{state.userState()}) {
|
|
ustate->NewDoLabel(std::get<Label>(result->statement.value().t));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::optional<EndDoStmtForCapturedLabelDoStmt::resultType>
|
|
EndDoStmtForCapturedLabelDoStmt::Parse(ParseState &state) {
|
|
static constexpr auto parser{
|
|
statement(indirect(construct<EndDoStmt>("END DO" >> maybe(name))))};
|
|
if (auto enddo{parser.Parse(state)}) {
|
|
if (enddo->label) {
|
|
if (const auto *ustate{state.userState()}) {
|
|
if (ustate->IsDoLabel(enddo->label.value())) {
|
|
return enddo;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<Success> EnterNonlabelDoConstruct::Parse(ParseState &state) {
|
|
if (auto *ustate{state.userState()}) {
|
|
ustate->EnterNonlabelDoConstruct();
|
|
}
|
|
return {Success{}};
|
|
}
|
|
|
|
std::optional<Success> LeaveDoConstruct::Parse(ParseState &state) {
|
|
if (auto ustate{state.userState()}) {
|
|
ustate->LeaveDoConstruct();
|
|
}
|
|
return {Success{}};
|
|
}
|
|
|
|
// These special parsers for bits of DEC STRUCTURE capture the names of
|
|
// their components and nested structures in the user state so that
|
|
// references to these fields with periods can be recognized as special
|
|
// cases.
|
|
|
|
std::optional<Name> OldStructureComponentName::Parse(ParseState &state) {
|
|
if (std::optional<Name> n{name.Parse(state)}) {
|
|
if (const auto *ustate{state.userState()}) {
|
|
if (ustate->IsOldStructureComponent(n->source)) {
|
|
return n;
|
|
}
|
|
}
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<DataComponentDefStmt> StructureComponents::Parse(
|
|
ParseState &state) {
|
|
static constexpr auto stmt{Parser<DataComponentDefStmt>{}};
|
|
std::optional<DataComponentDefStmt> defs{stmt.Parse(state)};
|
|
if (defs) {
|
|
if (auto *ustate{state.userState()}) {
|
|
for (const auto &item : std::get<std::list<ComponentOrFill>>(defs->t)) {
|
|
if (const auto *decl{std::get_if<ComponentDecl>(&item.u)}) {
|
|
ustate->NoteOldStructureComponent(std::get<Name>(decl->t).source);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return defs;
|
|
}
|
|
|
|
std::optional<StructureStmt> NestedStructureStmt::Parse(ParseState &state) {
|
|
std::optional<StructureStmt> stmt{Parser<StructureStmt>{}.Parse(state)};
|
|
if (stmt) {
|
|
if (auto *ustate{state.userState()}) {
|
|
for (const auto &entity : std::get<std::list<EntityDecl>>(stmt->t)) {
|
|
ustate->NoteOldStructureComponent(std::get<Name>(entity.t).source);
|
|
}
|
|
}
|
|
}
|
|
return stmt;
|
|
}
|
|
} // namespace Fortran::parser
|