feat: beginnings of expr parsing
This commit is contained in:
parent
d87bb17a27
commit
3bc507c9e8
|
@ -187,10 +187,12 @@ pub enum ArgName {
|
||||||
},
|
},
|
||||||
Named {
|
Named {
|
||||||
name: String,
|
name: String,
|
||||||
|
location: Span,
|
||||||
},
|
},
|
||||||
NamedLabeled {
|
NamedLabeled {
|
||||||
name: String,
|
name: String,
|
||||||
label: String,
|
label: String,
|
||||||
|
location: Span,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +272,9 @@ pub enum BinOp {
|
||||||
ModInt,
|
ModInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type UntypedPattern = Pattern<(), ()>;
|
||||||
|
pub type TypedPattern = Pattern<PatternConstructor, Arc<Type>>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Pattern<Constructor, Type> {
|
pub enum Pattern<Constructor, Type> {
|
||||||
Int {
|
Int {
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
use internment::Intern;
|
|
||||||
|
|
||||||
use crate::{ast::Span, error::ParseError, token::Token};
|
use crate::{ast::Span, error::ParseError, token::Token};
|
||||||
|
|
||||||
pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
||||||
let int = text::int(10)
|
let int = text::int(10).map(|value| Token::Int { value });
|
||||||
.map(Intern::new)
|
|
||||||
.map(|value| Token::Int { value });
|
|
||||||
|
|
||||||
let op = choice((
|
let op = choice((
|
||||||
just("==").to(Token::EqualEqual),
|
just("==").to(Token::EqualEqual),
|
||||||
|
@ -54,7 +51,6 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
||||||
.ignore_then(filter(|c| *c != '\\' && *c != '"').or(escape).repeated())
|
.ignore_then(filter(|c| *c != '\\' && *c != '"').or(escape).repeated())
|
||||||
.then_ignore(just('"'))
|
.then_ignore(just('"'))
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
.map(Intern::new)
|
|
||||||
.map(|value| Token::String { value })
|
.map(|value| Token::String { value })
|
||||||
.labelled("string");
|
.labelled("string");
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,17 @@ pub fn fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = ParseErr
|
||||||
location: span,
|
location: span,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
select! {Token::Name {name} => name}
|
||||||
|
.then(select! {Token::Name {name} => name})
|
||||||
|
.map_with_span(|(label, name), span| ast::ArgName::NamedLabeled {
|
||||||
|
label,
|
||||||
|
name,
|
||||||
|
location: span,
|
||||||
|
}),
|
||||||
|
select! {Token::Name {name} => name}.map_with_span(|name, span| ast::ArgName::Named {
|
||||||
|
name,
|
||||||
|
location: span,
|
||||||
|
}),
|
||||||
))
|
))
|
||||||
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
||||||
.map_with_span(|(arg_name, annotation), span| ast::Arg {
|
.map_with_span(|(arg_name, annotation), span| ast::Arg {
|
||||||
|
@ -214,7 +225,27 @@ pub fn fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = ParseErr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {}
|
pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {
|
||||||
|
recursive(|r| {
|
||||||
|
choice((just(Token::Try)
|
||||||
|
.ignore_then(pattern_parser())
|
||||||
|
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
||||||
|
.then_ignore(just(Token::Equal))
|
||||||
|
.then(expr_parser())
|
||||||
|
.then(r)
|
||||||
|
.map_with_span(|(((pattern, annotation), value), then_), span| {
|
||||||
|
expr::UntypedExpr::Try {
|
||||||
|
location: span,
|
||||||
|
value: Box::new(value),
|
||||||
|
pattern,
|
||||||
|
then: Box::new(then_),
|
||||||
|
annotation,
|
||||||
|
}
|
||||||
|
}),))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {}
|
||||||
|
|
||||||
pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
|
pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
|
||||||
recursive(|r| {
|
recursive(|r| {
|
||||||
|
@ -313,6 +344,118 @@ pub fn pub_parser() -> impl Parser<Token, (), Error = ParseError> {
|
||||||
just(Token::Pub).ignored()
|
just(Token::Pub).ignored()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = ParseError> {
|
||||||
|
recursive(|r| {
|
||||||
|
let constructor_pattern_arg_parser = choice((
|
||||||
|
select! {Token::Name {name} => name}
|
||||||
|
.then_ignore(just(Token::Colon))
|
||||||
|
.then(r.clone())
|
||||||
|
.map_with_span(|(name, pattern), span| ast::CallArg {
|
||||||
|
location: span,
|
||||||
|
label: Some(name),
|
||||||
|
value: pattern,
|
||||||
|
}),
|
||||||
|
r.map_with_span(|pattern, span| ast::CallArg {
|
||||||
|
location: span,
|
||||||
|
value: pattern,
|
||||||
|
label: None,
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
|
||||||
|
let constructor_pattern_args_parser = constructor_pattern_arg_parser
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
.allow_trailing()
|
||||||
|
.then(
|
||||||
|
just(Token::DotDot)
|
||||||
|
.then_ignore(just(Token::Comma).or_not())
|
||||||
|
.ignored()
|
||||||
|
.or_not(),
|
||||||
|
)
|
||||||
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||||
|
.or_not()
|
||||||
|
.map(|opt_args| {
|
||||||
|
opt_args
|
||||||
|
.map(|(a, b)| (a, b.is_some()))
|
||||||
|
.unwrap_or_else(|| (vec![], false))
|
||||||
|
});
|
||||||
|
|
||||||
|
let constructor_pattern_parser =
|
||||||
|
select! {Token::UpName { name } => name}.then(constructor_pattern_args_parser);
|
||||||
|
|
||||||
|
choice((
|
||||||
|
select! { Token::Name {name} => name }
|
||||||
|
.then(
|
||||||
|
just(Token::Dot)
|
||||||
|
.ignore_then(constructor_pattern_parser.clone())
|
||||||
|
.or_not(),
|
||||||
|
)
|
||||||
|
.map_with_span(|(name, opt_pattern), span| {
|
||||||
|
if let Some((c_name, (arguments, with_spread))) = opt_pattern {
|
||||||
|
ast::UntypedPattern::Constructor {
|
||||||
|
location: span,
|
||||||
|
name: c_name,
|
||||||
|
arguments,
|
||||||
|
module: Some(name),
|
||||||
|
constructor: (),
|
||||||
|
with_spread,
|
||||||
|
tipo: (),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ast::UntypedPattern::Var {
|
||||||
|
location: span,
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
constructor_pattern_parser.map_with_span(|(name, (arguments, with_spread)), span| {
|
||||||
|
ast::UntypedPattern::Constructor {
|
||||||
|
location: span,
|
||||||
|
name,
|
||||||
|
arguments,
|
||||||
|
module: None,
|
||||||
|
constructor: (),
|
||||||
|
with_spread,
|
||||||
|
tipo: (),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
|
||||||
|
ast::UntypedPattern::Discard {
|
||||||
|
name,
|
||||||
|
location: span,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
select! {Token::String {value} => value}.map_with_span(|value, span| {
|
||||||
|
ast::UntypedPattern::String {
|
||||||
|
location: span,
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
select! {Token::Int {value} => value}.map_with_span(|value, span| {
|
||||||
|
ast::UntypedPattern::Int {
|
||||||
|
location: span,
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
.then(
|
||||||
|
just(Token::As)
|
||||||
|
.ignore_then(select! { Token::Name {name} => name})
|
||||||
|
.or_not(),
|
||||||
|
)
|
||||||
|
.map_with_span(|(pattern, opt_as), span| {
|
||||||
|
if let Some(name) = opt_as {
|
||||||
|
ast::UntypedPattern::Assign {
|
||||||
|
name,
|
||||||
|
location: span,
|
||||||
|
pattern: Box::new(pattern),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pattern
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use internment::Intern;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Hash, Eq)]
|
#[derive(Clone, Debug, PartialEq, Hash, Eq)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
Error(char),
|
Error(char),
|
||||||
Name { name: String },
|
Name { name: String },
|
||||||
UpName { name: String },
|
UpName { name: String },
|
||||||
DiscardName { name: String },
|
DiscardName { name: String },
|
||||||
Int { value: Intern<String> },
|
Int { value: String },
|
||||||
String { value: Intern<String> },
|
String { value: String },
|
||||||
// Groupings
|
// Groupings
|
||||||
LeftParen, // (
|
LeftParen, // (
|
||||||
RightParen, // )
|
RightParen, // )
|
||||||
|
@ -85,8 +83,8 @@ impl fmt::Display for Token {
|
||||||
Token::Name { name } => name,
|
Token::Name { name } => name,
|
||||||
Token::UpName { name } => name,
|
Token::UpName { name } => name,
|
||||||
Token::DiscardName { name } => name,
|
Token::DiscardName { name } => name,
|
||||||
Token::Int { value } => &**value,
|
Token::Int { value } => value,
|
||||||
Token::String { value } => &**value,
|
Token::String { value } => value,
|
||||||
Token::LeftParen => "(",
|
Token::LeftParen => "(",
|
||||||
Token::RightParen => ")",
|
Token::RightParen => ")",
|
||||||
Token::LeftSquare => "[",
|
Token::LeftSquare => "[",
|
||||||
|
|
Loading…
Reference in New Issue