make parsing a bit nicer

This also merges the `match` and single-call interface.
Modules can simply be called with tags.
This commit is contained in:
Alain Zscheile 2023-05-22 21:32:54 +02:00
parent f0235832c3
commit 23490cc237
2 changed files with 36 additions and 45 deletions

View File

@ -6,7 +6,6 @@ pub enum Token<'a> {
CtrlFlowEdit,
Defer,
Final,
Match,
Module,
Public,
Tag,
@ -15,6 +14,8 @@ pub enum Token<'a> {
Assign,
OpenBrace,
CloseBrace,
OpenParen,
CloseParen,
Comma,
SemiColon,
Dot,
@ -101,11 +102,13 @@ impl<'a> Iterator for Lexer<'a> {
let x = self.s.chars().next()?;
let loc = self.loc;
let rtok = match x {
'{' | '}' | '=' | ',' | ';' | '.' => {
'{' | '}' | '(' | ')' | '=' | ',' | ';' | '.' => {
self.eat(x.len_utf8());
match x {
'{' => Token::OpenBrace,
'}' => Token::CloseBrace,
'(' => Token::OpenParen,
')' => Token::CloseParen,
'=' => Token::Assign,
',' => Token::Comma,
';' => Token::SemiColon,
@ -174,7 +177,6 @@ impl<'a> Iterator for Lexer<'a> {
"cfe" => Token::CtrlFlowEdit,
"defer" => Token::Defer,
"final" => Token::Final,
"match" => Token::Match,
"module" => Token::Module,
"pub" => Token::Public,
"tag" => Token::Tag,

View File

@ -181,33 +181,19 @@ impl FullIdentifier {
impl Expression {
fn parse_high(ctx: &mut ParserContext<'_>) -> Result<Self, Error> {
let (mut cfe, mut tag) = (false, false);
let preloc = ctx.peek_loc();
let mut cfe = false;
for (_, i) in ctx
.pklx
.peeking_take_while(|(_, t)| matches!(Token::CtrlFlowEdit | Token::Tag))
.peeking_take_while(|(_, t)| matches!(t, Token::CtrlFlowEdit))
{
match i {
Token::CtrlFlowEdit => cfe = true,
Token::Tag => tag = true,
_ => unimplemented!(),
}
}
if cfe && tag {
return Err(Error {
loc: preloc,
kind: ErrorKind::InvalidCombination(
"you can't specify both cfe and tag at the same time",
),
});
}
let obj = match ctx.pklx.peek() {
None => Err(ctx.make_eof()),
Some((_, Token::Identifier(ident))) if tag => {
Path::parse_high(ctx).map(Expression::Tag)
}
Some((_, Token::OpenBrace)) => {
ctx.pklx.next();
let mut codata = Vec::new();
@ -235,17 +221,16 @@ impl Expression {
}
})
}
Some(&(loc, _)) if tag => Err(Error {
loc,
kind: ErrorKind::Unexpected("identifier"),
}),
Some(&(loc, _)) if cfe => Err(Error {
loc,
kind: ErrorKind::Unexpected("braced statement set"),
}),
// we have no proper recursive delimiting,
// so just resort to the parsing which we also do for other such items,
// expect a single code object descriptor => alias, or number.
Some((_, Token::OpenParen)) => {
ctx.pklx.next();
let inner = Expression::parse_high(ctx)?;
ctx.expect_token(Token::CloseParen, /* ( */ ")")?;
Ok(inner)
}
Some(&(_, Token::Integer(i))) => {
ctx.pklx.next();
Ok(Expression::Integer(i))
@ -257,30 +242,34 @@ impl Expression {
ctx.expect_token(Token::CloseBrace, "}")?;
Ok(Expression::Module(m))
}
Some((_, Token::Tag)) => {
ctx.pklx.next();
Path::parse_high(ctx).map(Expression::Tag)
}
_ => FullIdentifier::parse_high(ctx).map(Expression::Alias),
}?;
Ok(if let Some(&(_, Token::Comma)) = ctx.pklx.peek() {
let mut args = BTreeMap::new();
while ctx.maybe_eat_token(Token::Comma).is_some() {
let Path { loc, idents } = Path::parse_high(ctx)?;
ctx.expect_token(Token::Assign, "=")?;
let obj = Expression::parse_high(ctx)?;
if args.insert(idents, (loc, obj)).is_some() {
return Err(Error {
loc,
kind: ErrorKind::DuplicateIdentifier,
});
Ok(match ctx.pklx.peek() {
None | Some((_, Token::SemiColon)) => obj,
Some((_, Token::Comma)) => {
let mut args = BTreeMap::new();
while ctx.maybe_eat_token(Token::Comma).is_some() {
let Path { loc, idents } = Path::parse_high(ctx)?;
ctx.expect_token(Token::Assign, "=")?;
let obj = Expression::parse_high(ctx)?;
if args.insert(idents, (loc, obj)).is_some() {
return Err(Error {
loc,
kind: ErrorKind::DuplicateIdentifier,
});
}
}
Expression::InvocationMulti {
obj: Box::new(obj),
args,
}
}
Expression::InvocationMulti {
obj: Box::new(obj),
args,
}
} else if matches!(ctx.pklx.peek(), Some(&(_, Token::SemiColon)) | None) {
obj
} else {
Expression::InvocationSingle(Box::new((obj, Expression::parse_high(ctx)?)))
_ => Expression::InvocationSingle(Box::new((obj, Expression::parse_high(ctx)?))),
})
}
}