Start rebuilding lite parser using nom

This commit is contained in:
Yehuda Katz
2019-06-10 22:53:04 -07:00
parent a3c3c4d776
commit 4291e31dc7
11 changed files with 352 additions and 45 deletions

6
src/parser/parse2.rs Normal file
View File

@ -0,0 +1,6 @@
crate mod operator;
crate mod parser;
crate mod span;
crate mod token_tree;
crate mod tokens;
crate mod util;

View 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
View 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
View 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
}
}

View File

@ -0,0 +1,6 @@
use crate::parser::parse2::{span::*, tokens::*};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub enum TokenNode {
Token(Token),
}

View 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>;

View File

@ -0,0 +1 @@