diff --git a/Cargo.lock b/Cargo.lock index 2ed37ff34..3d72a03bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,6 +643,19 @@ dependencies = [ "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "derive_more" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "difference" version = "2.0.0" @@ -799,6 +812,28 @@ dependencies = [ "array-macro 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "enum-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "enum-utils-from-str 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "enum-utils-from-str" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "enum_derive" version = "0.1.7" @@ -1551,8 +1586,10 @@ dependencies = [ "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cursive 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "dunce 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "enum_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures-sink-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1592,6 +1629,7 @@ dependencies = [ "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2442,6 +2480,15 @@ dependencies = [ "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_derive_internals" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_json" version = "1.0.39" @@ -3217,6 +3264,7 @@ dependencies = [ "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum derive_builder 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ca533e6abb78f9108585535ce2ae0b14c8b4504e138a9a28eaf8ba2b270c1d" "checksum derive_builder_core 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb484fe06ba1dc5b82f88aff700191dfc127e02b06b35e302c169706168e2528" +"checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" @@ -3237,6 +3285,8 @@ dependencies = [ "checksum enum-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccd9b2d5e0eb5c2ff851791e2af90ab4531b1168cfc239d1c0bf467e60ba3c89" "checksum enum-map-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "153f6e8a8b2868e2fedf921b165f30229edcccb74d6a9bb1ccf0480ef61cd07e" "checksum enum-map-internals 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38b0bacf3ea7aba18ce84032efc3f0fa29f5c814048b742ab3e64d07d83ac3e8" +"checksum enum-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23c5d9343285feb320b4f2b0d0ba9501c11e1a19052026852d772a6e96e8de5d" +"checksum enum-utils-from-str 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b5669381f76d7320e122abdd4a8307f986634f6d067fb69e31179422175801a" "checksum enum_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "406ac2a8c9eedf8af9ee1489bee9e50029278a6456c740f7454cf8a158abc816" "checksum enumset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac0a22e173f6570a7d69a2ab9e3fe79cf0dcdd0fdb162bfc932b97158f2b2a7" "checksum enumset_derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01d93b926a992a4a526c2a14e2faf734fdef5bf9d0a52ba69a2ca7d4494c284b" @@ -3410,6 +3460,7 @@ dependencies = [ "checksum serde-hjson 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4640cf3168e40c00c874ff1ad436c0f18c37edec101d5d897a4396f617abce29" "checksum serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" "checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" +"checksum serde_derive_internals 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a80c6c0b1ebbcea4ec2c7e9e2e9fa197a425d17f1afec8ba79fcd1352b18ffb" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" diff --git a/Cargo.toml b/Cargo.toml index 062824699..95d677566 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,9 @@ reqwest = "0.9" roxmltree = "0.6.0" pretty = "0.5.2" nom_locate = "0.3.1" +derive_more = "0.15.0" +enum-utils = "0.1.0" +unicode-xid = "0.1.0" [dependencies.pancurses] version = "0.16" diff --git a/src/parser/parse2.rs b/src/parser/parse2.rs index ab4ef485b..510c3e8aa 100644 --- a/src/parser/parse2.rs +++ b/src/parser/parse2.rs @@ -1,6 +1,8 @@ +crate mod flag; crate mod operator; crate mod parser; crate mod span; crate mod token_tree; crate mod tokens; +crate mod unit; crate mod util; diff --git a/src/parser/parse2/flag.rs b/src/parser/parse2/flag.rs new file mode 100644 index 000000000..0d255e451 --- /dev/null +++ b/src/parser/parse2/flag.rs @@ -0,0 +1,7 @@ +use serde_derive::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] +pub enum Flag { + Shorthand, + Longhand, +} diff --git a/src/parser/parse2/parser.rs b/src/parser/parse2/parser.rs index 36c2fea08..74bbc6639 100644 --- a/src/parser/parse2/parser.rs +++ b/src/parser/parse2/parser.rs @@ -1,4 +1,7 @@ -use crate::parser::parse2::{operator::*, span::*, tokens::*}; +#![allow(unused)] + +use crate::parser::parse2::{flag::*, operator::*, span::*, token_tree::*, tokens::*, unit::*}; +use nom; use nom::types::CompleteStr; use nom::*; use nom_locate::{position, LocatedSpan}; @@ -26,23 +29,30 @@ operator! { lte: <= } operator! { eq: == } operator! { neq: != } -named!(integer( NomSpan ) -> Token, +named!(pub raw_integer( NomSpan ) -> Spanned, do_parse!( l: position!() >> neg: opt!(tag!("-")) >> num: digit1 >> r: position!() - >> (Spanned::from_nom(RawToken::Integer(int(num.fragment.0, neg)), l, r)) + >> (Spanned::from_nom(int(num.fragment.0, neg), l, r)) ) ); -named!(operator( NomSpan ) -> Token, +named!(pub integer( NomSpan ) -> Token, + do_parse!( + int: raw_integer + >> (int.map(|i| RawToken::Integer(i))) + ) +); + +named!(pub operator( NomSpan ) -> Token, alt!( gte | lte | neq | gt | lt | eq ) ); -named!(dq_string( NomSpan ) -> Token, +named!(pub dq_string( NomSpan ) -> Token, do_parse!( l: position!() >> char!('"') @@ -55,7 +65,7 @@ named!(dq_string( NomSpan ) -> Token, ) ); -named!(sq_string( NomSpan ) -> Token, +named!(pub sq_string( NomSpan ) -> Token, do_parse!( l: position!() >> char!('\'') @@ -68,6 +78,114 @@ named!(sq_string( NomSpan ) -> Token, ) ); +named!(pub string( NomSpan ) -> Token, + alt!(sq_string | dq_string) +); + +named!(pub bare( NomSpan ) -> Token, + do_parse!( + l: position!() + >> take_while1!(is_start_bare_char) + >> take_while!(is_bare_char) + >> r: position!() + >> (Spanned::from_nom(RawToken::Bare, l, r)) + ) +); + +named!(pub var( NomSpan ) -> Token, + do_parse!( + l: position!() + >> tag!("$") + >> bare: identifier + >> r: position!() + >> (Spanned::from_nom(RawToken::Variable(bare.span), l, r)) + ) +); + +named!(pub identifier( NomSpan ) -> Spanned<()>, + do_parse!( + l: position!() + >> take_while1!(is_id_start) + >> take_while!(is_id_continue) + >> r: position!() + >> (Spanned::from_nom((), l, r)) + ) +); + +named!(pub flag( NomSpan ) -> Token, + do_parse!( + l: position!() + >> tag!("--") + >> bare: bare + >> r: position!() + >> (Spanned::from_nom(RawToken::Flag(Flag::Longhand, bare.span), l, r)) + ) +); + +named!(pub shorthand( NomSpan ) -> Token, + do_parse!( + l: position!() + >> tag!("-") + >> bare: bare + >> r: position!() + >> (Spanned::from_nom(RawToken::Flag(Flag::Shorthand, bare.span), l, r)) + ) +); + +named!(pub raw_unit( NomSpan ) -> Spanned, + do_parse!( + l: position!() + >> unit: alt!(tag!("B") | tag!("KB") | tag!("MB") | tag!("GB") | tag!("TB") | tag!("PB")) + >> r: position!() + >> (Spanned::from_nom(Unit::from(unit.fragment.0), l, r)) + ) +); + +named!(pub size( NomSpan ) -> Token, + do_parse!( + l: position!() + >> int: raw_integer + >> unit: raw_unit + >> r: position!() + >> (Spanned::from_nom(RawToken::Size(int.item, unit.item), l, r)) + ) +); + +// named!(pub unit_num( NomSpan ) -> Token, +// do_parse!( +// l: position!() +// >> +// ) +// ) + +named!(pub leaf( NomSpan ) -> Token, + alt!(size | integer | string | operator | flag | shorthand | bare) +); + +named!(pub leaf_node( NomSpan ) -> TokenNode, + do_parse!( + leaf: leaf + >> (TokenNode::Token(leaf)) + ) +); + +named!(pub delimited_paren( NomSpan ) -> TokenNode, + do_parse!( + l: position!() + >> items: delimited!( + char!('('), + delimited!(space0, separated_list!(space1, node), space0), + char!(')') + ) + >> r: position!() + >> (TokenNode::Delimited(Spanned::from_nom(DelimitedNode::new(Delimiter::Paren, items), l, r))) + ) +); + +named!(pub node( NomSpan ) -> TokenNode, + alt!(leaf_node | delimited_paren) +); + fn int(frag: &str, neg: Option) -> i64 { let int = FromStr::from_str(frag).unwrap(); @@ -77,70 +195,284 @@ fn int(frag: &str, neg: Option) -> i64 { } } +fn is_start_bare_char(c: char) -> bool { + match c { + _ if c.is_alphabetic() => true, + '.' => true, + '\\' => true, + '/' => true, + '_' => true, + '-' => true, + _ => false, + } +} + +fn is_bare_char(c: char) -> bool { + match c { + _ if c.is_alphanumeric() => true, + ':' => true, + '.' => true, + '\\' => true, + '/' => true, + '_' => true, + '-' => true, + _ => false, + } +} + +fn is_id_start(c: char) -> bool { + unicode_xid::UnicodeXID::is_xid_start(c) +} + +fn is_id_continue(c: char) -> bool { + unicode_xid::UnicodeXID::is_xid_continue(c) + || match c { + '-' => true, + '?' => true, + '!' => true, + _ => false, + } +} + #[cfg(test)] mod tests { use super::*; + use pretty_assertions::assert_eq; + + macro_rules! assert_leaf { + (parsers [ $($name:tt)* ] $input:tt -> $left:tt .. $right:tt { $kind:tt $parens:tt } ) => { + $( + assert_eq!( + apply($name, $input), + token(RawToken::$kind $parens, $left, $right) + ); + )* + + assert_eq!( + apply(leaf, $input), + token(RawToken::$kind $parens, $left, $right) + ); + + assert_eq!( + apply(leaf_node, $input), + TokenNode::Token(token(RawToken::$kind $parens, $left, $right)) + ); + + assert_eq!( + apply(node, $input), + TokenNode::Token(token(RawToken::$kind $parens, $left, $right)) + ); + }; + + (parsers [ $($name:tt)* ] $input:tt -> $left:tt .. $right:tt { $kind:tt } ) => { + $( + assert_eq!( + apply($name, $input), + token(RawToken::$kind, $left, $right) + ); + )* + } + } #[test] fn test_integer() { - assert_eq!( - integer(NomSpan::new(CompleteStr("123"))).unwrap().1, - Spanned::from_item(RawToken::Integer(123), (0, 3)) - ); + assert_leaf! { + parsers [ integer ] + "123" -> 0..3 { Integer(123) } + } - assert_eq!( - integer(NomSpan::new(CompleteStr("-123"))).unwrap().1, - Spanned::from_item(RawToken::Integer(-123), (0, 4)) - ); + assert_leaf! { + parsers [ integer ] + "-123" -> 0..4 { Integer(-123) } + } + } + + #[test] + fn test_size() { + assert_leaf! { + parsers [ size ] + "123MB" -> 0..5 { Size(123, Unit::MB) } + } + + assert_leaf! { + parsers [ size ] + "10GB" -> 0..4 { Size(10, Unit::GB) } + } } #[test] fn test_operator() { - assert_eq!( - operator(NomSpan::new(CompleteStr(">"))).unwrap().1, - Spanned::from_item(RawToken::Operator(Operator::GreaterThan), (0, 1)) - ); + assert_leaf! { + parsers [ operator ] + ">" -> 0..1 { Operator(Operator::GreaterThan) } + } - assert_eq!( - operator(NomSpan::new(CompleteStr(">="))).unwrap().1, - Spanned::from_item(RawToken::Operator(Operator::GreaterThanOrEqual), (0, 2)) - ); + assert_leaf! { + parsers [ operator ] + ">=" -> 0..2 { Operator(Operator::GreaterThanOrEqual) } + } - assert_eq!( - operator(NomSpan::new(CompleteStr("<"))).unwrap().1, - Spanned::from_item(RawToken::Operator(Operator::LessThan), (0, 1)) - ); + assert_leaf! { + parsers [ operator ] + "<" -> 0..1 { Operator(Operator::LessThan) } + } - assert_eq!( - operator(NomSpan::new(CompleteStr("<="))).unwrap().1, - Spanned::from_item(RawToken::Operator(Operator::LessThanOrEqual), (0, 2)) - ); + assert_leaf! { + parsers [ operator ] + "<=" -> 0..2 { Operator(Operator::LessThanOrEqual) } + } - assert_eq!( - operator(NomSpan::new(CompleteStr("=="))).unwrap().1, - Spanned::from_item(RawToken::Operator(Operator::Equal), (0, 2)) - ); + assert_leaf! { + parsers [ operator ] + "==" -> 0..2 { Operator(Operator::Equal) } + } - assert_eq!( - operator(NomSpan::new(CompleteStr("!="))).unwrap().1, - Spanned::from_item(RawToken::Operator(Operator::NotEqual), (0, 2)) - ); + assert_leaf! { + parsers [ operator ] + "!=" -> 0..2 { Operator(Operator::NotEqual) } + } } #[test] fn test_string() { + assert_leaf! { + parsers [ string dq_string ] + r#""hello world""# -> 0..13 { String(span(1, 12)) } + } + + assert_leaf! { + parsers [ string sq_string ] + r"'hello world'" -> 0..13 { String(span(1, 12)) } + } + } + + #[test] + fn test_bare() { + assert_leaf! { + parsers [ bare ] + "hello" -> 0..5 { Bare } + } + + assert_leaf! { + parsers [ bare ] + "chrome.exe" -> 0..10 { Bare } + } + + assert_leaf! { + parsers [ bare ] + r"C:\windows\system.dll" -> 0..21 { Bare } + } + + assert_leaf! { + parsers [ bare ] + r"C:\Code\-testing\my_tests.js" -> 0..28 { Bare } + } + } + + #[test] + fn test_flag() { + assert_leaf! { + parsers [ flag ] + "--hello" -> 0..7 { Flag(Flag::Longhand, span(2, 7)) } + } + + assert_leaf! { + parsers [ flag ] + "--hello-world" -> 0..13 { Flag(Flag::Longhand, span(2, 13)) } + } + } + + #[test] + fn test_shorthand() { + assert_leaf! { + parsers [ shorthand ] + "-alt" -> 0..4 { Flag(Flag::Shorthand, span(1, 4)) } + } + } + + fn test_variable() { + assert_leaf! { + parsers [ var ] + "$it" -> 0..3 { Variable(span(1, 3)) } + } + + assert_leaf! { + parsers [ var ] + "$name" -> 0..5 { Variable(span(1, 5)) } + } + } + + #[test] + fn test_delimited() { assert_eq!( - dq_string(NomSpan::new(CompleteStr(r#""hello world""#))) - .unwrap() - .1, - Spanned::from_item(RawToken::String(Span::from((1, 12))), (0, 13)) + apply(node, "(abc)"), + delimited( + Delimiter::Paren, + vec![TokenNode::Token(token(RawToken::Bare, 1, 4))], + 0, + 5 + ) ); assert_eq!( - sq_string(NomSpan::new(CompleteStr(r#"'hello world'"#))) - .unwrap() - .1, - Spanned::from_item(RawToken::String(Span::from((1, 12))), (0, 13)) + apply(node, "( abc )"), + delimited( + Delimiter::Paren, + vec![TokenNode::Token(token(RawToken::Bare, 3, 6))], + 0, + 9 + ) + ); + + assert_eq!( + apply(node, "( abc def )"), + delimited( + Delimiter::Paren, + vec![ + TokenNode::Token(token(RawToken::Bare, 3, 6)), + TokenNode::Token(token(RawToken::Bare, 7, 10)), + ], + 0, + 12 + ) + ); + + assert_eq!( + apply(node, "( abc def 123 456GB )"), + delimited( + Delimiter::Paren, + vec![ + TokenNode::Token(token(RawToken::Bare, 3, 6)), + TokenNode::Token(token(RawToken::Bare, 7, 10)), + TokenNode::Token(token(RawToken::Integer(123), 11, 14)), + TokenNode::Token(token(RawToken::Size(456, Unit::GB), 15, 20)), + ], + 0, + 22 + ) ); } + + fn apply(f: impl Fn(NomSpan) -> Result<(NomSpan, T), nom::Err>, string: &str) -> T { + f(NomSpan::new(CompleteStr(string))).unwrap().1 + } + + fn span(left: usize, right: usize) -> Span { + Span::from((left, right)) + } + + fn delimited( + delimiter: Delimiter, + children: Vec, + left: usize, + right: usize, + ) -> TokenNode { + let node = DelimitedNode::new(delimiter, children); + let spanned = Spanned::from_item(node, (left, right)); + TokenNode::Delimited(spanned) + } + + fn token(token: RawToken, left: usize, right: usize) -> Token { + Spanned::from_item(token, (left, right)) + } } diff --git a/src/parser/parse2/token_tree.rs b/src/parser/parse2/token_tree.rs index 3f9f45ded..ecb409428 100644 --- a/src/parser/parse2/token_tree.rs +++ b/src/parser/parse2/token_tree.rs @@ -1,6 +1,22 @@ use crate::parser::parse2::{span::*, tokens::*}; +use derive_new::new; +use enum_utils::FromStr; -#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] pub enum TokenNode { Token(Token), + Delimited(Spanned), +} + +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, new)] +pub struct DelimitedNode { + delimiter: Delimiter, + children: Vec, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, FromStr)] +pub enum Delimiter { + Paren, + Brace, + Square, } diff --git a/src/parser/parse2/tokens.rs b/src/parser/parse2/tokens.rs index b12c361b9..eece2cd07 100644 --- a/src/parser/parse2/tokens.rs +++ b/src/parser/parse2/tokens.rs @@ -1,11 +1,17 @@ +use crate::parser::parse2::flag::*; use crate::parser::parse2::operator::*; use crate::parser::parse2::span::*; +use crate::parser::parse2::unit::*; #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum RawToken { Integer(i64), + Size(i64, Unit), Operator(Operator), String(Span), + Variable(Span), + Bare, + Flag(Flag, Span), } pub type Token = Spanned; diff --git a/src/parser/parse2/unit.rs b/src/parser/parse2/unit.rs new file mode 100644 index 000000000..883f4c507 --- /dev/null +++ b/src/parser/parse2/unit.rs @@ -0,0 +1,50 @@ +use serde_derive::{Deserialize, Serialize}; +use std::str::FromStr; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] +pub enum Unit { + B, + KB, + MB, + GB, + TB, + PB, +} + +impl Unit { + pub fn print(&self) -> String { + self.as_str().to_string() + } + + pub fn as_str(&self) -> &str { + match *self { + Unit::B => "B", + Unit::KB => "KB", + Unit::MB => "MB", + Unit::GB => "GB", + Unit::TB => "TB", + Unit::PB => "PB", + } + } +} + +impl From<&str> for Unit { + fn from(input: &str) -> Unit { + Unit::from_str(input).unwrap() + } +} + +impl FromStr for Unit { + type Err = (); + fn from_str(input: &str) -> Result::Err> { + match input { + "B" => Ok(Unit::B), + "KB" => Ok(Unit::KB), + "MB" => Ok(Unit::MB), + "GB" => Ok(Unit::GB), + "TB" => Ok(Unit::TB), + "PB" => Ok(Unit::PB), + _ => Err(()), + } + } +}