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:
parent
f0235832c3
commit
23490cc237
|
@ -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,
|
||||
|
|
|
@ -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)?))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue