Compare commits
No commits in common. "a66e769b5adf3fe56e6d833ab39fda071f8160c4" and "200bd1d7026722b1f0b14ff056e3bf056b570e87" have entirely different histories.
a66e769b5a
...
200bd1d702
109
src/parser.rs
109
src/parser.rs
|
@ -1,12 +1,17 @@
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{escaped, is_not, tag, take_until},
|
bytes::complete::{escaped, is_not},
|
||||||
character::complete::{alpha1, alphanumeric1, char, multispace0, one_of, space0},
|
bytes::complete::{tag, take_until},
|
||||||
combinator::{cut, map, recognize, value},
|
character::complete::char,
|
||||||
error::ParseError,
|
character::complete::multispace0,
|
||||||
|
character::complete::{alpha1, alphanumeric1, digit1, one_of, space0},
|
||||||
|
combinator::value,
|
||||||
|
combinator::{cut, map, map_res, recognize},
|
||||||
|
error::{context, convert_error, ContextError, ErrorKind, ParseError, VerboseError},
|
||||||
multi::{fold_many0, many0, separated_list0},
|
multi::{fold_many0, many0, separated_list0},
|
||||||
number::complete::double,
|
number::complete::double,
|
||||||
sequence::{delimited, pair, preceded, terminated, tuple},
|
sequence::pair,
|
||||||
|
sequence::{delimited, preceded, terminated, tuple},
|
||||||
IResult, Parser,
|
IResult, Parser,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,11 +28,17 @@ fn pinline_comment<'a, E>(i: &'a str) -> IResult<&'a str, (), E>
|
||||||
where
|
where
|
||||||
E: ParseError<&'a str>,
|
E: ParseError<&'a str>,
|
||||||
{
|
{
|
||||||
value((), tuple((tag("/*"), take_until("*/"), tag("*/"))))(i)
|
value(
|
||||||
|
(), // Output is thrown away.
|
||||||
|
tuple((tag("/*"), take_until("*/"), tag("*/"))),
|
||||||
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> {
|
fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> {
|
||||||
value((), pair(char('/'), is_not("\n\r")))(i)
|
value(
|
||||||
|
(), // Output is thrown away.
|
||||||
|
pair(char('/'), is_not("\n\r")),
|
||||||
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn braces<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
|
fn braces<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
|
||||||
|
@ -50,17 +61,11 @@ where
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn identifier(i: &str) -> IResult<&str, &str> {
|
fn identifier(input: &str) -> IResult<&str, &str> {
|
||||||
println!("identifier: {}", i);
|
|
||||||
recognize(pair(
|
recognize(pair(
|
||||||
alt((alpha1, tag("_"))),
|
alt((alpha1, tag("_"))),
|
||||||
many0(alt((alphanumeric1, tag("_")))),
|
many0(alt((alphanumeric1, tag("_")))),
|
||||||
))(i)
|
))(input)
|
||||||
}
|
|
||||||
|
|
||||||
fn variable(i: &str) -> IResult<&str, Expr> {
|
|
||||||
println!("variable: {}", i);
|
|
||||||
map(identifier, |a| Expr::Var(a.to_string()))(i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_str<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
|
fn parse_str<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
|
||||||
|
@ -68,7 +73,6 @@ fn parse_str<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
fn string<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
||||||
println!("string: {}", i);
|
|
||||||
map(
|
map(
|
||||||
preceded(char('\"'), cut(terminated(parse_str, char('\"')))),
|
preceded(char('\"'), cut(terminated(parse_str, char('\"')))),
|
||||||
|s| Expr::LStr(String::from(s)),
|
|s| Expr::LStr(String::from(s)),
|
||||||
|
@ -83,22 +87,18 @@ fn boolean<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
||||||
))(i)
|
))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
fn call<'a>(i: &'a str) -> IResult<&'a str, (Identifier, Vec<Expr>)> {
|
||||||
println!("call: {}", i);
|
println!("call: {}", i);
|
||||||
map(
|
map(
|
||||||
tuple((
|
tuple((
|
||||||
identifier,
|
identifier,
|
||||||
sc,
|
delimited(
|
||||||
alt((
|
char('('),
|
||||||
value(vec![], tuple((char('('), sc, char(')')))),
|
separated_list0(tuple((sc, tag(","), sc)), expr),
|
||||||
delimited(
|
char(')'),
|
||||||
char('('),
|
),
|
||||||
separated_list0(tuple((sc, tag(","), sc)), expr),
|
|
||||||
char(')'),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
)),
|
)),
|
||||||
|(i, _, v)| Expr::Call(i.to_string(), v),
|
|(i, v)| (i.to_string(), v),
|
||||||
)(i)
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ fn literal(i: &str) -> IResult<&str, Expr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn factor_bin(i: &str) -> IResult<&str, Expr> {
|
fn factor_bin(i: &str) -> IResult<&str, Expr> {
|
||||||
alt((delimited(space0, term, space0), expr))(i)
|
alt((delimited(space0, literal, space0), expr))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bin_less_greater(i: &str) -> IResult<&str, Expr> {
|
fn bin_less_greater(i: &str) -> IResult<&str, Expr> {
|
||||||
|
@ -134,13 +134,13 @@ fn bin_equal_not(i: &str) -> IResult<&str, Expr> {
|
||||||
let (i, init) = bin_less_greater(i)?;
|
let (i, init) = bin_less_greater(i)?;
|
||||||
|
|
||||||
fold_many0(
|
fold_many0(
|
||||||
pair(alt((tag("=="), tag("!="))), bin_less_greater),
|
pair(alt((char('<'), char('>'))), bin_less_greater),
|
||||||
move || init.clone(),
|
move || init.clone(),
|
||||||
|acc, (op, val)| {
|
|acc, (op, val): (char, Expr)| {
|
||||||
if op == "==" {
|
if op == '<' {
|
||||||
Expr::Binary(BinOp::Equals, Box::new(acc), Box::new(val))
|
Expr::Binary(BinOp::LessThan, Box::new(acc), Box::new(val))
|
||||||
} else {
|
} else {
|
||||||
Expr::Binary(BinOp::NotEquals, Box::new(acc), Box::new(val))
|
Expr::Binary(BinOp::GreaterThan, Box::new(acc), Box::new(val))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)(i)
|
)(i)
|
||||||
|
@ -177,19 +177,25 @@ fn binary<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
||||||
)(i)
|
)(i)
|
||||||
}
|
}
|
||||||
fn receive<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
fn receive<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
||||||
println!("receive: {}", i);
|
|
||||||
map(pair(tag("<-"), expr), |(_, expr)| {
|
map(pair(tag("<-"), expr), |(_, expr)| {
|
||||||
Expr::Receive(Box::new(expr))
|
Expr::Receive(Box::new(expr))
|
||||||
})(i)
|
})(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
pub fn expr<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
||||||
alt((receive, binary))(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn term<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
|
||||||
println!("expr: {}", i);
|
println!("expr: {}", i);
|
||||||
delimited(sc, alt((literal, call, variable, parens(expr))), sc)(i)
|
delimited(
|
||||||
|
sc,
|
||||||
|
alt((
|
||||||
|
parens(expr),
|
||||||
|
map(call, |(i, v)| Expr::Call(i, v)),
|
||||||
|
receive,
|
||||||
|
binary,
|
||||||
|
literal,
|
||||||
|
map(identifier, |i| Expr::Var(i.to_string())),
|
||||||
|
)),
|
||||||
|
sc,
|
||||||
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -208,7 +214,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn can_parse_binary_op() {
|
fn can_parse_binary_op() {
|
||||||
let a = "3 +3 + 6";
|
let a = "3 +3 + 6";
|
||||||
let (_rest, res) = expr(a).unwrap();
|
let (_rest, res) = binary(a).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
|
@ -227,7 +233,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn can_parse_binary_op_with_str() {
|
fn can_parse_binary_op_with_str() {
|
||||||
let a = r#"3 +3 + 6 + "hey""#;
|
let a = r#"3 +3 + 6 + "hey""#;
|
||||||
let (_rest, res) = expr(a).unwrap();
|
let (_rest, res) = binary(a).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
|
@ -247,15 +253,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_parse_var() {
|
|
||||||
let a = "hello";
|
|
||||||
let (rest, res) = expr(a).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(res, Expr::Var("hello".to_string()));
|
|
||||||
assert_eq!(rest, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_parse_empty_call() {
|
fn can_parse_empty_call() {
|
||||||
let a = "hello()";
|
let a = "hello()";
|
||||||
|
@ -265,18 +262,6 @@ mod tests {
|
||||||
assert_eq!(rest, "");
|
assert_eq!(rest, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_parse_call_with_var() {
|
|
||||||
let a = "hello(hey)";
|
|
||||||
let (rest, res) = expr(a).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
res,
|
|
||||||
Expr::Call("hello".to_string(), vec![Expr::Var("hey".to_string())])
|
|
||||||
);
|
|
||||||
assert_eq!(rest, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_parse_call() {
|
fn can_parse_call() {
|
||||||
let a = "hello(1.0, 45 , yeah)";
|
let a = "hello(1.0, 45 , yeah)";
|
||||||
|
|
Loading…
Reference in New Issue