Comment parsing

This commit is contained in:
Alex Bethel 2022-08-07 22:45:44 -05:00
parent e72a22d294
commit b4fb2deb55
2 changed files with 93 additions and 106 deletions

View file

@ -1 +1,13 @@
def a (x: String) = 2 + a::b["xyz"] + fn x y -> x + y + {a : b};
// Need tuples, f x is broken
def a (x: String) = 2 + a::b["xyz"] // foo
+ fn x y -> x + y + {a : b};
def b = let (x, y) = 20 in x + y;
def c = match x + 1 {
a => {c: d, e: f},
};
class Cat a {
def meow (cat: a);
}

View file

@ -215,6 +215,7 @@ impl Default for ParserMeta {
/// Parser for AlexScript code.
pub fn parser<'a>(m: &'a ParserMeta) -> impl Parser<char, SyntaxTree, Error = Simple<char>> + 'a {
whitespace_cmt().ignore_then(
parse_statement(m)
.repeated()
.map(SyntaxTree)
@ -222,7 +223,8 @@ pub fn parser<'a>(m: &'a ParserMeta) -> impl Parser<char, SyntaxTree, Error = Si
.map(|exprs| {
println!("{:#?}", exprs);
todo!()
})
}),
)
}
fn parse_statement<'a>(
@ -237,16 +239,16 @@ fn parse_statement<'a>(
}
fn parse_type_def(m: &ParserMeta) -> impl Parser<char, Statement, Error = Simple<char>> {
keyword("data")
pad(keyword("data"))
.ignore_then(parse_type(m))
.then_ignore(just('=').then(whitespace()))
.then_ignore(pad(just('=')))
.then(parse_constructor(m).repeated())
.then_ignore(just(';').then(whitespace()))
.then_ignore(pad(just(';')))
.map(|(typ, constructors)| Statement::TypeDefinition { typ, constructors })
}
fn parse_constructor(m: &ParserMeta) -> impl Parser<char, TypeConstructor, Error = Simple<char>> {
ident()
pad(ident())
.then(parse_type(m).repeated())
.map(|(name, args)| TypeConstructor { name, args })
}
@ -254,13 +256,13 @@ fn parse_constructor(m: &ParserMeta) -> impl Parser<char, TypeConstructor, Error
fn parse_instance_def<'a>(
m: &'a ParserMeta,
) -> impl Parser<char, Statement, Error = Simple<char>> + 'a {
keyword("instance")
.ignore_then(ident())
pad(keyword("instance"))
.ignore_then(pad(ident()))
.then(parse_type(m))
.then(
parse_class_member(m)
.repeated()
.delimited_by(just('{').then(whitespace()), just('}').then(whitespace())),
.delimited_by(pad(just('{')), pad(just('}'))),
)
.map(|((classname, typ), decls)| Statement::InstanceDefinition {
class_name: classname,
@ -284,17 +286,11 @@ fn parse_class_member<'a>(
fn parse_func_decl<'a>(
m: &'a ParserMeta,
) -> impl Parser<char, ClassMember, Error = Simple<char>> + 'a {
keyword("def")
.then_ignore(whitespace())
.ignore_then(ident().then_ignore(whitespace()))
pad(keyword("def"))
.ignore_then(pad(ident()))
.then(parse_pattern(m).repeated())
.then(
just('=')
.then(whitespace())
.ignore_then(parse_expression(m))
.or_not(),
)
.then_ignore(just(';').then(whitespace()))
.then(pad(just('=')).ignore_then(parse_expression(m)).or_not())
.then_ignore(pad(just(';')))
.map(|((name, arguments), definition)| ClassMember::Function {
name,
arguments,
@ -303,29 +299,23 @@ fn parse_func_decl<'a>(
}
fn parse_type_alias(m: &ParserMeta) -> impl Parser<char, ClassMember, Error = Simple<char>> {
keyword("type")
.then_ignore(whitespace())
pad(keyword("type"))
.ignore_then(parse_type(m))
.then(
just('=')
.then(whitespace())
.ignore_then(parse_type(m))
.or_not(),
)
.then_ignore(just(';').then(whitespace()))
.then(pad(just('=')).ignore_then(parse_type(m)).or_not())
.then_ignore(pad(just(';')))
.map(|(left, right)| ClassMember::TypeAlias { left, right })
}
fn parse_class_def<'a>(
m: &'a ParserMeta,
) -> impl Parser<char, Statement, Error = Simple<char>> + 'a {
keyword("class")
.ignore_then(ident())
.then(ident())
pad(keyword("class"))
.ignore_then(pad(ident()))
.then(pad(ident()))
.then(
parse_class_member(m)
.repeated()
.delimited_by(just('{').then(whitespace()), just('}').then(whitespace())),
.delimited_by(pad(just('{')), pad(just('}'))),
)
.map(|((name, var), decls)| Statement::ClassDefinition { name, var, decls })
}
@ -355,8 +345,7 @@ fn parse_unary(
_m: &ParserMeta,
base: impl Parser<char, Expr, Error = Simple<char>> + Clone,
) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
choice((just("-").to("-"), just("+").to("+")))
.then_ignore(whitespace())
pad(choice((just("-").to("-"), just("+").to("+"))))
.repeated()
.then(base.clone())
.map(|(ops, exp)| {
@ -374,8 +363,7 @@ fn parse_binary<'a>(
) -> impl Parser<char, Expr, Error = Simple<char>> + 'a + Clone {
let op_defs = m.operators.iter().filter(|def| def.precedence == prec);
let op_parsers = op_defs.map(|def| {
just(def.name.to_string())
.then(whitespace())
pad(just(def.name.to_string()))
.ignore_then(base.clone())
.map(|e| (&def.name, &def.assoc, e))
});
@ -452,12 +440,11 @@ fn parse_let_expr(
m: &ParserMeta,
base: impl Parser<char, Expr, Error = Simple<char>> + Clone,
) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
keyword("let")
.then(whitespace())
pad(keyword("let"))
.ignore_then(parse_pattern(m))
.then_ignore(just('=').then(whitespace()))
.then_ignore(pad(just('=')))
.then(base.clone())
.then_ignore(keyword("in").then(whitespace()))
.then_ignore(pad(keyword("in")))
.then(base.clone())
.map(|((left, right), into)| Expr::Let {
left,
@ -470,16 +457,15 @@ fn parse_match_expr(
m: &ParserMeta,
base: impl Parser<char, Expr, Error = Simple<char>> + Clone,
) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
keyword("match")
.then(whitespace())
pad(keyword("match"))
.ignore_then(base.clone())
.then(
parse_pattern(m)
.then_ignore(just("=>").then(whitespace()))
.then_ignore(pad(just("=>")))
.then(base.clone())
.separated_by(just(",").then(whitespace()))
.separated_by(pad(just(",")))
.allow_trailing()
.delimited_by(just('{').then(whitespace()), just('}').then(whitespace())),
.delimited_by(pad(just('{')), pad(just('}'))),
)
.map(|(matcher, cases)| Expr::Match {
matcher: Box::new(matcher),
@ -491,14 +477,12 @@ fn parse_record_expr(
_m: &ParserMeta,
base: impl Parser<char, Expr, Error = Simple<char>> + Clone,
) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
ident()
.then_ignore(whitespace())
.then_ignore(just(':'))
.then_ignore(whitespace())
pad(ident())
.then_ignore(pad(just(':')))
.then(base)
.separated_by(just(',').then(whitespace()))
.separated_by(pad(just(',')))
.allow_trailing()
.delimited_by(just('{').then(whitespace()), just('}').then(whitespace()))
.delimited_by(pad(just('{')), pad(just('}')))
.map(Expr::Record)
}
@ -506,10 +490,9 @@ fn parse_lambda_expr(
m: &ParserMeta,
base: impl Parser<char, Expr, Error = Simple<char>> + Clone,
) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
keyword("fn")
.then(whitespace())
pad(keyword("fn"))
.ignore_then(parse_pattern(m).repeated())
.then_ignore(just("->").then(whitespace()))
.then_ignore(pad(just("->")))
.then(base)
.map(|(arguments, result)| Expr::Lambda {
arguments,
@ -529,12 +512,11 @@ fn parse_subscript_expr(
base.clone()
.then(
choice((
just('.')
.ignore_then(whitespace())
pad(just('.'))
.ignore_then(base.clone())
.map(|e| (SubscriptKind::Dot, e)),
base.clone()
.delimited_by(just('[').then(whitespace()), just(']').then(whitespace()))
.delimited_by(pad(just('[')), pad(just(']')))
.map(|e| (SubscriptKind::Bracket, e)),
))
.repeated(),
@ -554,9 +536,8 @@ fn parse_subscript_expr(
}
fn parse_var_ref_expr(_m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
ident()
.then_ignore(whitespace())
.separated_by(just("::").then(whitespace()))
pad(ident())
.separated_by(pad(just("::")))
.map(Expr::VariableReference)
}
@ -584,7 +565,6 @@ fn parse_literal(_m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char
))));
let int = int(10)
.then_ignore(whitespace())
.map(|s: String| s.parse().unwrap())
.map(Literal::Integer);
@ -603,9 +583,7 @@ fn parse_literal(_m: &ParserMeta) -> impl Parser<char, Expr, Error = Simple<char
.map(|(l, r)| (l + "." + &r).parse().unwrap())
.map(Literal::Float);
choice((int, float, string))
.then_ignore(whitespace())
.map(Expr::Literal)
pad(choice((int, float, string))).map(Expr::Literal)
}
fn parse_type(m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
@ -630,16 +608,16 @@ fn parse_type(m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
}
fn parse_named_type(_m: &ParserMeta) -> impl Parser<char, Type, Error = Simple<char>> {
ident().then_ignore(whitespace()).map(Type::Named)
pad(ident()).map(Type::Named)
}
fn parse_tuple_type(
_m: &ParserMeta,
rec: impl Parser<char, Type, Error = Simple<char>>,
) -> impl Parser<char, Type, Error = Simple<char>> {
rec.separated_by(just(',').then(whitespace()))
rec.separated_by(pad(just(',')))
.allow_trailing()
.delimited_by(just('(').then(whitespace()), just(')').then(whitespace()))
.delimited_by(pad(just('(')), pad(just(')')))
.map(|types| {
if types.len() == 1 {
// `(Int)` is the same as `Int`
@ -654,14 +632,12 @@ fn parse_record_type(
_m: &ParserMeta,
rec: impl Parser<char, Type, Error = Simple<char>>,
) -> impl Parser<char, Type, Error = Simple<char>> {
ident()
.then_ignore(whitespace())
.then_ignore(just(':'))
.then_ignore(whitespace())
pad(ident())
.then_ignore(pad(just(':')))
.then(rec)
.separated_by(just(',').then(whitespace()))
.separated_by(pad(just(',')))
.allow_trailing()
.delimited_by(just('{').then(whitespace()), just('}').then(whitespace()))
.delimited_by(pad(just('{')), pad(just('}')))
.map(Type::Record)
}
@ -681,12 +657,7 @@ fn parse_pattern(m: &ParserMeta) -> impl Parser<char, Pattern, Error = Simple<ch
.reduce(|l, r| Pattern::Destructure(Box::new(l), Box::new(r)))
.unwrap()
})
.then(
just(':')
.then(whitespace())
.ignore_then(parse_type(m))
.or_not(),
)
.then(pad(just(':')).ignore_then(parse_type(m)).or_not())
.map(|(pat, typ)| match typ {
Some(typ) => Pattern::TypeAnnotated {
pat: Box::new(pat),
@ -698,20 +669,20 @@ fn parse_pattern(m: &ParserMeta) -> impl Parser<char, Pattern, Error = Simple<ch
}
fn parse_ignore_pattern(_m: &ParserMeta) -> impl Parser<char, Pattern, Error = Simple<char>> {
keyword("_").then_ignore(whitespace()).to(Pattern::Ignore)
pad(keyword("_")).to(Pattern::Ignore)
}
fn parse_capture_pattern(_m: &ParserMeta) -> impl Parser<char, Pattern, Error = Simple<char>> {
ident().then_ignore(whitespace()).map(Pattern::Capture)
pad(ident()).map(Pattern::Capture)
}
fn parse_tuple_pattern(
_m: &ParserMeta,
rec: impl Parser<char, Pattern, Error = Simple<char>>,
) -> impl Parser<char, Pattern, Error = Simple<char>> {
rec.separated_by(just(',').then(whitespace()))
rec.separated_by(pad(just(',')))
.allow_trailing()
.delimited_by(just('(').then(whitespace()), just(')').then(whitespace()))
.delimited_by(pad(just('(')), pad(just(')')))
.map(|pats| {
if pats.len() == 1 {
// `(Int)` is the same as `Int`
@ -726,25 +697,13 @@ fn parse_record_pattern(
_m: &ParserMeta,
rec: impl Parser<char, Pattern, Error = Simple<char>>,
) -> impl Parser<char, Pattern, Error = Simple<char>> {
let item = ident().then_ignore(whitespace()).then(
just(':')
.ignore_then(whitespace())
.ignore_then(rec)
.or_not(),
);
let items = item
.separated_by(just(',').then(whitespace()))
.allow_trailing();
let ellipsis = just("...")
.ignore_then(whitespace())
.or_not()
.map(|ellipsis| ellipsis.is_some());
let item = pad(ident()).then(pad(just(':')).ignore_then(rec).or_not());
let items = item.separated_by(pad(just(','))).allow_trailing();
let ellipsis = pad(just("...")).or_not().map(|ellipsis| ellipsis.is_some());
items
.then(ellipsis)
.delimited_by(just('{').then(whitespace()), just('}').then(whitespace()))
.delimited_by(pad(just('{')), pad(just('}')))
.map(|(members, inexhaustive)| Pattern::Record {
members,
inexhaustive,
@ -758,3 +717,19 @@ fn parse_literal_pattern(m: &ParserMeta) -> impl Parser<char, Pattern, Error = S
_ => unreachable!(),
})
}
fn whitespace_cmt() -> impl Parser<char, (), Error = Simple<char>> + Clone {
whitespace().then_ignore(
just("//")
.then(none_of("\n").repeated())
.then(just('\n'))
.then(whitespace())
.repeated(),
)
}
fn pad<T>(
p: impl Parser<char, T, Error = Simple<char>> + Clone,
) -> impl Parser<char, T, Error = Simple<char>> + Clone {
p.then_ignore(whitespace_cmt())
}