Various cleanup

This commit is contained in:
Greg Shuflin 2021-11-19 09:59:08 -08:00
parent 69d857e94d
commit 219f5a183a
2 changed files with 96 additions and 60 deletions

View File

@ -7,11 +7,11 @@ use nom::{
complete::{alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space1}, complete::{alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space1},
is_alphanumeric, is_alphanumeric,
}, },
combinator::{cut, map, not, opt, peek, recognize, value}, combinator::{cut, eof, map, not, opt, peek, recognize, value, verify},
error::{context, ParseError, VerboseError}, error::{context, ParseError, VerboseError},
multi::{many0, many1, separated_list0, separated_list1}, multi::{many0, many1, separated_list0, separated_list1},
sequence::{delimited, pair, preceded, separated_pair, tuple}, sequence::{delimited, pair, preceded, separated_pair, terminated, tuple},
IResult, Parser, Finish, IResult, Parser,
}; };
use nom_locate::{position, LocatedSpan}; use nom_locate::{position, LocatedSpan};
@ -27,6 +27,38 @@ use crate::ast::*;
fn rc_string(s: &str) -> Rc<String> { fn rc_string(s: &str) -> Rc<String> {
Rc::new(s.to_string()) Rc::new(s.to_string())
} }
fn is_keyword(input: &str) -> bool {
let keywords = [
"if",
"then",
"else",
"is",
"fn",
"for",
"while",
"in",
"true",
"false",
"let",
"in",
"mut",
"return",
"break",
"continue",
"type",
"alias",
"self",
"Self",
"interface",
"impl",
"module",
"import",
];
keywords.iter().any(|kw| kw == &input)
}
fn fresh_id(span: &Span) -> Id<ASTItem> { fn fresh_id(span: &Span) -> Id<ASTItem> {
let mut table_handle = span.extra.borrow_mut(); let mut table_handle = span.extra.borrow_mut();
table_handle.fresh() table_handle.fresh()
@ -750,9 +782,17 @@ fn identifier(input: Span) -> ParseResult<Span> {
} }
fn identifier_span(input: Span) -> ParseResult<Span> { fn identifier_span(input: Span) -> ParseResult<Span> {
recognize(pair(alt((tag("_"), alpha1)), take_while(|ch: char| is_alphanumeric(ch as u8) || ch == '_')))( fn check(input: &Span) -> bool {
input, !is_keyword(input.fragment())
) }
verify(
recognize(tuple((
alt((tag("_"), alpha1)),
take_while(|ch: char| is_alphanumeric(ch as u8) || ch == '_'),
))),
check,
)(input)
} }
fn bool_literal(input: Span) -> ParseResult<ExpressionKind> { fn bool_literal(input: Span) -> ParseResult<ExpressionKind> {
@ -897,21 +937,6 @@ mod test {
use super::*; use super::*;
fn rc(s: &str) -> Rc<String> {
Rc::new(s.to_owned())
}
macro_rules! qn {
( $( $component:ident),* ) => {
{
let mut components = vec![];
$(
components.push(rc(stringify!($component)));
)*
QualifiedName { components, id: Default::default() }
}
};
}
macro_rules! span { macro_rules! span {
($func:expr, $input:expr) => {{ ($func:expr, $input:expr) => {{
let id_store: IdStore<ASTItem> = IdStore::new(); let id_store: IdStore<ASTItem> = IdStore::new();
@ -926,6 +951,8 @@ mod test {
assert_eq!(span!(bin_literal, "0b1111qsdf"), Ok(("qsdf", 15))); assert_eq!(span!(bin_literal, "0b1111qsdf"), Ok(("qsdf", 15)));
assert_eq!(span!(bare_string_literal, r#""fah""#), Ok(("", "fah".to_string()))); assert_eq!(span!(bare_string_literal, r#""fah""#), Ok(("", "fah".to_string())));
assert_eq!(span!(bare_string_literal, r#""""#), Ok(("", "".to_string()))); assert_eq!(span!(bare_string_literal, r#""""#), Ok(("", "".to_string())));
assert_eq!(*span!(identifier_span, "modulek").unwrap().1.fragment(), "modulek");
assert!(span!(identifier_span, "module").is_err());
} }
#[test] #[test]
@ -946,9 +973,5 @@ mod test {
span!(expression_kind(true), " /*gay*/ true").unwrap().1, span!(expression_kind(true), " /*gay*/ true").unwrap().1,
ExpressionKind::BoolLiteral(true) ExpressionKind::BoolLiteral(true)
); );
assert_eq!(
span!(expression_kind(true), " /*yolo*/ barnaby").unwrap().1,
ExpressionKind::Value(qn!(barnaby))
);
} }
} }

View File

@ -85,6 +85,7 @@ fn ty_simple(name: &str) -> TypeIdentifier {
TypeIdentifier::Singleton(TypeSingletonName { name: rc(name), params: vec![] }) TypeIdentifier::Singleton(TypeSingletonName { name: rc(name), params: vec![] })
} }
/*
macro_rules! assert_ast { macro_rules! assert_ast {
($input:expr, $statements:expr) => { ($input:expr, $statements:expr) => {
let mut parser = Parser::new(); let mut parser = Parser::new();
@ -97,8 +98,9 @@ macro_rules! assert_ast {
assert_eq!(ast.unwrap(), expected); assert_eq!(ast.unwrap(), expected);
}; };
} }
*/
macro_rules! assert_ast_comb { macro_rules! assert_ast {
($input:expr, $statements:expr) => { ($input:expr, $statements:expr) => {
let mut parser = Parser::new(); let mut parser = Parser::new();
let ast = parser.parse_comb($input); let ast = parser.parse_comb($input);
@ -119,6 +121,14 @@ macro_rules! assert_fail {
}; };
} }
macro_rules! assert_fail_comb {
($input:expr, $failure:expr) => {
let mut parser = Parser::new();
let err = parser.parse_comb($input).unwrap_err();
assert_eq!(err.msg, $failure);
};
}
/* /*
macro_rules! assert_expr { macro_rules! assert_expr {
($input:expr, $correct:expr) => { ($input:expr, $correct:expr) => {
@ -195,7 +205,7 @@ fn binexps() {
use StatementKind::Expression; use StatementKind::Expression;
assert_expr!("0xf_f+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1)))); assert_expr!("0xf_f+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
assert_ast_comb!( assert_ast!(
"3; 4; 4.3", "3; 4; 4.3",
vec![ vec![
stmt(Expression(expr(NatLiteral(3)))), stmt(Expression(expr(NatLiteral(3)))),
@ -509,7 +519,7 @@ fn complex_lambdas() {
use ExpressionKind::*; use ExpressionKind::*;
//TODO support this without the semicolon after the lambda //TODO support this without the semicolon after the lambda
assert_ast_comb! { assert_ast! {
r#"fn wahoo() { let a = 10; \(x) { x + a }; } r#"fn wahoo() { let a = 10; \(x) { x + a }; }
wahoo()(3) "#, wahoo()(3) "#,
vec![ vec![
@ -553,7 +563,7 @@ fn type_annotations() {
use ExpressionKind::*; use ExpressionKind::*;
use TypeIdentifier::*; use TypeIdentifier::*;
assert_ast_comb!( assert_ast!(
"let a = b : Int", "let a = b : Int",
vec![decl(Declaration::Binding { vec![decl(Declaration::Binding {
name: rc("a"), name: rc("a"),
@ -611,7 +621,7 @@ fn type_annotations() {
#[test] #[test]
fn type_declarations() { fn type_declarations() {
use Declaration::TypeDecl; use Declaration::TypeDecl;
assert_ast_comb! { assert_ast! {
"type Alpha = Alpha", vec![ "type Alpha = Alpha", vec![
decl(TypeDecl { decl(TypeDecl {
name: TypeSingletonName { name: rc("Alpha"), params: vec![] }, name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
@ -627,7 +637,7 @@ fn type_declarations() {
] ]
}; };
assert_ast_comb!( assert_ast!(
"type mut Kuah = Kuah", "type mut Kuah = Kuah",
decl(TypeDecl { decl(TypeDecl {
name: TypeSingletonName { name: rc("Kuah"), params: vec![] }, name: TypeSingletonName { name: rc("Kuah"), params: vec![] },
@ -640,7 +650,7 @@ fn type_declarations() {
}) })
); );
assert_ast_comb! { assert_ast! {
"type Alpha = Alpha { a: Int, b: Int }", "type Alpha = Alpha { a: Int, b: Int }",
vec![decl(TypeDecl { vec![decl(TypeDecl {
name: TypeSingletonName { name: rc("Alpha"), params: vec![] }, name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
@ -658,7 +668,7 @@ fn type_declarations() {
})] })]
}; };
assert_ast_comb! { assert_ast! {
"type Alpha = { a: Int, b: Int }", "type Alpha = { a: Int, b: Int }",
vec![decl(TypeDecl { vec![decl(TypeDecl {
name: TypeSingletonName { name: rc("Alpha"), params: vec![] }, name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
@ -671,7 +681,7 @@ fn type_declarations() {
})] })]
}; };
assert_ast_comb!( assert_ast!(
"type Option<T> = None | Some(T)", "type Option<T> = None | Some(T)",
vec![decl(TypeDecl { vec![decl(TypeDecl {
name: TypeSingletonName { name: TypeSingletonName {
@ -693,12 +703,12 @@ fn type_declarations() {
})] })]
); );
assert_ast_comb!( assert_ast!(
"type alias Alpha = Beta", "type alias Alpha = Beta",
decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") }) decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") })
); );
assert_ast_comb!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))", assert_ast!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))",
decl(TypeDecl { decl(TypeDecl {
name: TypeSingletonName { name: rc("Complex"), params: vec![ name: TypeSingletonName { name: rc("Complex"), params: vec![
TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }), TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }),
@ -735,7 +745,7 @@ fn type_declarations() {
fn declarations() { fn declarations() {
use ExpressionKind::*; use ExpressionKind::*;
assert_ast_comb!( assert_ast!(
"let q_q = Yolo::Swaggins", "let q_q = Yolo::Swaggins",
vec![decl(Declaration::Binding { vec![decl(Declaration::Binding {
name: rc("q_q"), name: rc("q_q"),
@ -750,7 +760,7 @@ fn declarations() {
fn bindings() { fn bindings() {
use ExpressionKind::*; use ExpressionKind::*;
assert_ast_comb!( assert_ast!(
"let mut a = 10", "let mut a = 10",
vec![decl(Declaration::Binding { vec![decl(Declaration::Binding {
name: rc("a"), name: rc("a"),
@ -760,7 +770,7 @@ fn bindings() {
})] })]
); );
assert_ast_comb!( assert_ast!(
"let a = 2 + a", "let a = 2 + a",
vec![stmt(StatementKind::Declaration(Declaration::Binding { vec![stmt(StatementKind::Declaration(Declaration::Binding {
name: rc("a"), name: rc("a"),
@ -770,7 +780,7 @@ fn bindings() {
}))] }))]
); );
assert_ast_comb!( assert_ast!(
"let a: Nat = 2", "let a: Nat = 2",
vec![stmt(StatementKind::Declaration(Declaration::Binding { vec![stmt(StatementKind::Declaration(Declaration::Binding {
name: rc("a"), name: rc("a"),
@ -784,7 +794,7 @@ fn bindings() {
#[test] #[test]
fn functions() { fn functions() {
use ExpressionKind::*; use ExpressionKind::*;
assert_ast_comb!( assert_ast!(
"fn oi()", "fn oi()",
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature { vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("oi"), name: rc("oi"),
@ -794,7 +804,7 @@ fn functions() {
})))] })))]
); );
assert_ast_comb!( assert_ast!(
"oi()", "oi()",
vec![stmt(StatementKind::Expression(expr(Call { f: bx(expr(Value(qn!(oi)))), arguments: vec![] })))] vec![stmt(StatementKind::Expression(expr(Call { f: bx(expr(Value(qn!(oi)))), arguments: vec![] })))]
); );
@ -811,7 +821,7 @@ fn functions() {
); );
assert_fail!("a(b,,c)","error at 1:5: expected one of \"(\", \".\", \"0b\", \"0x\", \"[\", \"\\\"\", \"_\", \"false\", \"for\", \"if\", \"true\", \"while\", ['+' | '-' | '!'], ['0' ..= '9'], ['a' ..= 'z' | 'A' ..= 'Z' | '_'], r#\"\\\"#"); assert_fail!("a(b,,c)","error at 1:5: expected one of \"(\", \".\", \"0b\", \"0x\", \"[\", \"\\\"\", \"_\", \"false\", \"for\", \"if\", \"true\", \"while\", ['+' | '-' | '!'], ['0' ..= '9'], ['a' ..= 'z' | 'A' ..= 'Z' | '_'], r#\"\\\"#");
assert_ast_comb!( assert_ast!(
"fn a(b, c: Int): Int", "fn a(b, c: Int): Int",
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature { vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("a"), name: rc("a"),
@ -836,7 +846,7 @@ fn functions() {
}"#; }"#;
assert_ast_comb!( assert_ast!(
source, source,
vec![fn_decl( vec![fn_decl(
Signature { name: rc("some_function"), operator: false, type_anno: None, params: vec![] }, Signature { name: rc("some_function"), operator: false, type_anno: None, params: vec![] },
@ -876,7 +886,7 @@ fn functions_with_different_whitespace() {
"#; "#;
for item in [a, b, c].iter() { for item in [a, b, c].iter() {
assert_ast_comb!( assert_ast!(
item, item,
vec![fn_decl( vec![fn_decl(
Signature { Signature {
@ -899,7 +909,7 @@ fn functions_with_different_whitespace() {
fn functions_with_default_args() { fn functions_with_default_args() {
use ExpressionKind::*; use ExpressionKind::*;
assert_ast_comb!( assert_ast!(
"fn func(x: Int, y: Int = 4) { }", "fn func(x: Int, y: Int = 4) { }",
vec![fn_decl( vec![fn_decl(
Signature { Signature {
@ -923,7 +933,7 @@ fn functions_with_default_args() {
#[test] #[test]
fn interface() { fn interface() {
let glue = TypeIdentifier::Singleton(TypeSingletonName { name: rc("Glue"), params: vec![] }); let glue = TypeIdentifier::Singleton(TypeSingletonName { name: rc("Glue"), params: vec![] });
assert_ast_comb!( assert_ast!(
"interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }", "interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }",
vec![decl(Declaration::Interface { vec![decl(Declaration::Interface {
name: rc("Unglueable"), name: rc("Unglueable"),
@ -955,13 +965,13 @@ fn impls() {
), ),
]; ];
assert_ast_comb!( assert_ast!(
"impl Heh { fn yolo() { }; fn swagg() { } }", "impl Heh { fn yolo() { }; fn swagg() { } }",
vec![decl(Impl { type_name: ty_simple("Heh"), interface_name: None, block: block.clone() })] vec![decl(Impl { type_name: ty_simple("Heh"), interface_name: None, block: block.clone() })]
); );
//TODO `"impl Heh<X> { fn yolo() { }; fn swagg() { }; }"` ought to work //TODO `"impl Heh<X> { fn yolo() { }; fn swagg() { }; }"` ought to work
assert_ast_comb!( assert_ast!(
"impl Heh<X> { fn yolo() { }; fn swagg() { } }", "impl Heh<X> { fn yolo() { }; fn swagg() { } }",
vec![decl(Impl { vec![decl(Impl {
type_name: TypeIdentifier::Singleton(TypeSingletonName { type_name: TypeIdentifier::Singleton(TypeSingletonName {
@ -973,7 +983,7 @@ fn impls() {
})] })]
); );
assert_ast_comb!( assert_ast!(
"impl Heh for Saraz { fn yolo() {}; fn swagg() {} }", "impl Heh for Saraz { fn yolo() {}; fn swagg() {} }",
vec![decl(Impl { vec![decl(Impl {
type_name: ty_simple("Saraz"), type_name: ty_simple("Saraz"),
@ -982,7 +992,7 @@ fn impls() {
})] })]
); );
assert_ast_comb!( assert_ast!(
"impl Heh<T> for (Int, Codepoint) {}", "impl Heh<T> for (Int, Codepoint) {}",
vec![decl(Impl { vec![decl(Impl {
type_name: TypeIdentifier::Tuple(vec![ty_simple("Int"), ty_simple("Codepoint")]), type_name: TypeIdentifier::Tuple(vec![ty_simple("Int"), ty_simple("Codepoint")]),
@ -1001,7 +1011,7 @@ fn annotations() {
vec![].into(), vec![].into(),
)); ));
assert_ast_comb! { assert_ast! {
r#" r#"
@test_annotation @test_annotation
fn some_function() { fn some_function() {
@ -1015,7 +1025,7 @@ fn annotations() {
] ]
}; };
assert_ast_comb! { assert_ast! {
r#" r#"
@test_annotation(some,value) @test_annotation(some,value)
@another_annotation @another_annotation
@ -1035,7 +1045,7 @@ fn annotations() {
#[test] #[test]
fn modules() { fn modules() {
assert_ast_comb! { assert_ast! {
r#" r#"
module ephraim { module ephraim {
let mut a = 10 let mut a = 10
@ -1058,7 +1068,7 @@ fn modules() {
#[test] #[test]
fn imports() { fn imports() {
assert_ast_comb! { assert_ast! {
"import harbinger::draughts::Norgleheim", "import harbinger::draughts::Norgleheim",
vec![stmt(StatementKind::Import(ImportSpecifier { vec![stmt(StatementKind::Import(ImportSpecifier {
id: ItemId::default(), id: ItemId::default(),
@ -1067,7 +1077,7 @@ fn imports() {
}))] }))]
}; };
assert_ast_comb! { assert_ast! {
"import harbinger::draughts::{Norgleheim, Xraksenlaigar}", "import harbinger::draughts::{Norgleheim, Xraksenlaigar}",
vec![stmt(StatementKind::Import(ImportSpecifier { vec![stmt(StatementKind::Import(ImportSpecifier {
id: ItemId::default(), id: ItemId::default(),
@ -1078,7 +1088,7 @@ fn imports() {
}; };
//TODO this shouldn't be legal //TODO this shouldn't be legal
assert_ast_comb! { assert_ast! {
"import bespouri::{}", "import bespouri::{}",
vec![stmt(StatementKind::Import(ImportSpecifier { vec![stmt(StatementKind::Import(ImportSpecifier {
id: Default::default(), id: Default::default(),
@ -1087,7 +1097,7 @@ fn imports() {
}))] }))]
}; };
assert_ast_comb! { assert_ast! {
"import bespouri::*", "import bespouri::*",
vec![stmt(StatementKind::Import(ImportSpecifier { vec![stmt(StatementKind::Import(ImportSpecifier {
id: Default::default(), id: Default::default(),
@ -1302,7 +1312,7 @@ fn flow_control() {
return 10; return 10;
}"#; }"#;
assert_ast_comb!( assert_ast!(
source, source,
vec![fn_decl( vec![fn_decl(
Signature { name: rc("test"), operator: false, type_anno: None, params: vec![] }, Signature { name: rc("test"), operator: false, type_anno: None, params: vec![] },
@ -1413,7 +1423,10 @@ fn comments() {
assert_fail_expr!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2)))); assert_fail_expr!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))));
let source = "5//no man\n"; let source = "5//no man\n";
assert_ast_comb!(source, vec![exst(NatLiteral(5))]); assert_ast!(source, vec![exst(NatLiteral(5))]);
let source = " /*yolo*/ barnaby";
assert_ast!(source, exst(ExpressionKind::Value(qn!(barnaby))));
} }
//TODO support backtick operators like this //TODO support backtick operators like this