lysp: add dotted pair notation

This commit is contained in:
2026-06-02 09:42:45 +03:00
parent 679ac51602
commit befdf63c7c
2 changed files with 44 additions and 4 deletions
+42 -4
View File
@@ -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();
+2
View File
@@ -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: [