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