mirror of
https://github.com/nushell/nushell.git
synced 2025-08-11 08:44:39 +02:00
Start rebuilding lite parser using nom
This commit is contained in:
6
src/parser/parse2.rs
Normal file
6
src/parser/parse2.rs
Normal file
@ -0,0 +1,6 @@
|
||||
crate mod operator;
|
||||
crate mod parser;
|
||||
crate mod span;
|
||||
crate mod token_tree;
|
||||
crate mod tokens;
|
||||
crate mod util;
|
50
src/parser/parse2/operator.rs
Normal file
50
src/parser/parse2/operator.rs
Normal file
@ -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 Operator {
|
||||
Equal,
|
||||
NotEqual,
|
||||
LessThan,
|
||||
GreaterThan,
|
||||
LessThanOrEqual,
|
||||
GreaterThanOrEqual,
|
||||
}
|
||||
|
||||
impl Operator {
|
||||
pub fn print(&self) -> String {
|
||||
self.as_str().to_string()
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
match *self {
|
||||
Operator::Equal => "==",
|
||||
Operator::NotEqual => "!=",
|
||||
Operator::LessThan => "<",
|
||||
Operator::GreaterThan => ">",
|
||||
Operator::LessThanOrEqual => "<=",
|
||||
Operator::GreaterThanOrEqual => ">=",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Operator {
|
||||
fn from(input: &str) -> Operator {
|
||||
Operator::from_str(input).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Operator {
|
||||
type Err = ();
|
||||
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
|
||||
match input {
|
||||
"==" => Ok(Operator::Equal),
|
||||
"!=" => Ok(Operator::NotEqual),
|
||||
"<" => Ok(Operator::LessThan),
|
||||
">" => Ok(Operator::GreaterThan),
|
||||
"<=" => Ok(Operator::LessThanOrEqual),
|
||||
">=" => Ok(Operator::GreaterThanOrEqual),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
146
src/parser/parse2/parser.rs
Normal file
146
src/parser/parse2/parser.rs
Normal file
@ -0,0 +1,146 @@
|
||||
use crate::parser::parse2::{operator::*, span::*, tokens::*};
|
||||
use nom::types::CompleteStr;
|
||||
use nom::*;
|
||||
use nom_locate::{position, LocatedSpan};
|
||||
use std::str::FromStr;
|
||||
|
||||
type NomSpan<'a> = LocatedSpan<CompleteStr<'a>>;
|
||||
|
||||
macro_rules! operator {
|
||||
($name:tt : $token:tt ) => {
|
||||
named!($name( NomSpan ) -> Token,
|
||||
do_parse!(
|
||||
l: position!()
|
||||
>> t: tag!(stringify!($token))
|
||||
>> r: position!()
|
||||
>> (Spanned::from_nom(RawToken::Operator(Operator::from_str(t.fragment.0).unwrap()), l, r))
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
operator! { gt: > }
|
||||
operator! { lt: < }
|
||||
operator! { gte: >= }
|
||||
operator! { lte: <= }
|
||||
operator! { eq: == }
|
||||
operator! { neq: != }
|
||||
|
||||
named!(integer( NomSpan ) -> Token,
|
||||
do_parse!(
|
||||
l: position!()
|
||||
>> neg: opt!(tag!("-"))
|
||||
>> num: digit1
|
||||
>> r: position!()
|
||||
>> (Spanned::from_nom(RawToken::Integer(int(num.fragment.0, neg)), l, r))
|
||||
)
|
||||
);
|
||||
|
||||
named!(operator( NomSpan ) -> Token,
|
||||
alt!(
|
||||
gte | lte | neq | gt | lt | eq
|
||||
)
|
||||
);
|
||||
|
||||
named!(dq_string( NomSpan ) -> Token,
|
||||
do_parse!(
|
||||
l: position!()
|
||||
>> char!('"')
|
||||
>> l1: position!()
|
||||
>> many0!(none_of!("\""))
|
||||
>> r1: position!()
|
||||
>> char!('"')
|
||||
>> r: position!()
|
||||
>> (Spanned::from_nom(RawToken::String(Span::from((l1, r1))), l, r))
|
||||
)
|
||||
);
|
||||
|
||||
named!(sq_string( NomSpan ) -> Token,
|
||||
do_parse!(
|
||||
l: position!()
|
||||
>> char!('\'')
|
||||
>> l1: position!()
|
||||
>> many0!(none_of!("'"))
|
||||
>> r1: position!()
|
||||
>> char!('\'')
|
||||
>> r: position!()
|
||||
>> (Spanned::from_nom(RawToken::String(Span::from((l1, r1))), l, r))
|
||||
)
|
||||
);
|
||||
|
||||
fn int<T>(frag: &str, neg: Option<T>) -> i64 {
|
||||
let int = FromStr::from_str(frag).unwrap();
|
||||
|
||||
match neg {
|
||||
None => int,
|
||||
Some(_) => int * -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_integer() {
|
||||
assert_eq!(
|
||||
integer(NomSpan::new(CompleteStr("123"))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Integer(123), (0, 3))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
integer(NomSpan::new(CompleteStr("-123"))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Integer(-123), (0, 4))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operator() {
|
||||
assert_eq!(
|
||||
operator(NomSpan::new(CompleteStr(">"))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Operator(Operator::GreaterThan), (0, 1))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
operator(NomSpan::new(CompleteStr(">="))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Operator(Operator::GreaterThanOrEqual), (0, 2))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
operator(NomSpan::new(CompleteStr("<"))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Operator(Operator::LessThan), (0, 1))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
operator(NomSpan::new(CompleteStr("<="))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Operator(Operator::LessThanOrEqual), (0, 2))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
operator(NomSpan::new(CompleteStr("=="))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Operator(Operator::Equal), (0, 2))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
operator(NomSpan::new(CompleteStr("!="))).unwrap().1,
|
||||
Spanned::from_item(RawToken::Operator(Operator::NotEqual), (0, 2))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string() {
|
||||
assert_eq!(
|
||||
dq_string(NomSpan::new(CompleteStr(r#""hello world""#)))
|
||||
.unwrap()
|
||||
.1,
|
||||
Spanned::from_item(RawToken::String(Span::from((1, 12))), (0, 13))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq_string(NomSpan::new(CompleteStr(r#"'hello world'"#)))
|
||||
.unwrap()
|
||||
.1,
|
||||
Spanned::from_item(RawToken::String(Span::from((1, 12))), (0, 13))
|
||||
);
|
||||
}
|
||||
}
|
114
src/parser/parse2/span.rs
Normal file
114
src/parser/parse2/span.rs
Normal file
@ -0,0 +1,114 @@
|
||||
use derive_new::new;
|
||||
use std::ops::Range;
|
||||
|
||||
#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Spanned<T> {
|
||||
crate span: Span,
|
||||
crate item: T,
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for Spanned<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.item
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Spanned<T> {
|
||||
crate fn from_nom<U>(
|
||||
item: T,
|
||||
start: nom_locate::LocatedSpan<U>,
|
||||
end: nom_locate::LocatedSpan<U>,
|
||||
) -> Spanned<T> {
|
||||
let start = start.offset;
|
||||
let end = end.offset;
|
||||
|
||||
Spanned {
|
||||
span: Span::from((start, end)),
|
||||
item,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn from_item(item: T, span: impl Into<Span>) -> Spanned<T> {
|
||||
Spanned {
|
||||
span: span.into(),
|
||||
item,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn map<U>(self, input: impl FnOnce(T) -> U) -> Spanned<U> {
|
||||
let Spanned { span, item } = self;
|
||||
|
||||
let mapped = input(item);
|
||||
Spanned { span, item: mapped }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
||||
pub struct Span {
|
||||
crate start: usize,
|
||||
crate end: usize,
|
||||
// source: &'source str,
|
||||
}
|
||||
|
||||
impl<T> From<(nom_locate::LocatedSpan<T>, nom_locate::LocatedSpan<T>)> for Span {
|
||||
fn from(input: (nom_locate::LocatedSpan<T>, nom_locate::LocatedSpan<T>)) -> Span {
|
||||
Span {
|
||||
start: input.0.offset,
|
||||
end: input.1.offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(usize, usize)> for Span {
|
||||
fn from(input: (usize, usize)) -> Span {
|
||||
Span {
|
||||
start: input.0,
|
||||
end: input.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&std::ops::Range<usize>> for Span {
|
||||
fn from(input: &std::ops::Range<usize>) -> Span {
|
||||
Span {
|
||||
start: input.start,
|
||||
end: input.end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Span {
|
||||
fn new(range: &Range<usize>) -> Span {
|
||||
Span {
|
||||
start: range.start,
|
||||
end: range.end,
|
||||
// source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl language_reporting::ReportingSpan for Span {
|
||||
fn with_start(&self, start: usize) -> Self {
|
||||
Span {
|
||||
start,
|
||||
end: self.end,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_end(&self, end: usize) -> Self {
|
||||
Span {
|
||||
start: self.start,
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
||||
fn start(&self) -> usize {
|
||||
self.start
|
||||
}
|
||||
|
||||
fn end(&self) -> usize {
|
||||
self.end
|
||||
}
|
||||
}
|
6
src/parser/parse2/token_tree.rs
Normal file
6
src/parser/parse2/token_tree.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use crate::parser::parse2::{span::*, tokens::*};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum TokenNode {
|
||||
Token(Token),
|
||||
}
|
11
src/parser/parse2/tokens.rs
Normal file
11
src/parser/parse2/tokens.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::parser::parse2::operator::*;
|
||||
use crate::parser::parse2::span::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum RawToken {
|
||||
Integer(i64),
|
||||
Operator(Operator),
|
||||
String(Span),
|
||||
}
|
||||
|
||||
pub type Token = Spanned<RawToken>;
|
1
src/parser/parse2/util.rs
Normal file
1
src/parser/parse2/util.rs
Normal file
@ -0,0 +1 @@
|
||||
|
Reference in New Issue
Block a user