mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
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.
This commit is contained 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 \
|
||||
|
||||
96
gcc/rust/ast/rust-fmt.cc
Normal file
96
gcc/rust/ast/rust-fmt.cc
Normal file
@@ -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
|
||||
133
gcc/rust/ast/rust-fmt.h
Normal file
133
gcc/rust/ast/rust-fmt.h
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user