feat(bin): Add a binary, that helps in showing the generated code
This commit is contained in:
parent
eb7a901d09
commit
ec929dabe5
|
@ -41,12 +41,19 @@ libc ={ version = "0.2.153", optional = true}
|
|||
log = { version = "0.4.21", optional = true}
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0.81"
|
||||
# parser
|
||||
pretty_assertions = "1.4.0"
|
||||
|
||||
[features]
|
||||
default = ["parser", "types", "macros"]
|
||||
default = ["parser", "types", "macros", "build-binary"]
|
||||
# default = ["parser", "types", "macros"]
|
||||
build-binary = ["clap", "parser", "types", "macros"]
|
||||
|
||||
parser = [ "regex", "thiserror", "convert_case" ]
|
||||
types = [ "parser", "libc", "log", "proc-macro2", "quote", "syn", "thiserror", "convert_case" ]
|
||||
macros = [ "parser", "types", "prettyplease", "proc-macro2", "quote", "syn", "convert_case" ]
|
||||
|
||||
[[bin]]
|
||||
name = "trixy"
|
||||
required-features = ["build-binary"]
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
//! Wonderful command line interface
|
||||
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
#[command(propagate_version = true)]
|
||||
#[command(disable_colored_help = false)]
|
||||
#[command(color = clap::ColorChoice::Auto)]
|
||||
/// A helper CLI to work with Trixy files
|
||||
pub struct Cli {
|
||||
/// The Trixy API file to use
|
||||
#[arg(/* short = 'f', long, */value_name = "FILE")]
|
||||
pub api_file: PathBuf,
|
||||
|
||||
#[command(subcommand)]
|
||||
/// The mode in which to work with the file
|
||||
pub mode: Mode,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
/// A way to work with a Trixy file
|
||||
pub enum Mode {
|
||||
/// Perform operations on the Trixy file, without involving the code gen
|
||||
Parse {
|
||||
#[command(subcommand)]
|
||||
/// How to parse the file
|
||||
parse_command: ParseCommand,
|
||||
},
|
||||
/// Involving the code gen, when working with a trixy file
|
||||
Generate {
|
||||
/// The languages to generate for
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
value_name = "LANGUAGE",
|
||||
value_enum,
|
||||
default_value = "all",
|
||||
global = true
|
||||
)]
|
||||
language: Language,
|
||||
|
||||
#[command(subcommand)]
|
||||
/// What to generate from the file
|
||||
gen_command: GenCommand,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Clone, Copy)]
|
||||
/// Specify what to parse
|
||||
pub enum ParseCommand {
|
||||
/// Only replace the regex replacements in the file
|
||||
Replace,
|
||||
|
||||
/// Only try to tokenize the file
|
||||
#[command(visible_alias = "lex")]
|
||||
Tokenize,
|
||||
|
||||
/// Check syntax, without type checking
|
||||
Parse,
|
||||
/// Check syntax and perform a type check
|
||||
Process,
|
||||
|
||||
/// Act on the file as the `trixy-parser` crate would do it
|
||||
Library,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Clone, Copy)]
|
||||
/// Specify what to generate
|
||||
pub enum GenCommand {
|
||||
/// Generate host code for a language
|
||||
Host,
|
||||
|
||||
/// Generate auxiliary code for a language
|
||||
Auxiliary,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||
/// Which language to generate the code in
|
||||
///
|
||||
/// If you, for example, specified to generate auxiliary files, than setting this to c means, that we generate c
|
||||
/// header files.
|
||||
pub enum Language {
|
||||
/// c
|
||||
C,
|
||||
|
||||
/// Rust
|
||||
Rust,
|
||||
|
||||
/// lua
|
||||
Lua,
|
||||
|
||||
/// All supported languages
|
||||
All,
|
||||
}
|
||||
|
||||
impl From<trixy::macros::config::trixy::Language> for Language {
|
||||
fn from(value: trixy::macros::config::trixy::Language) -> Self {
|
||||
match value {
|
||||
trixy::macros::config::trixy::Language::Rust => Self::Rust,
|
||||
trixy::macros::config::trixy::Language::C => Self::C,
|
||||
trixy::macros::config::trixy::Language::Lua => Self::Lua,
|
||||
trixy::macros::config::trixy::Language::All => Self::All,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Language> for trixy::macros::config::trixy::Language {
|
||||
fn from(value: Language) -> Self {
|
||||
match value {
|
||||
Language::C => Self::C,
|
||||
Language::Rust => Self::Rust,
|
||||
Language::Lua => Self::Lua,
|
||||
Language::All => Self::All,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
use std::path::Path;
|
||||
|
||||
use trixy::macros::config::trixy::TrixyConfig;
|
||||
|
||||
use crate::cli::{GenCommand, Language};
|
||||
|
||||
pub fn handle(gen_command: GenCommand, language: Language, api_file: &Path) {
|
||||
let base_config = TrixyConfig::new("callback_function")
|
||||
.trixy_path(api_file.to_owned())
|
||||
.dist_dir_path("dist")
|
||||
.out_dir("out/dir");
|
||||
|
||||
match gen_command {
|
||||
GenCommand::Host => {
|
||||
let file_tree = base_config.generate();
|
||||
println!("{}", file_tree);
|
||||
}
|
||||
GenCommand::Auxiliary => todo!(),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use crate::cli::Cli;
|
||||
|
||||
pub mod generate;
|
||||
pub mod parse;
|
||||
|
||||
pub mod cli;
|
||||
|
||||
pub fn main() {
|
||||
let args = Cli::parse();
|
||||
match args.mode {
|
||||
cli::Mode::Parse { parse_command } => parse::handle(parse_command, &args.api_file),
|
||||
cli::Mode::Generate {
|
||||
language,
|
||||
gen_command,
|
||||
} => generate::handle(gen_command, language, &args.api_file),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
||||
use clap::CommandFactory;
|
||||
Cli::command().debug_assert()
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
use std::{fs, path::Path, process};
|
||||
|
||||
use trixy::parser::{
|
||||
command_spec::{checked, unchecked},
|
||||
lexing::TokenStream,
|
||||
parse_trixy_lang,
|
||||
};
|
||||
|
||||
use crate::cli::ParseCommand;
|
||||
|
||||
pub fn handle(parse_command: ParseCommand, api_file: &Path) {
|
||||
let input = fs::read_to_string(api_file).unwrap();
|
||||
|
||||
let input_tokens = tokenize(&input);
|
||||
let parsed = parse_unchecked(input_tokens.clone());
|
||||
let processed = process(parsed.clone(), input.clone());
|
||||
|
||||
match parse_command {
|
||||
// These also map the path the file undergoes when it is put into the [`parse_trixy_lang`]
|
||||
// function.
|
||||
ParseCommand::Replace => {
|
||||
let parsed = TokenStream::replace(&input);
|
||||
println!("{}", parsed);
|
||||
}
|
||||
ParseCommand::Tokenize => {
|
||||
println!("{:#?}", input_tokens);
|
||||
}
|
||||
ParseCommand::Parse => {
|
||||
println!("{:#?}", parsed);
|
||||
}
|
||||
ParseCommand::Process => {
|
||||
println!("{:#?}", processed);
|
||||
}
|
||||
|
||||
ParseCommand::Library => {
|
||||
let parsed = parse_trixy_lang(&input).unwrap_or_else(|err| {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
println!("{:#?}", parsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tokenize(input: &str) -> TokenStream {
|
||||
match TokenStream::lex(&input) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
eprintln!("Error while tokenizing:");
|
||||
eprintln!("{}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_unchecked(token_stream: TokenStream) -> unchecked::CommandSpec {
|
||||
match token_stream.parse_unchecked() {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
eprintln!("Error while doing the first (unchecked) parsing run:");
|
||||
eprintln!("{}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process(command_spec: unchecked::CommandSpec, input: String) -> checked::CommandSpec {
|
||||
match command_spec.process(input) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
eprintln!("Error while doing the second (checked) parsing run:");
|
||||
eprintln!("{}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue