lysp: add dotted pair notation
This commit is contained in:
@@ -11,7 +11,7 @@ use nom::{
|
||||
combinator::{map, map_res, opt, recognize, value, verify},
|
||||
error::{Error, ErrorKind, FromExternalError, ParseError},
|
||||
multi::{fold, fold_many1, many0},
|
||||
sequence::{delimited, preceded},
|
||||
sequence::{delimited, pair, preceded},
|
||||
};
|
||||
|
||||
use crate::vm::value::{Keyword, NumberValue, Value, Vector};
|
||||
@@ -331,8 +331,25 @@ fn parse_vector(input: &str) -> IResult<&str, Value> {
|
||||
.parse(input)
|
||||
}
|
||||
|
||||
fn parse_dotted_cons(input: &str) -> IResult<&str, Value> {
|
||||
delimited(
|
||||
char('('),
|
||||
pair(
|
||||
preceded(skip_comment_and_whitespace, parse_value),
|
||||
preceded(
|
||||
pair(skip_comment_and_whitespace, char('.')),
|
||||
preceded(skip_comment_and_whitespace, parse_value),
|
||||
),
|
||||
),
|
||||
preceded(skip_comment_and_whitespace, char(')')),
|
||||
)
|
||||
.map(|(a, b)| a.cons(b))
|
||||
.parse(input)
|
||||
}
|
||||
|
||||
pub fn parse_value(input: &str) -> IResult<&str, Value> {
|
||||
alt((
|
||||
parse_dotted_cons,
|
||||
parse_list_or_nil,
|
||||
parse_vector,
|
||||
parse_boolean,
|
||||
@@ -353,9 +370,9 @@ mod tests {
|
||||
|
||||
use crate::{
|
||||
parse::{
|
||||
OverflowError, parse_boolean, parse_identifier, parse_identifier_or_keyword_or_nil,
|
||||
parse_integer, parse_integer_dec, parse_integer_hex, parse_integer_oct,
|
||||
parse_list_or_nil, parse_value,
|
||||
OverflowError, parse_boolean, parse_dotted_cons, parse_identifier,
|
||||
parse_identifier_or_keyword_or_nil, parse_integer, parse_integer_dec,
|
||||
parse_integer_hex, parse_integer_oct, parse_list_or_nil, parse_value,
|
||||
},
|
||||
vm::value::{Keyword, Value},
|
||||
};
|
||||
@@ -514,6 +531,27 @@ mod tests {
|
||||
assert_eq!(v, Value::Boolean(false.into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dotted_pair() {
|
||||
let (r, v) = parse_dotted_cons("(a.b)").unwrap();
|
||||
assert_eq!(r, "");
|
||||
assert_eq!(
|
||||
v,
|
||||
Value::Identifier("a".into()).cons(Value::Identifier("b".into()))
|
||||
);
|
||||
let (r, v) = parse_dotted_cons("(a .(b. ( c . (d.NIL ) )))").unwrap();
|
||||
assert_eq!(r, "");
|
||||
assert_eq!(
|
||||
v,
|
||||
Value::list_or_nil([
|
||||
Value::Identifier("a".into()),
|
||||
Value::Identifier("b".into()),
|
||||
Value::Identifier("c".into()),
|
||||
Value::Identifier("d".into()),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_value() {
|
||||
let (r, v) = parse_value("+123\n").unwrap();
|
||||
|
||||
@@ -857,6 +857,7 @@ mod tests {
|
||||
let env = Rc::new(Environment::default());
|
||||
// (lambda (y) (let (x 123) (+ x y)))
|
||||
let lambda_function = Rc::new(BytecodeFunction {
|
||||
script: None,
|
||||
identifier: None,
|
||||
docstring: None,
|
||||
instructions: [
|
||||
@@ -906,6 +907,7 @@ mod tests {
|
||||
let env = Rc::new(Environment::default());
|
||||
// (lambda (x y) (+ x y))
|
||||
let lambda_function = Rc::new(BytecodeFunction {
|
||||
script: None,
|
||||
identifier: None,
|
||||
docstring: None,
|
||||
instructions: [
|
||||
|
||||
Reference in New Issue
Block a user