Implement or, fix scanner bugz

This commit is contained in:
vaidehi joshi 2018-09-12 16:29:06 -07:00 committed by Godfrey Chan
parent 393abea3cb
commit c1c614e6ee
5 changed files with 2395 additions and 1121 deletions

View File

@ -4,4 +4,12 @@ use scanner;
pub enum Expression {
Token(scanner::Token),
Group(Vec<Expression>),
Or(Vec<Expression>),
}
pub fn concat<T: Clone>(lhs: T, rhs: &[T]) -> Vec<T> {
let mut v = Vec::with_capacity(1 + rhs.len());
v.push(lhs);
v.extend_from_slice(rhs);
v
}

View File

@ -4,30 +4,31 @@ use nodes::*;
grammar;
pub Expressions: Vec<Expression> = {
<e: Expression> <rest: Expressions> => {
let mut v = Vec::with_capacity(1 + rest.len());
v.push(e);
v.extend_from_slice(&rest);
v
},
<e: Expression> <rest: Expressions> => { concat(e, &rest) },
<Expression> => { vec![<>] },
<Or> => { vec![Expression::Or(<>)] }
}
pub Expression: Expression = {
<Terminal> => { Expression::Token(<>) },
<Group> => { Expression::Group(<>) },
<Star> => { Expression::Token(<>) }
<STAR> => { Expression::Token(<>) }
}
pub Group: Vec<Expression> = {
LParen <Expressions> RParen
LPAREN <Expressions> RPAREN
}
pub Or: Vec<Expression> = {
<lhs: Expression> OR <rhs: Expression> => { vec![lhs, rhs] },
<lhs: Expression> OR <rhs: Or> => { concat(lhs, &rhs) },
}
pub Terminal: Token = {
<Symbol>,
<Literal>,
<Slash>,
<Dot>
<SYMBOL>,
<LITERAL>,
<SLASH>,
<DOT>
}
extern {
@ -35,13 +36,13 @@ extern {
type Error = NotPossible;
enum Token {
Slash => Token::Slash,
LParen => Token::LParen,
RParen => Token::RParen,
Dot => Token::Dot,
Or => Token::Or,
Star => Token::Star(_),
Symbol => Token::Symbol(_),
Literal => Token::Literal(_),
SLASH => Token::Slash,
LPAREN => Token::LParen,
RPAREN => Token::RParen,
DOT => Token::Dot,
OR => Token::Or,
STAR => Token::Star(_),
SYMBOL => Token::Symbol(_),
LITERAL => Token::Literal(_),
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
use owned_chars::{OwnedCharIndices, OwnedCharsExt};
use std;
use owned_chars::{OwnedCharsExt, OwnedCharIndices};
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Token {
@ -44,7 +44,7 @@ impl Scanner {
fn consume_symbol_or_star(&mut self) -> Option<(usize, String, usize)> {
if self.peek_char().is_none() {
return None
return None;
} else {
let mut ident = String::new();
let start = self.peek_char().unwrap().0;
@ -59,12 +59,14 @@ impl Scanner {
let is_boundary = match self.peek_char() {
Some((_, c)) => match c {
'_' => false,
c => !c.is_ascii_alphanumeric(),
c => !c.is_ascii_alphanumeric(),
},
None => true
None => true,
};
if is_boundary { break; }
if is_boundary {
break;
}
}
Some((start, ident, end))
@ -73,7 +75,7 @@ impl Scanner {
fn consume_literal(&mut self) -> Option<(usize, String, usize)> {
if self.peek_char().is_none() {
return None
return None;
} else {
let mut ident = String::new();
let start = self.peek_char().unwrap().0;
@ -92,13 +94,15 @@ impl Scanner {
let is_boundary = match self.peek_char() {
Some((_, c)) => match c {
'/' => true,
_ => false,
'/' | '(' | ')' | '.' | '|' => true,
_ => false,
},
None => true
None => true,
};
if is_boundary { break; }
if is_boundary {
break;
}
}
Some((start, ident, end))
@ -119,35 +123,35 @@ impl Iterator for Scanner {
'/' => {
self.consume_char();
Ok((loc, Slash, loc))
},
}
'(' => {
self.consume_char();
Ok((loc, LParen, loc))
},
}
')' => {
self.consume_char();
Ok((loc, RParen, loc))
},
}
'.' => {
self.consume_char();
Ok((loc, Dot, loc))
},
}
'|' => {
self.consume_char();
Ok((loc, Or, loc))
},
}
'*' => {
let (start, ident, end) = self.consume_symbol_or_star().unwrap();
Ok((start, Star(ident), end))
},
}
':' => {
let (start, ident, end) = self.consume_symbol_or_star().unwrap();
Ok((start, Symbol(ident), end))
},
_ => {
}
_ => {
let (start, ident, end) = self.consume_literal().unwrap();
Ok((start, Literal(ident), end))
},
}
})
}
}

View File

@ -1,8 +1,9 @@
extern crate lalrpop_util;
use parser::*;
use scanner::{self, Scanner, Token::*};
use nodes::Expression::{self, *};
use parser::ExpressionsParser;
use scanner::Token::{Dot, Literal, Slash, Star, Symbol};
use scanner::{self, Scanner};
type ParseError = lalrpop_util::ParseError<usize, scanner::Token, scanner::NotPossible>;
type ParseResult = Result<Vec<Expression>, ParseError>;
@ -15,259 +16,385 @@ fn parse(s: &'static str) -> ParseResult {
#[test]
fn test_slash() {
assert_eq!(parse("/").unwrap(), vec![
Token(Slash)
]);
assert_eq!(parse("/").unwrap(), vec![Token(Slash)]);
}
#[test]
fn test_segment() {
assert_eq!(parse("foo").unwrap(), vec![
Token(Literal("foo".to_string()))
]);
assert_eq!(
parse("foo").unwrap(),
vec![Token(Literal("foo".to_string()))]
);
assert_eq!(parse("/foo").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string()))
]);
assert_eq!(
parse("/foo").unwrap(),
vec![Token(Slash), Token(Literal("foo".to_string()))]
);
assert_eq!(parse("/foo/").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash)
]);
assert_eq!(
parse("/foo/").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
]
);
}
#[test]
fn test_segments() {
assert_eq!(parse("/foo/bar/baz").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string())),
Token(Slash),
Token(Literal("baz".to_string()))
]);
assert_eq!(
parse("/foo/bar/baz").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string())),
Token(Slash),
Token(Literal("baz".to_string())),
]
);
assert_eq!(parse("/foo/bar/baz/").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string())),
Token(Slash),
Token(Literal("baz".to_string())),
Token(Slash)
]);
}
#[test]
fn test_symbol() {
assert_eq!(parse(":foo").unwrap(), vec![
Token(Symbol(":foo".to_string()))
]);
assert_eq!(parse("/:foo").unwrap(), vec![
Token(Slash),
Token(Symbol(":foo".to_string()))
]);
assert_eq!(parse("/:foo/").unwrap(), vec![
Token(Slash),
Token(Symbol(":foo".to_string())),
Token(Slash)
]);
assert_eq!(
parse("/foo/bar/baz/").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string())),
Token(Slash),
Token(Literal("baz".to_string())),
Token(Slash),
]
);
}
#[test]
fn test_segment_symbol() {
assert_eq!(parse("/foo/:id").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Symbol(":id".to_string()))
]);
assert_eq!(
parse("/foo/:id").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Symbol(":id".to_string())),
]
);
}
#[test]
fn test_symbol() {
assert_eq!(
parse(":foo").unwrap(),
vec![Token(Symbol(":foo".to_string()))]
);
assert_eq!(
parse("/:foo").unwrap(),
vec![Token(Slash), Token(Symbol(":foo".to_string()))]
);
assert_eq!(
parse("/:foo/").unwrap(),
vec![
Token(Slash),
Token(Symbol(":foo".to_string())),
Token(Slash),
]
);
}
#[test]
fn test_group() {
assert_eq!(parse("(/:foo)").unwrap(), vec![
Group(vec![
Token(Slash),
Token(Symbol(":foo".to_string()))
])
]);
assert_eq!(
parse("(/:foo)").unwrap(),
vec![Group(vec![Token(Slash), Token(Symbol(":foo".to_string()))])]
);
}
#[test]
fn test_groups() {
assert_eq!(parse("(/:foo)(/:bar)").unwrap(), vec![
Group(vec![
Token(Slash),
Token(Symbol(":foo".to_string()))
]),
Group(vec![
Token(Slash),
Token(Symbol(":bar".to_string()))
])
]);
assert_eq!(
parse("(/:foo)(/:bar)").unwrap(),
vec![
Group(vec![Token(Slash), Token(Symbol(":foo".to_string()))]),
Group(vec![Token(Slash), Token(Symbol(":bar".to_string()))]),
]
);
}
#[test]
fn test_nested_groups() {
assert_eq!(parse("(/:foo(/:bar))").unwrap(), vec![
Group(vec![
assert_eq!(
parse("(/:foo(/:bar))").unwrap(),
vec![Group(vec![
Token(Slash),
Token(Symbol(":foo".to_string())),
Group(vec![
Token(Slash),
Token(Symbol(":bar".to_string()))
])
])
]);
}
#[test]
fn parse_star() {
assert_eq!(parse("*foo").unwrap(), vec![
Token(Star("*foo".to_string()))
]);
assert_eq!(parse("/*foo").unwrap(), vec![
Token(Slash),
Token(Star("*foo".to_string()))
]);
assert_eq!(parse("/*foo/").unwrap(), vec![
Token(Slash),
Token(Star("*foo".to_string())),
Token(Slash)
]);
assert_eq!(parse("/foo/*bar").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Star("*bar".to_string()))
]);
assert_eq!(parse("/foo/*bar/").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Star("*bar".to_string())),
Token(Slash)
]);
assert_eq!(parse("/*foo/bar").unwrap(), vec![
Token(Slash),
Token(Star("*foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string()))
]);
assert_eq!(parse("/*foo/bar/").unwrap(), vec![
Token(Slash),
Token(Star("*foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string())),
Token(Slash)
]);
Group(vec![Token(Slash), Token(Symbol(":bar".to_string()))]),
])]
);
}
#[test]
fn test_dot_symbol() {
assert_eq!(parse(".:format").unwrap(), vec![
Token(Dot),
Token(Symbol(":format".to_string()))
]);
assert_eq!(
parse(".:format").unwrap(),
vec![Token(Dot), Token(Symbol(":format".to_string()))]
);
}
#[test]
fn test_dot_literal() {
assert_eq!(parse(".xml").unwrap(), vec![
Token(Dot),
Token(Literal("xml".to_string()))
]);
assert_eq!(
parse(".xml").unwrap(),
vec![Token(Dot), Token(Literal("xml".to_string()))]
);
}
#[test]
fn test_segment_dot() {
assert_eq!(parse("/foo.:bar").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Dot),
Token(Symbol(":bar".to_string()))
]);
assert_eq!(
parse("/foo.:bar").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Dot),
Token(Symbol(":bar".to_string())),
]
);
}
#[test]
fn test_segment_group_dot() {
assert_eq!(parse("/foo(.:bar)").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Group(vec![
Token(Dot),
Token(Symbol(":bar".to_string()))
])
]);
assert_eq!(
parse("/foo(.:bar)").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Group(vec![Token(Dot), Token(Symbol(":bar".to_string()))]),
]
);
}
#[test]
fn test_segment_group() {
assert_eq!(parse("/foo(/:action)").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Group(vec![
assert_eq!(
parse("/foo(/:action)").unwrap(),
vec![
Token(Slash),
Token(Symbol(":action".to_string()))
])
]);
Token(Literal("foo".to_string())),
Group(vec![Token(Slash), Token(Symbol(":action".to_string()))]),
]
);
}
#[test]
fn test_segment_groups() {
assert_eq!(parse("/foo(/:action)(/:bar)").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Group(vec![
assert_eq!(
parse("/foo(/:action)(/:bar)").unwrap(),
vec![
Token(Slash),
Token(Symbol(":action".to_string()))
]),
Group(vec![
Token(Slash),
Token(Symbol(":bar".to_string()))
])
]);
Token(Literal("foo".to_string())),
Group(vec![Token(Slash), Token(Symbol(":action".to_string()))]),
Group(vec![Token(Slash), Token(Symbol(":bar".to_string()))]),
]
);
}
#[test]
fn test_segment_nested_groups() {
assert_eq!(parse("/foo(/:action(/:bar))").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Group(vec![
assert_eq!(
parse("/foo(/:action(/:bar))").unwrap(),
vec![
Token(Slash),
Token(Symbol(":action".to_string())),
Token(Literal("foo".to_string())),
Group(vec![
Token(Slash),
Token(Symbol(":bar".to_string()))
])
])
]);
Token(Symbol(":action".to_string())),
Group(vec![Token(Slash), Token(Symbol(":bar".to_string()))]),
]),
]
);
}
#[test]
fn test_group_followed_by_path() {
assert_eq!(parse("/foo(/:action)/:bar").unwrap(), vec![
Token(Slash),
Token(Literal("foo".to_string())),
Group(vec![
assert_eq!(
parse("/foo(/:action)/:bar").unwrap(),
vec![
Token(Slash),
Token(Symbol(":action".to_string()))
]),
Token(Slash),
Token(Symbol(":bar".to_string()))
]);
Token(Literal("foo".to_string())),
Group(vec![Token(Slash), Token(Symbol(":action".to_string()))]),
Token(Slash),
Token(Symbol(":bar".to_string())),
]
);
}
#[test]
fn test_star() {
assert_eq!(
parse("*foo").unwrap(),
vec![Token(Star("*foo".to_string()))]
);
assert_eq!(
parse("/*foo").unwrap(),
vec![Token(Slash), Token(Star("*foo".to_string()))]
);
assert_eq!(
parse("/*foo/").unwrap(),
vec![Token(Slash), Token(Star("*foo".to_string())), Token(Slash)]
);
assert_eq!(
parse("/foo/*bar").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Star("*bar".to_string())),
]
);
assert_eq!(
parse("/foo/*bar/").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Token(Star("*bar".to_string())),
Token(Slash),
]
);
assert_eq!(
parse("/*foo/bar").unwrap(),
vec![
Token(Slash),
Token(Star("*foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string())),
]
);
assert_eq!(
parse("/*foo/bar/").unwrap(),
vec![
Token(Slash),
Token(Star("*foo".to_string())),
Token(Slash),
Token(Literal("bar".to_string())),
Token(Slash),
]
);
assert_eq!(
parse("/foo/(*bar)").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Group(vec![Token(Star("*bar".to_string()))]),
]
);
assert_eq!(
parse("/foo/(*bar)/").unwrap(),
vec![
Token(Slash),
Token(Literal("foo".to_string())),
Token(Slash),
Group(vec![Token(Star("*bar".to_string()))]),
Token(Slash),
]
);
assert_eq!(
parse("/(*foo)/bar").unwrap(),
vec![
Token(Slash),
Group(vec![Token(Star("*foo".to_string()))]),
Token(Slash),
Token(Literal("bar".to_string())),
]
);
assert_eq!(
parse("/(*foo)/bar/").unwrap(),
vec![
Token(Slash),
Group(vec![Token(Star("*foo".to_string()))]),
Token(Slash),
Token(Literal("bar".to_string())),
Token(Slash),
]
);
}
#[test]
fn test_or() {
assert_eq!(
parse("a|b").unwrap(),
vec![Or(vec![
Token(Literal("a".to_string())),
Token(Literal("b".to_string())),
])]
);
assert_eq!(
parse("a|b|c").unwrap(),
vec![Or(vec![
Token(Literal("a".to_string())),
Token(Literal("b".to_string())),
Token(Literal("c".to_string())),
])]
);
assert_eq!(
parse("(a|b)|c").unwrap(),
vec![Or(vec![
Group(vec![Or(vec![
Token(Literal("a".to_string())),
Token(Literal("b".to_string())),
])]),
Token(Literal("c".to_string())),
])]
);
assert_eq!(
parse("a|(b|c)").unwrap(),
vec![Or(vec![
Token(Literal("a".to_string())),
Group(vec![Or(vec![
Token(Literal("b".to_string())),
Token(Literal("c".to_string())),
])]),
])]
);
assert_eq!(
parse("*a|(b|c)").unwrap(),
vec![Or(vec![
Token(Star("*a".to_string())),
Group(vec![Or(vec![
Token(Literal("b".to_string())),
Token(Literal("c".to_string())),
])]),
])]
);
assert_eq!(
parse("*a|(:b|c)").unwrap(),
vec![Or(vec![
Token(Star("*a".to_string())),
Group(vec![Or(vec![
Token(Symbol(":b".to_string())),
Token(Literal("c".to_string())),
])]),
])]
);
}
#[test]
@ -292,7 +419,6 @@ fn parse_invalid_paths() {
// assert!(parse(")").is_err());
// }
// #[test]
// fn parse_path() {
// let scanner = Scanner::new("/foo/bar".to_string());