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