From 220d827dbbbf354a80ab5adeb4b9a8be01834e48 Mon Sep 17 00:00:00 2001 From: NotAFile Date: Tue, 1 Feb 2022 02:00:27 +0100 Subject: [PATCH] switch to ariadne and greedyerror --- Cargo.lock | 130 +++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 3 + src/main.rs | 24 ++++---- src/parser.rs | 11 ++-- src/parser/error.rs | 38 ++++++++++++ src/parser/literals.rs | 8 ++- 6 files changed, 191 insertions(+), 23 deletions(-) create mode 100644 src/parser/error.rs diff --git a/Cargo.lock b/Cargo.lock index 1a65225..87c522a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "ariadne" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7080ae01b2f0c312065d4914cd0f0de045eb8832e9415b355106a6cff3073cb4" +dependencies = [ + "yansi", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "atty" version = "0.2.14" @@ -28,12 +43,24 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytecount" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" + [[package]] name = "bytecount" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "2.34.0" @@ -53,8 +80,11 @@ dependencies = [ name = "futilehdl" version = "0.1.0" dependencies = [ - "nom", - "nom_locate", + "ariadne", + "nom 7.1.0", + "nom-greedyerror", + "nom_locate 4.0.0", + "smol_str", "structopt", ] @@ -82,6 +112,19 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.115" @@ -100,6 +143,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "lexical-core", + "memchr", + "version_check", +] + [[package]] name = "nom" version = "7.1.0" @@ -111,15 +165,50 @@ dependencies = [ "version_check", ] +[[package]] +name = "nom-greedyerror" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcd01dcb46ac4b8133a093685c5133b044d45c35f10ac9b6606e4db780d94ac7" +dependencies = [ + "nom 5.1.2", + "nom 7.1.0", + "nom_locate 1.0.0", + "nom_locate 2.1.0", + "nom_locate 4.0.0", +] + +[[package]] +name = "nom_locate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f932834fd8e391fc7710e2ba17e8f9f8645d846b55aa63207e17e110a1e1ce35" +dependencies = [ + "bytecount 0.3.2", + "memchr", + "nom 5.1.2", +] + +[[package]] +name = "nom_locate" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67484adf5711f94f2f28b653bf231bff8e438be33bf5b0f35935a0db4f618a2" +dependencies = [ + "bytecount 0.6.2", + "memchr", + "nom 5.1.2", +] + [[package]] name = "nom_locate" version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37794436ca3029a3089e0b95d42da1f0b565ad271e4d3bb4bad0c7bb70b10605" dependencies = [ - "bytecount", + "bytecount 0.6.2", "memchr", - "nom", + "nom 7.1.0", ] [[package]] @@ -164,6 +253,33 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" + +[[package]] +name = "smol_str" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61d15c83e300cce35b7c8cd39ff567c1ef42dde6d4a1a38dbdbf9a59902261bd" +dependencies = [ + "serde", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.8.0" @@ -265,3 +381,9 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "yansi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71" diff --git a/Cargo.toml b/Cargo.toml index a404f6e..8c06711 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +ariadne = "0.1.3" nom = "7.1.0" +nom-greedyerror = "0.4.0" nom_locate = "4.0.0" +smol_str = "0.1.21" structopt = "0.3.26" diff --git a/src/main.rs b/src/main.rs index 345c6f0..dec7247 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ mod builtin_cells; mod frontend; -mod literals; mod package; mod parser; mod rtlil; @@ -8,7 +7,10 @@ mod rtlil; use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; + use structopt::StructOpt; +use nom_greedyerror::convert_error; +use ariadne::Source; #[derive(Debug, StructOpt)] #[structopt(name = "example", about = "An example of StructOpt usage.")] @@ -26,13 +28,13 @@ struct Opt { fn main() { let opt = Opt::from_args(); - // let mut infile = File::open(opt.input).expect("could not open file"); - let packages = package::PackageRegistry::new(); - let mut infile = packages - .get("builtins") - .expect("no package") - .open() - .expect("could not open file"); + let mut infile = File::open(opt.input).expect("could not open file"); + // let packages = package::PackageRegistry::new(); + // let mut infile = packages + // .get("builtins") + // .expect("no package") + // .open() + // .expect("could not open file"); let mut input = String::new(); infile @@ -43,11 +45,9 @@ fn main() { let parsed = parser::parse(input); match parsed { Err(nom::Err::Error(err) | nom::Err::Failure(err)) => { - // TODO: get pretty errors again - // print!("{}", convert_error(*input, err)) - print!("{}", err); + parser::error::convert_error(input, err).eprint(Source::from(input.fragment())).unwrap(); } - Err(_) => (), + Err(_) => ( unreachable!() ), Ok(res) => { if opt.debug { println!("{:#?}", res); diff --git a/src/parser.rs b/src/parser.rs index 57d8dcf..9863628 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,25 +1,28 @@ pub mod module; pub mod proc; +mod literals; +pub mod error; use nom::{ branch::alt, bytes::complete::tag, character::complete::{alpha1, alphanumeric1, char, multispace0, u64 as decimal}, combinator::{map, opt, recognize}, - error::{ParseError, VerboseError}, + error::{ParseError, ErrorKind}, multi::{many0, separated_list0}, sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, }; - +use nom_greedyerror::GreedyError; use nom_locate::LocatedSpan; // custom span type for nom_locate pub type Span<'a> = LocatedSpan<&'a str>; +pub type IErr = GreedyError; // custom IResult type for VerboseError -pub type IResult> = nom::IResult; +pub type IResult> = nom::IResult; -use crate::literals::hexadecimal; +use literals::hexadecimal; pub use crate::parser::module::{module, Module, ModuleItem, PortDirection}; fn ws0<'a, F: 'a, O, E: ParseError>>( diff --git a/src/parser/error.rs b/src/parser/error.rs new file mode 100644 index 0000000..3360c2e --- /dev/null +++ b/src/parser/error.rs @@ -0,0 +1,38 @@ +use std::fmt::Debug; +use std::ops::Deref; + +use super::{Span, IErr}; +use nom::error::ErrorKind; +use nom_greedyerror::{Position, GreedyErrorKind}; +use ariadne::{Report, ReportKind, Label}; + +fn span_to_range(input: Span) -> std::ops::Range { + input.position()..(input.position() + input.len()) +} + +pub fn convert_error( + input: Span, + e: IErr, +) -> Report { + let mut labels = Vec::new(); + for err in e.errors { + let label = match err.1 { + GreedyErrorKind::Context(ctx) => { + Label::new(span_to_range(err.0)) + .with_message(format!("in {ctx}")) + }, + GreedyErrorKind::Char(c) => { + Label::new(err.0.position()..err.0.position()) + .with_message(format!("expected {c:?}")) + }, + GreedyErrorKind::Nom(_) => todo!(), + }; + labels.push(label); + } + let mut rep = Report::build(ReportKind::Error, (), 0) + .with_message("Parse Error"); + for lbl in labels { + rep = rep.with_label(lbl) + } + rep.finish() +} diff --git a/src/parser/literals.rs b/src/parser/literals.rs index 84ad4e5..403d1fd 100644 --- a/src/parser/literals.rs +++ b/src/parser/literals.rs @@ -1,6 +1,6 @@ use nom::{ character::complete::{char, one_of}, - combinator::{map_res, recognize}, + combinator::{map, recognize}, multi::{many0, many1}, sequence::{preceded, terminated}, }; @@ -8,7 +8,7 @@ use nom::{ use crate::parser::{IResult, Span}; pub fn hexadecimal(input: Span) -> IResult { - map_res( + map( preceded( char('h'), recognize(many1(terminated( @@ -16,7 +16,9 @@ pub fn hexadecimal(input: Span) -> IResult { many0(char('_')), ))), ), - |out: Span| u64::from_str_radix(&str::replace(out.fragment(), "_", ""), 16), + |out: Span| { + u64::from_str_radix(&str::replace(out.fragment(), "_", ""), 16).expect("error parsing literal") + }, )(input) }