diff --git a/Cargo.lock b/Cargo.lock index e60da52a51b868f11e416491c6920b7769db653e..ba4de2d5cebcc6d51435aed97cb43ef21737883a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,21 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "borsh" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +dependencies = [ + "cfg_aliases", +] + [[package]] name = "bytecount" version = "0.6.8" @@ -30,25 +45,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "codespan" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4b418d52c9206820a56fc1aa28db73d67e346ba8ba6aa90987e8d6becef7e4" -dependencies = [ - "codespan-reporting", - "serde", -] - -[[package]] -name = "codespan-reporting" -version = "0.12.0" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" -dependencies = [ - "serde", - "termcolor", - "unicode-width", -] +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "convert_case" @@ -77,16 +77,10 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.100", + "syn", "unicode-xid", ] -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - [[package]] name = "gdextension-api" version = "0.2.2" @@ -175,57 +169,25 @@ name = "grimoire" version = "0.0.1" dependencies = [ "anyhow", - "godot", - "grimoire-parser", - "thiserror", -] - -[[package]] -name = "grimoire-parser" -version = "0.0.1" -dependencies = [ + "bitflags", "bytecount", "cfg-if", - "codespan", - "codespan-reporting", "derive_more", - "grimoire-parser-derive", + "godot", "log", - "paste", -] - -[[package]] -name = "grimoire-parser-derive" -version = "0.0.1" -dependencies = [ - "indexmap", - "proc-macro2", - "quote", - "syn 1.0.109", + "memchr", + "nom", + "nom_locate", + "smol_str", + "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "indexmap" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "libc" version = "0.2.172" @@ -278,10 +240,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a846cbc04412cf509efcd8f3694b114fc700a035fb5a37f21517f9fb019f1ebc" [[package]] -name = "paste" -version = "1.0.15" +name = "nom" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom_locate" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b577e2d69827c4740cba2b52efaad1c4cc7c73042860b199710b3575c68438d" +dependencies = [ + "bytecount", + "memchr", + "nom", +] [[package]] name = "proc-macro2" @@ -347,18 +323,17 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] -name = "syn" -version = "1.0.109" +name = "smol_str" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "borsh", + "serde", ] [[package]] @@ -372,15 +347,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "2.0.12" @@ -398,7 +364,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -419,12 +385,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" -[[package]] -name = "unicode-width" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" - [[package]] name = "unicode-xid" version = "0.2.6" @@ -440,85 +400,3 @@ dependencies = [ "proc-macro2", "quote", ] - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index 084e1728f0ce34c82c2ebb04add38701bba2ffbe..3edf4d3efab4f40fb91fd6356dc3f01559bf6d40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,33 +1,20 @@ -[workspace] -resolver = "2" -members = ["grimoire-*"] -package = { version = "0.0.1", license = "MIT", rust-version = "1.86", edition = "2024", authors = [ - "Maëlle Martin <maelle.martin@proton.me>", -] } - - [package] -name = "grimoire" -description = "The Grimoire Engine, a VN engine done for fun" - -version.workspace = true -edition.workspace = true -license.workspace = true -authors.workspace = true -rust-version.workspace = true +name = "grimoire" +description = "The Grimoire Engine, a VN engine done for fun" +version = "0.0.1" +license = "MIT" +rust-version = "1.86" +edition = "2024" + +authors = [ + "Maëlle Martin <maelle.martin@proton.me>", +] [lib] crate-type = ["cdylib"] -[dependencies] -grimoire-parser.workspace = true -thiserror.workspace = true -anyhow = "1" -godot = { git = "https://github.com/godot-rust/gdext.git", features = ["api-4-4", "register-docs"] } - - [profile.release] debug = false opt-level = 3 @@ -42,10 +29,10 @@ debug = true opt-level = "s" -[workspace.dependencies] -grimoire-parser = { path = "grimoire-parser" } -grimoire-parser-derive = { path = "grimoire-parser-derive" } - +[dependencies] +anyhow = "1" +nom = "8" +nom_locate = "5" bytecount = "0.6" cfg-if = "1" thiserror = "2" @@ -53,3 +40,8 @@ log = "0.4" derive_more = { version = "2", features = ["full"] } smol_str = { version = "0.3", features = ["serde"] } bitflags = { version = "2", default-features = false } +memchr = { version = "*", default-features = false } # ^1.0.0 + ^2.0 + +[dependencies.godot] +git = "https://github.com/godot-rust/gdext.git" +features = ["api-4-4", "register-docs"] diff --git a/grimoire-parser-derive/Cargo.toml b/grimoire-parser-derive/Cargo.toml deleted file mode 100644 index 4da1313d511822de34508ee85c9d2c0f295fec07..0000000000000000000000000000000000000000 --- a/grimoire-parser-derive/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "grimoire-parser-derive" -description = "Internally used for the grimoire-parser crate." - - -license.workspace = true -version.workspace = true -edition.workspace = true -authors.workspace = true - - -[lib] -proc-macro = true - - -[dependencies] -syn = { version = "1", features = ["extra-traits"] } -quote = "1" -proc-macro2 = "1" -indexmap = "2" diff --git a/grimoire-parser-derive/src/lib.rs b/grimoire-parser-derive/src/lib.rs deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/grimoire-parser/Cargo.toml b/grimoire-parser/Cargo.toml deleted file mode 100644 index 6ff9dcac36dbb783dc3f041c8ba24ee9cf71fbc6..0000000000000000000000000000000000000000 --- a/grimoire-parser/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "grimoire-parser" -description = "A parser for Grimoire Scripts." - -license.workspace = true -version.workspace = true -edition.workspace = true -authors.workspace = true - -[dependencies] -grimoire-parser-derive.workspace = true - -bytecount.workspace = true -cfg-if.workspace = true -derive_more.workspace = true -log.workspace = true - -paste = "1" -codespan = "0.12" -codespan-reporting = "0.12" diff --git a/grimoire-parser/src/lib.rs b/grimoire-parser/src/lib.rs deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/expr/mod.rs b/src/expr/mod.rs index 29a991e560a564b65f40f5b8d1096ff9b7619a70..fa12c7701d34e8d5ff0cf3c289b17f43b8642f83 100644 --- a/src/expr/mod.rs +++ b/src/expr/mod.rs @@ -1,2 +1,86 @@ #[derive(Debug)] -pub enum Expression {} +pub enum VarOrConstant { + Var(String), + Constant(Constant), +} + +#[derive(Debug)] +pub enum Constant { + Int(i32), + Flt(f32), + Bool(bool), + String(String), +} + +#[derive(Debug)] +pub enum Expression { + Binary(Box<Expression>, BinOp, Box<Expression>), + Unary(UnOp, Box<Expression>), + Leaf(VarOrConstant), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum UnOp { + Not, + Neg, +} + +impl UnOp { + pub fn as_str(&self) -> &'static str { + match self { + UnOp::Not => todo!(), + UnOp::Neg => todo!(), + } + } +} + +impl AsRef<str> for UnOp { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum BinOp { + Add, + Sub, + Mul, + Div, + Mod, + CompGE, + CompGT, + CompLT, + CompLE, + Or, + And, + Xor, + CompEQ, + CompNEQ, +} + +impl BinOp { + pub fn as_str(&self) -> &'static str { + match self { + BinOp::Add => todo!(), + BinOp::Sub => todo!(), + BinOp::Mul => todo!(), + BinOp::Div => todo!(), + BinOp::Mod => todo!(), + BinOp::CompGE => todo!(), + BinOp::CompGT => todo!(), + BinOp::CompLT => todo!(), + BinOp::CompLE => todo!(), + BinOp::Or => todo!(), + BinOp::And => todo!(), + BinOp::Xor => todo!(), + BinOp::CompEQ => todo!(), + BinOp::CompNEQ => todo!(), + } + } +} + +impl AsRef<str> for BinOp { + fn as_ref(&self) -> &str { + self.as_str() + } +} diff --git a/src/lib.rs b/src/lib.rs index 61bc0a7316e81b0237aae3e0d9c8b0e8bc04d9c3..56217569cdc5ef6d03c7964cbda13df30a5460c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,12 @@ -pub mod spell; +pub mod error; pub mod expr; +pub mod parser; +pub mod spell; pub mod state; -pub mod error; pub mod dummy; -use godot::prelude::*; +use godot::prelude::{ExtensionLibrary, gdextension}; struct GrimoireExtension; diff --git a/src/parser/error.rs b/src/parser/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..6c129bcce1f571c12b06517abf15206a8336acea --- /dev/null +++ b/src/parser/error.rs @@ -0,0 +1,45 @@ +use crate::parser::span::{Location, Span}; +use nom::{IResult, error::*}; +use std::num::{ParseFloatError, ParseIntError}; + +#[derive(Debug, thiserror::Error)] +pub enum ParserError { + #[error("{0:?}, {1}")] + ParseFloat(Location, ParseFloatError), + + #[error("{0:?}, {1}")] + ParseInt(Location, ParseIntError), + + #[error("{0:?}, {1:?}")] + Nom(Location, ErrorKind), +} + +pub type ParserResult<'a, T> = IResult<Span<'a>, T, ParserError>; + +impl<I> ContextError<I> for ParserError { + fn add_context(_: I, _ctx: &'static str, other: Self) -> Self { + other + } +} + +impl ParseError<Span<'_>> for ParserError { + fn from_error_kind(input: Span<'_>, kind: ErrorKind) -> Self { + Self::Nom(input.get_location(), kind) + } + + fn append(_: Span<'_>, _: ErrorKind, other: Self) -> Self { + other + } +} + +impl nom::error::FromExternalError<Span<'_>, ParseFloatError> for ParserError { + fn from_external_error(input: Span<'_>, _: ErrorKind, e: ParseFloatError) -> Self { + Self::ParseFloat(input.get_location(), e) + } +} + +impl nom::error::FromExternalError<Span<'_>, ParseIntError> for ParserError { + fn from_external_error(input: Span<'_>, _: ErrorKind, e: ParseIntError) -> Self { + Self::ParseInt(input.get_location(), e) + } +} diff --git a/src/parser/expr.rs b/src/parser/expr.rs new file mode 100644 index 0000000000000000000000000000000000000000..2f0b272801955f26e8c3674de085f5adfc94f2eb --- /dev/null +++ b/src/parser/expr.rs @@ -0,0 +1,99 @@ +use crate::{ + expr::{BinOp, Expression, UnOp}, + parser::*, +}; + +use nom::{ + Parser, branch::alt, bytes::complete::tag, character::complete::multispace0, combinator::map, + multi::many0, sequence::preceded, +}; + +fn leaf(s: Span) -> ParserResult<Expression> { + alt(( + // 1 + unop(UnOp::Not, expression), + unop(UnOp::Neg, expression), + // 2 + utils::parse_paren(expression), + )) + .parse(s) +} + +fn unop<'a>( + op: UnOp, + next: impl Parser<Span<'a>, Output = Expression, Error = ParserError>, +) -> impl Parser<Span<'a>, Output = Expression, Error = ParserError> { + map((multispace0, tag(op.as_str()), next), move |(.., expr)| { + Expression::Unary(op, Box::new(expr)) + }) +} + +fn binop<'a>( + op: BinOp, + next: impl Parser<Span<'a>, Output = Expression, Error = ParserError>, +) -> impl Parser<Span<'a>, Output = (BinOp, Expression), Error = ParserError> { + preceded(multispace0, (map(tag(op.as_str()), move |_| op), next)) +} + +fn fold_exprs(initial: Expression, remainder: Vec<(BinOp, Expression)>) -> Expression { + remainder.into_iter().fold(initial, |acc, (op, expr)| { + Expression::Binary(Box::new(acc), op, Box::new(expr)) + }) +} + +fn terms(s: Span) -> ParserResult<Expression> { + let (s, initial) = leaf(s)?; + let (s, remainder): (Span, Vec<(BinOp, Expression)>) = many0(alt(( + binop(BinOp::Mul, leaf), + binop(BinOp::Div, leaf), + binop(BinOp::Mod, leaf), + ))) + .parse(s)?; + Ok((s, fold_exprs(initial, remainder))) +} + +fn sums(s: Span) -> ParserResult<Expression> { + let (s, initial) = terms(s)?; + let (s, remainder) = + many0(alt((binop(BinOp::Add, terms), binop(BinOp::Sub, terms)))).parse(s)?; + Ok((s, fold_exprs(initial, remainder))) +} + +fn logic_terms(s: Span) -> ParserResult<Expression> { + let (s, initial) = sums(s)?; + let (s, remainder) = many0(binop(BinOp::And, sums)).parse(s)?; + Ok((s, fold_exprs(initial, remainder))) +} + +fn logic_sums(s: Span) -> ParserResult<Expression> { + let (s, initial) = logic_terms(s)?; + let (s, remainder) = many0(alt(( + binop(BinOp::Xor, logic_terms), + binop(BinOp::Or, logic_terms), + ))) + .parse(s)?; + Ok((s, fold_exprs(initial, remainder))) +} + +fn logic_comp(s: Span) -> ParserResult<Expression> { + let (s, initial) = logic_sums(s)?; + let (s, remainder) = many0(alt(( + binop(BinOp::CompLE, logic_sums), + binop(BinOp::CompGE, logic_sums), + binop(BinOp::CompLT, logic_sums), + binop(BinOp::CompGT, logic_sums), + ))) + .parse(s)?; + Ok((s, fold_exprs(initial, remainder))) +} + +#[allow(dead_code)] +pub(crate) fn expression(s: Span) -> ParserResult<Expression> { + let (s, initial) = logic_comp(s)?; + let (s, remainder) = many0(alt(( + binop(BinOp::CompEQ, logic_comp), + binop(BinOp::CompNEQ, logic_comp), + ))) + .parse(s)?; + Ok((s, fold_exprs(initial, remainder))) +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..fe3d0641b423e6c3f2c06dfa18e7f941a33211af --- /dev/null +++ b/src/parser/mod.rs @@ -0,0 +1,7 @@ +mod error; +mod expr; +mod span; +pub mod utils; + +pub use error::*; +pub use span::*; diff --git a/src/parser/span.rs b/src/parser/span.rs new file mode 100644 index 0000000000000000000000000000000000000000..6a0deb3820b578ddcbc4512607406ad275be10cd --- /dev/null +++ b/src/parser/span.rs @@ -0,0 +1,142 @@ +use nom::{Compare, Input, Offset as _}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Location { + offset: usize, + line: u32, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Span<'a> { + /// The offset represents the position of the fragment relatively to + /// the input of the parser. It starts at offset 0. + offset: usize, + + /// The line number of the fragment relatively to the input of the + /// parser. It starts at line 1. + line: u32, + + /// The fragment that is spanned. + /// The fragment represents a part of the input of the parser. + fragment: &'a str, +} + +impl<'a> core::ops::Deref for Span<'a> { + type Target = &'a str; + fn deref(&self) -> &Self::Target { + &self.fragment + } +} + +impl<'a> Span<'a> { + pub fn new(fragment: &'a str) -> Span<'a> { + Self { + offset: 0, + line: 1, + fragment, + } + } + + pub fn get_location(&self) -> Location { + todo!() + } + + /// The offset represents the position of the fragment relatively to + /// the input of the parser. It starts at offset 0. + pub fn location_offset(&self) -> usize { + self.offset + } + + /// The line number of the fragment relatively to the input of the + /// parser. It starts at line 1. + pub fn location_line(&self) -> u32 { + self.line + } + + /// The fragment that is spanned. + /// The fragment represents a part of the input of the parser. + pub fn fragment(&self) -> &str { + &self.fragment + } + + pub fn into_fragment(self) -> &'a str { + self.fragment + } + + fn slice_by(&self, next_fragment: &'a str) -> Self { + let consumed_len = self.fragment.offset(&next_fragment); + if consumed_len == 0 { + return Self { + line: self.line, + offset: self.offset, + fragment: next_fragment, + }; + } + + let consumed = self.fragment.take(consumed_len); + + let next_offset = self.offset + consumed_len; + + let consumed_as_bytes = consumed.as_bytes(); + let iter = memchr::Memchr::new(b'\n', consumed_as_bytes); + let number_of_lines = iter.count() as u32; + let next_line = self.line + number_of_lines; + + Self { + line: next_line, + offset: next_offset, + fragment: next_fragment, + } + } +} + +impl<'a> Input for Span<'a> { + type Item = <&'a str as Input>::Item; + type Iter = <&'a str as Input>::Iter; + type IterIndices = <&'a str as Input>::IterIndices; + + fn input_len(&self) -> usize { + self.fragment.input_len() + } + + fn take(&self, index: usize) -> Self { + self.slice_by(self.fragment.take(index)) + } + + fn take_from(&self, index: usize) -> Self { + self.slice_by(self.fragment.take_from(index)) + } + + fn take_split(&self, index: usize) -> (Self, Self) { + (self.take_from(index), self.take(index)) + } + + fn position<P>(&self, predicate: P) -> Option<usize> + where + P: Fn(Self::Item) -> bool, + { + self.fragment.position(predicate) + } + + fn iter_elements(&self) -> Self::Iter { + self.fragment.iter_elements() + } + + fn iter_indices(&self) -> Self::IterIndices { + self.fragment.iter_indices() + } + + fn slice_index(&self, count: usize) -> Result<usize, nom::Needed> { + self.fragment.slice_index(count) + } +} + +impl Compare<&str> for Span<'_> { + fn compare(&self, t: &str) -> nom::CompareResult { + todo!() + } + + fn compare_no_case(&self, t: &str) -> nom::CompareResult { + todo!() + } +} diff --git a/src/parser/utils.rs b/src/parser/utils.rs new file mode 100644 index 0000000000000000000000000000000000000000..ca8516ddc4b9d7192e1738eb4f9050db8121c3aa --- /dev/null +++ b/src/parser/utils.rs @@ -0,0 +1,13 @@ +use crate::parser::{error::*, span::*}; +use nom::{ + Parser, + bytes::complete::tag, + character::complete::multispace0, + sequence::{delimited, preceded}, +}; + +pub fn parse_paren<'a, T>( + inner: impl Parser<Span<'a>, Output = T, Error = ParserError>, +) -> impl Parser<Span<'a>, Output = T, Error = ParserError> { + preceded(multispace0, delimited(tag("("), inner, tag(")"))) +}