Compare commits
3 commits
35ada4a21d
...
ed6c52f120
Author | SHA1 | Date | |
---|---|---|---|
|
ed6c52f120 | ||
|
23490cc237 | ||
|
f0235832c3 |
|
@ -35,8 +35,8 @@ as an argument, prefix the block with `'`.
|
||||||
## Control flow builtins
|
## Control flow builtins
|
||||||
|
|
||||||
- `cflow.if, cond = ..., then = ..., else = ...`
|
- `cflow.if, cond = ..., then = ..., else = ...`
|
||||||
- `cflow.loop ...`
|
- `cflow.loop § ...`
|
||||||
- `cflow.return ...` (implicit when last expr in a block is not terminated via semicolon)
|
- `cflow.return § ...` (implicit when last expr in a block is not terminated via semicolon)
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ with package-lock files or such. Packages (packaged module trees) would then be
|
||||||
# 1.
|
# 1.
|
||||||
|
|
||||||
final main { args env } = {
|
final main { args env } = {
|
||||||
std.io.writeln "Hello World!";
|
std.io.writeln § "Hello World!";
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ with package-lock files or such. Packages (packaged module trees) would then be
|
||||||
what_now = {
|
what_now = {
|
||||||
self.business_in_the_front;
|
self.business_in_the_front;
|
||||||
}, self.party_in_the_back {
|
}, self.party_in_the_back {
|
||||||
std.io.writeln "It works";
|
std.io.writeln § "It works";
|
||||||
};
|
};
|
||||||
|
|
||||||
# running `what_now` results in "It works" being printed.
|
# running `what_now` results in "It works" being printed.
|
||||||
|
|
|
@ -6,7 +6,6 @@ pub enum Token<'a> {
|
||||||
CtrlFlowEdit,
|
CtrlFlowEdit,
|
||||||
Defer,
|
Defer,
|
||||||
Final,
|
Final,
|
||||||
Match,
|
|
||||||
Module,
|
Module,
|
||||||
Public,
|
Public,
|
||||||
Tag,
|
Tag,
|
||||||
|
@ -15,9 +14,12 @@ pub enum Token<'a> {
|
||||||
Assign,
|
Assign,
|
||||||
OpenBrace,
|
OpenBrace,
|
||||||
CloseBrace,
|
CloseBrace,
|
||||||
|
OpenParen,
|
||||||
|
CloseParen,
|
||||||
Comma,
|
Comma,
|
||||||
SemiColon,
|
SemiColon,
|
||||||
Dot,
|
Dot,
|
||||||
|
MatchPara,
|
||||||
|
|
||||||
// dynamic stuff
|
// dynamic stuff
|
||||||
/// amount of prefixed `$` to force immediate application
|
/// amount of prefixed `$` to force immediate application
|
||||||
|
@ -32,11 +34,6 @@ impl Token<'_> {
|
||||||
pub fn is_def_attr(&self) -> bool {
|
pub fn is_def_attr(&self) -> bool {
|
||||||
matches!(self, Token::Final)
|
matches!(self, Token::Final)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn is_cobj_attr(&self) -> bool {
|
|
||||||
matches!(self, Token::CtrlFlowEdit)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
|
@ -106,15 +103,18 @@ impl<'a> Iterator for Lexer<'a> {
|
||||||
let x = self.s.chars().next()?;
|
let x = self.s.chars().next()?;
|
||||||
let loc = self.loc;
|
let loc = self.loc;
|
||||||
let rtok = match x {
|
let rtok = match x {
|
||||||
'{' | '}' | '=' | ',' | ';' | '.' => {
|
'{' | '}' | '(' | ')' | '=' | ',' | ';' | '.' | '§' => {
|
||||||
self.eat(x.len_utf8());
|
self.eat(x.len_utf8());
|
||||||
match x {
|
match x {
|
||||||
'{' => Token::OpenBrace,
|
'{' => Token::OpenBrace,
|
||||||
'}' => Token::CloseBrace,
|
'}' => Token::CloseBrace,
|
||||||
|
'(' => Token::OpenParen,
|
||||||
|
')' => Token::CloseParen,
|
||||||
'=' => Token::Assign,
|
'=' => Token::Assign,
|
||||||
',' => Token::Comma,
|
',' => Token::Comma,
|
||||||
';' => Token::SemiColon,
|
';' => Token::SemiColon,
|
||||||
'.' => Token::Dot,
|
'.' => Token::Dot,
|
||||||
|
'§' => Token::MatchPara,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,6 @@ impl<'a> Iterator for Lexer<'a> {
|
||||||
"cfe" => Token::CtrlFlowEdit,
|
"cfe" => Token::CtrlFlowEdit,
|
||||||
"defer" => Token::Defer,
|
"defer" => Token::Defer,
|
||||||
"final" => Token::Final,
|
"final" => Token::Final,
|
||||||
"match" => Token::Match,
|
|
||||||
"module" => Token::Module,
|
"module" => Token::Module,
|
||||||
"pub" => Token::Public,
|
"pub" => Token::Public,
|
||||||
"tag" => Token::Tag,
|
"tag" => Token::Tag,
|
||||||
|
|
|
@ -50,10 +50,7 @@ pub enum Expression {
|
||||||
obj: Box<Expression>,
|
obj: Box<Expression>,
|
||||||
args: BTreeMap<Box<[Atom]>, (Location, Expression)>,
|
args: BTreeMap<Box<[Atom]>, (Location, Expression)>,
|
||||||
},
|
},
|
||||||
Tag {
|
Tag(Path),
|
||||||
obj: Box<Expression>,
|
|
||||||
args: BTreeMap<Box<[Atom]>, (Location, Expression)>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -79,6 +76,7 @@ pub enum ErrorKind {
|
||||||
UnexpectedTrail,
|
UnexpectedTrail,
|
||||||
InvalidIdentifier,
|
InvalidIdentifier,
|
||||||
DuplicateIdentifier,
|
DuplicateIdentifier,
|
||||||
|
InvalidCombination(&'static str),
|
||||||
Unexpected(&'static str),
|
Unexpected(&'static str),
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
@ -184,7 +182,10 @@ impl FullIdentifier {
|
||||||
impl Expression {
|
impl Expression {
|
||||||
fn parse_high(ctx: &mut ParserContext<'_>) -> Result<Self, Error> {
|
fn parse_high(ctx: &mut ParserContext<'_>) -> Result<Self, Error> {
|
||||||
let mut cfe = false;
|
let mut cfe = false;
|
||||||
for (_, i) in ctx.pklx.peeking_take_while(|(_, t)| t.is_cobj_attr()) {
|
for (_, i) in ctx
|
||||||
|
.pklx
|
||||||
|
.peeking_take_while(|(_, t)| matches!(t, Token::CtrlFlowEdit))
|
||||||
|
{
|
||||||
match i {
|
match i {
|
||||||
Token::CtrlFlowEdit => cfe = true,
|
Token::CtrlFlowEdit => cfe = true,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
|
@ -224,9 +225,12 @@ impl Expression {
|
||||||
loc,
|
loc,
|
||||||
kind: ErrorKind::Unexpected("braced statement set"),
|
kind: ErrorKind::Unexpected("braced statement set"),
|
||||||
}),
|
}),
|
||||||
// we have no proper recursive delimiting,
|
Some((_, Token::OpenParen)) => {
|
||||||
// so just resort to the parsing which we also do for other such items,
|
ctx.pklx.next();
|
||||||
// expect a single code object descriptor => alias, or number.
|
let inner = Expression::parse_high(ctx)?;
|
||||||
|
ctx.expect_token(Token::CloseParen, /* ( */ ")")?;
|
||||||
|
Ok(inner)
|
||||||
|
}
|
||||||
Some(&(_, Token::Integer(i))) => {
|
Some(&(_, Token::Integer(i))) => {
|
||||||
ctx.pklx.next();
|
ctx.pklx.next();
|
||||||
Ok(Expression::Integer(i))
|
Ok(Expression::Integer(i))
|
||||||
|
@ -238,31 +242,45 @@ impl Expression {
|
||||||
ctx.expect_token(Token::CloseBrace, "}")?;
|
ctx.expect_token(Token::CloseBrace, "}")?;
|
||||||
Ok(Expression::Module(m))
|
Ok(Expression::Module(m))
|
||||||
}
|
}
|
||||||
|
Some((_, Token::Tag)) => {
|
||||||
|
ctx.pklx.next();
|
||||||
|
Path::parse_high(ctx).map(Expression::Tag)
|
||||||
|
}
|
||||||
_ => FullIdentifier::parse_high(ctx).map(Expression::Alias),
|
_ => FullIdentifier::parse_high(ctx).map(Expression::Alias),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
Ok(if let Some(&(_, Token::Comma)) = ctx.pklx.peek() {
|
match ctx.pklx.peek() {
|
||||||
let mut args = BTreeMap::new();
|
None | Some((_, Token::SemiColon | Token::CloseBrace | Token::CloseParen)) => Ok(obj),
|
||||||
while ctx.maybe_eat_token(Token::Comma).is_some() {
|
Some((_, Token::Comma)) => {
|
||||||
let Path { loc, idents } = Path::parse_high(ctx)?;
|
let mut args = BTreeMap::new();
|
||||||
ctx.expect_token(Token::Assign, "=")?;
|
while ctx.maybe_eat_token(Token::Comma).is_some() {
|
||||||
let obj = Expression::parse_high(ctx)?;
|
let Path { loc, idents } = Path::parse_high(ctx)?;
|
||||||
if args.insert(idents, (loc, obj)).is_some() {
|
ctx.expect_token(Token::Assign, "=")?;
|
||||||
return Err(Error {
|
let obj = Expression::parse_high(ctx)?;
|
||||||
loc,
|
if args.insert(idents, (loc, obj)).is_some() {
|
||||||
kind: ErrorKind::DuplicateIdentifier,
|
return Err(Error {
|
||||||
});
|
loc,
|
||||||
|
kind: ErrorKind::DuplicateIdentifier,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Ok(Expression::InvocationMulti {
|
||||||
|
obj: Box::new(obj),
|
||||||
|
args,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Expression::InvocationMulti {
|
Some((_, Token::MatchPara)) => {
|
||||||
obj: Box::new(obj),
|
ctx.pklx.next();
|
||||||
args,
|
Ok(Expression::InvocationSingle(Box::new((
|
||||||
|
obj,
|
||||||
|
Expression::parse_high(ctx)?,
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
} else if matches!(ctx.pklx.peek(), Some(&(_, Token::SemiColon)) | None) {
|
_ => Err(Error {
|
||||||
obj
|
loc: ctx.peek_loc(),
|
||||||
} else {
|
kind: ErrorKind::Unexpected("end of expression"),
|
||||||
Expression::InvocationSingle(Box::new((obj, Expression::parse_high(ctx)?)))
|
}),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue