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}
|
log = { version = "0.4.21", optional = true}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
anyhow = "1.0.81"
|
||||||
# parser
|
# parser
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
|
|
||||||
[features]
|
[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" ]
|
parser = [ "regex", "thiserror", "convert_case" ]
|
||||||
types = [ "parser", "libc", "log", "proc-macro2", "quote", "syn", "thiserror", "convert_case" ]
|
types = [ "parser", "libc", "log", "proc-macro2", "quote", "syn", "thiserror", "convert_case" ]
|
||||||
macros = [ "parser", "types", "prettyplease", "proc-macro2", "quote", "syn", "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