@@ -100,6 +100,7 @@ GRS_OBJS = \
rust/rust-proc-macro-invoc-lexer.o \
rust/rust-macro-substitute-ctx.o \
rust/rust-macro-builtins.o \
+ rust/rust-fmt.o \
rust/rust-hir.o \
rust/rust-hir-map.o \
rust/rust-attributes.o \
new file mode 100644
@@ -0,0 +1,96 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-fmt.h"
+
+namespace Rust {
+tl::expected<Fmt, Fmt::Error>
+Fmt::parse_fmt_string (Fmt::Input input)
+{
+ return Fmt ();
+}
+
+tl::expected<Fmt::Result<tl::optional<Fmt::Format>>, Fmt::Error>
+Fmt::maybe_format (Fmt::Input input)
+{
+ tl::optional<Fmt::Format> none = tl::nullopt;
+
+ return Fmt::Result (input, none);
+}
+
+tl::expected<Fmt::Result<Fmt::Format>, Fmt::Error>
+Fmt::format (Input input)
+{
+ return Fmt::Result (input, Format ());
+}
+
+tl::expected<Fmt::Result<Fmt::Argument>, Fmt::Error>
+Fmt::argument (Input input)
+{
+ return Fmt::Result (input, Argument ());
+}
+
+tl::expected<Fmt::Result<Fmt::FormatSpec>, Fmt::Error>
+Fmt::format_spec (Input input)
+{
+ return Fmt::Result (input, FormatSpec ());
+}
+
+tl::expected<Fmt::Result<Fmt::Fill>, Fmt::Error>
+Fmt::fill (Input input)
+{
+ return Fmt::Result (input, Fill ());
+}
+
+tl::expected<Fmt::Result<Fmt::Align>, Fmt::Error>
+Fmt::align (Input input)
+{
+ switch (input[0])
+ {
+ case '<':
+ return Fmt::Result (input.substr (1), Align::Left);
+ case '^':
+ return Fmt::Result (input.substr (1), Align::Top);
+ case '>':
+ return Fmt::Result (input.substr (1), Align::Right);
+ default:
+ // TODO: Store the character here
+ // TODO: Can we have proper error locations?
+ // TODO: Maybe we should use a Rust::Literal string instead of a string
+ return tl::make_unexpected (Error::Align);
+ }
+}
+
+tl::expected<Fmt::Result<Fmt::Sign>, Fmt::Error>
+Fmt::sign (Input input)
+{
+ switch (input[0])
+ {
+ case '+':
+ return Fmt::Result (input.substr (1), Sign::Plus);
+ case '-':
+ return Fmt::Result (input.substr (1), Sign::Minus);
+ default:
+ // TODO: Store the character here
+ // TODO: Can we have proper error locations?
+ // TODO: Maybe we should use a Rust::Literal string instead of a string
+ return tl::make_unexpected (Error::Sign);
+ }
+}
+
+} // namespace Rust
new file mode 100644
@@ -0,0 +1,133 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_FMT_H
+#define RUST_FMT_H
+
+#include "expected.h"
+#include "optional.h"
+#include "rust-ast.h"
+#include "rust-system.h"
+
+namespace Rust {
+
+/**
+ * This class implements the parsing of Rust format strings according to the
+ * grammar here: https://doc.rust-lang.org/std/fmt/index.html#syntax
+ */
+// TODO: Are there features that are only present in specific Rust editions?
+class Fmt
+{
+public:
+ // TODO: Keep location information
+ // TODO: Switch to a Rust::AST::Literal here
+ using Input = std::string;
+
+ enum class Error
+ {
+ Align,
+ Sign,
+ };
+
+ template <typename T> class Result
+ {
+ public:
+ explicit Result (Input remaining_input, T result)
+ : remaining_input (remaining_input), result (result)
+ {}
+
+ private:
+ Input remaining_input;
+ T result;
+ };
+
+ // FIXME: Do not use an owned string here
+ static tl::expected<Fmt, Fmt::Error> parse_fmt_string (Input input);
+
+private:
+ // the parse functions should return the remaining input as well as the
+ // expected node let's look at nom
+ // TODO: no string view :( use an owned string for now?
+
+ template <typename T> struct ParseResult
+ {
+ tl::expected<Result<T>, Error> inner;
+
+ ParseResult (tl::expected<Result<T>, Error> inner) : inner (inner) {}
+ ParseResult operator= (tl::expected<Result<T>, Error> inner)
+ {
+ return ParseResult (inner);
+ }
+
+ Input remaining_input () { return inner->remaining_input; }
+ T value () { return inner->value; }
+ };
+
+ struct Format
+ {
+ };
+
+ struct Argument
+ {
+ enum struct Kind
+ {
+ Integer,
+ Identifier,
+ } kind;
+
+ int integer;
+ Identifier identifier;
+ };
+
+ struct FormatSpec
+ {
+ };
+
+ struct Fill
+ {
+ char to_fill;
+ };
+
+ enum class Align
+ {
+ Left,
+ Top,
+ Right
+ };
+
+ enum class Sign
+ {
+ Plus,
+ Minus
+ };
+
+ // let's do one function per rule in the BNF
+ static tl::expected<Result<std::string>, Error> text (Input input);
+ static tl::expected<Result<tl::optional<Format>>, Error>
+ maybe_format (Input input);
+ static tl::expected<Result<Format>, Error> format (Input input);
+ static tl::expected<Result<Argument>, Error> argument (Input input);
+ static tl::expected<Result<FormatSpec>, Error> format_spec (Input input);
+ static tl::expected<Result<Fill>, Error> fill (Input input);
+ static tl::expected<Result<Align>, Error> align (Input input);
+ static tl::expected<Result<Sign>, Error> sign (Input input);
+};
+
+} // namespace Rust
+
+#endif // ! RUST_FMT_H