From: Arthur Cohen Date: Thu, 9 Nov 2023 17:32:52 +0000 (+0100) Subject: gccrs: fmt: Start working on format_args!() parser X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=473feb033d5ccb139f8af8e0e54193b176d1cd93;p=gcc.git gccrs: fmt: Start working on format_args!() parser This commit adds a base class for parsing the various constructs of a Rust format string, according to the grammar in the reference: https://doc.rust-lang.org/std/fmt/index.html#syntax gcc/rust/ChangeLog: * Make-lang.in: Compile rust-fmt object * ast/rust-fmt.cc: New file. * ast/rust-fmt.h: New file. --- diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index e437c32e3471..c0df49a7fee8 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -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 \ diff --git a/gcc/rust/ast/rust-fmt.cc b/gcc/rust/ast/rust-fmt.cc new file mode 100644 index 000000000000..9f9ba48f0c3a --- /dev/null +++ b/gcc/rust/ast/rust-fmt.cc @@ -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 +// . + +#include "rust-fmt.h" + +namespace Rust { +tl::expected +Fmt::parse_fmt_string (Fmt::Input input) +{ + return Fmt (); +} + +tl::expected>, Fmt::Error> +Fmt::maybe_format (Fmt::Input input) +{ + tl::optional none = tl::nullopt; + + return Fmt::Result (input, none); +} + +tl::expected, Fmt::Error> +Fmt::format (Input input) +{ + return Fmt::Result (input, Format ()); +} + +tl::expected, Fmt::Error> +Fmt::argument (Input input) +{ + return Fmt::Result (input, Argument ()); +} + +tl::expected, Fmt::Error> +Fmt::format_spec (Input input) +{ + return Fmt::Result (input, FormatSpec ()); +} + +tl::expected, Fmt::Error> +Fmt::fill (Input input) +{ + return Fmt::Result (input, Fill ()); +} + +tl::expected, 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::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 diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h new file mode 100644 index 000000000000..f3dd53da9791 --- /dev/null +++ b/gcc/rust/ast/rust-fmt.h @@ -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 +// . + +#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 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 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 struct ParseResult + { + tl::expected, Error> inner; + + ParseResult (tl::expected, Error> inner) : inner (inner) {} + ParseResult operator= (tl::expected, 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, Error> text (Input input); + static tl::expected>, Error> + maybe_format (Input input); + static tl::expected, Error> format (Input input); + static tl::expected, Error> argument (Input input); + static tl::expected, Error> format_spec (Input input); + static tl::expected, Error> fill (Input input); + static tl::expected, Error> align (Input input); + static tl::expected, Error> sign (Input input); +}; + +} // namespace Rust + +#endif // ! RUST_FMT_H