Create interval.h. Use std::size_t instead of bare size_t. Redefine parser::Name to not be just a bare string. Break out and rename CharBlock from token-sequence.h for use in the parse tree. Incremental replacement of name strings with pointers to cooked characters. Fix case sensitivity problem. Use new CharBlock encoding to replace strings for real literal constants. Normalized cooked character stream to lower case. Simplify parsing now that cooked stream is lower case. Replace Keyword in parse tree. Add static_asserts to || and recovery parsers to enforce same result types. Remove needless TODO comment inserted earlier. Fix case conversion on prefixed character literals (f90_correct/dc04.f90). Use CharBlock in user-state.h. Complete transition from nextChar to nextCh (i.e., always use pointers). Document extensions. Begin work on compiler directive lines. More documentation work. Reformat prescan.cc. More work on compiler directive scanning. Original-commit: flang-compiler/f18@38d0404e16 Reviewed-on: https://github.com/flang-compiler/f18/pull/29 Tree-same-pre-rewrite: false
163 lines
5.9 KiB
C++
163 lines
5.9 KiB
C++
#include "parse-tree.h"
|
|
#include "idioms.h"
|
|
#include "indirection.h"
|
|
#include <algorithm>
|
|
|
|
namespace Fortran {
|
|
namespace parser {
|
|
|
|
// R867
|
|
ImportStmt::ImportStmt(Kind &&k, std::list<Name> &&n)
|
|
: kind{k}, names(std::move(n)) {
|
|
CHECK(kind == Kind::Default || kind == Kind::Only || names.empty());
|
|
}
|
|
|
|
// R901 designator
|
|
bool Designator::EndsInBareName() const {
|
|
return std::visit(
|
|
visitors{[](const ObjectName &) { return true; },
|
|
[](const DataReference &dr) {
|
|
return std::holds_alternative<Name>(dr.u) ||
|
|
std::holds_alternative<Indirection<StructureComponent>>(dr.u);
|
|
},
|
|
[](const Substring &) { return false; }},
|
|
u);
|
|
}
|
|
|
|
ProcedureDesignator Designator::ConvertToProcedureDesignator() {
|
|
return std::visit(
|
|
visitors{
|
|
[](ObjectName &n) -> ProcedureDesignator { return {std::move(n)}; },
|
|
[](DataReference &dr) -> ProcedureDesignator {
|
|
if (Name *n = std::get_if<Name>(&dr.u)) {
|
|
return {std::move(*n)};
|
|
}
|
|
StructureComponent &sc{
|
|
*std::get<Indirection<StructureComponent>>(dr.u)};
|
|
return {ProcComponentRef{
|
|
Scalar<Variable>{Indirection<Designator>{std::move(sc.base)}},
|
|
std::move(sc.component)}};
|
|
},
|
|
[](Substring &) -> ProcedureDesignator {
|
|
CHECK(!"can't get here");
|
|
return {Name{}};
|
|
}},
|
|
u);
|
|
}
|
|
|
|
std::optional<Call> Designator::ConvertToCall() {
|
|
return std::visit(
|
|
visitors{[](ObjectName &n) -> std::optional<Call> {
|
|
return {Call{ProcedureDesignator{std::move(n)},
|
|
std::list<ActualArgSpec>{}}};
|
|
},
|
|
[this](DataReference &dr) -> std::optional<Call> {
|
|
if (std::holds_alternative<Indirection<CoindexedNamedObject>>(
|
|
dr.u)) {
|
|
return {};
|
|
}
|
|
if (Name *n = std::get_if<Name>(&dr.u)) {
|
|
return {Call{ProcedureDesignator{std::move(*n)},
|
|
std::list<ActualArgSpec>{}}};
|
|
}
|
|
if (auto *isc =
|
|
std::get_if<Indirection<StructureComponent>>(&dr.u)) {
|
|
StructureComponent &sc{**isc};
|
|
Variable var{Indirection<Designator>{std::move(sc.base)}};
|
|
ProcComponentRef pcr{
|
|
Scalar<Variable>{std::move(var)}, std::move(sc.component)};
|
|
return {Call{ProcedureDesignator{std::move(pcr)},
|
|
std::list<ActualArgSpec>{}}};
|
|
}
|
|
ArrayElement &ae{*std::get<Indirection<ArrayElement>>(dr.u)};
|
|
if (std::any_of(ae.subscripts.begin(), ae.subscripts.end(),
|
|
[](const SectionSubscript &ss) {
|
|
return !ss.CanConvertToActualArgument();
|
|
})) {
|
|
return {};
|
|
}
|
|
std::list<ActualArgSpec> args;
|
|
for (auto &ss : ae.subscripts) {
|
|
args.emplace_back(
|
|
std::optional<Keyword>{}, ss.ConvertToActualArgument());
|
|
}
|
|
if (Name * n{std::get_if<Name>(&ae.base.u)}) {
|
|
return {
|
|
Call{ProcedureDesignator{std::move(*n)}, std::move(args)}};
|
|
}
|
|
StructureComponent &bsc{
|
|
*std::get<Indirection<StructureComponent>>(ae.base.u)};
|
|
Variable var{Indirection<Designator>{std::move(bsc.base)}};
|
|
ProcComponentRef pcr{
|
|
Scalar<Variable>{std::move(var)}, std::move(bsc.component)};
|
|
return {Call{ProcedureDesignator{std::move(pcr)}, std::move(args)}};
|
|
},
|
|
[](const Substring &) -> std::optional<Call> { return {}; }},
|
|
u);
|
|
}
|
|
|
|
// R911 data-ref -> part-ref [% part-ref]...
|
|
DataReference::DataReference(std::list<PartRef> &&prl)
|
|
: u{std::move(prl.front().name)} {
|
|
for (bool first{true}; !prl.empty(); first = false, prl.pop_front()) {
|
|
PartRef &pr{prl.front()};
|
|
if (!first) {
|
|
u = Indirection<StructureComponent>{std::move(*this), std::move(pr.name)};
|
|
}
|
|
if (!pr.subscripts.empty()) {
|
|
u = Indirection<ArrayElement>{std::move(*this), std::move(pr.subscripts)};
|
|
}
|
|
if (pr.imageSelector.has_value()) {
|
|
u = Indirection<CoindexedNamedObject>{
|
|
std::move(*this), std::move(*pr.imageSelector)};
|
|
}
|
|
}
|
|
}
|
|
|
|
// R920 section-subscript
|
|
bool SectionSubscript::CanConvertToActualArgument() const {
|
|
return std::visit(visitors{[](const VectorSubscript &) { return true; },
|
|
[](const ScalarIntExpr &) { return true; },
|
|
[](const SubscriptTriplet &) { return false; }},
|
|
u);
|
|
}
|
|
|
|
ActualArg SectionSubscript::ConvertToActualArgument() {
|
|
return std::visit(visitors{[](VectorSubscript &vs) -> ActualArg {
|
|
return vs.thing->ConvertToActualArgument();
|
|
},
|
|
[](ScalarIntExpr &vs) -> ActualArg {
|
|
return vs.thing.thing->ConvertToActualArgument();
|
|
},
|
|
[](SubscriptTriplet &) -> ActualArg {
|
|
CHECK(!"can't happen");
|
|
return {Name{}};
|
|
}},
|
|
u);
|
|
}
|
|
|
|
// R1001 - R1022 expression
|
|
Expr::Expr(Designator &&x) : u{Indirection<Designator>(std::move(x))} {}
|
|
Expr::Expr(FunctionReference &&x)
|
|
: u{Indirection<FunctionReference>(std::move(x))} {}
|
|
|
|
std::optional<Variable> Expr::ConvertToVariable() {
|
|
if (Indirection<Designator> *id = std::get_if<Indirection<Designator>>(&u)) {
|
|
return {Variable{std::move(*id)}};
|
|
}
|
|
if (Indirection<FunctionReference> *ifr =
|
|
std::get_if<Indirection<FunctionReference>>(&u)) {
|
|
return {Variable{std::move(*ifr)}};
|
|
}
|
|
return {};
|
|
}
|
|
|
|
ActualArg Expr::ConvertToActualArgument() {
|
|
if (std::optional<Variable> var{ConvertToVariable()}) {
|
|
return {std::move(var.value())};
|
|
}
|
|
return {std::move(*this)};
|
|
}
|
|
} // namespace parser
|
|
} // namespace Fortran
|