use std::mem;
use erg_common::config::ErgConfig;
use erg_common::error::Location;
use erg_common::io::{Input, InputKind};
use erg_common::set::Set as HashSet;
use erg_common::str::Str;
use erg_common::traits::{DequeStream, ExitStatus, Locational, Runnable, Stream};
use erg_common::{
caused_by, debug_power_assert, enum_unwrap, fn_name, impl_display_for_enum,
impl_locational_for_enum, log, set, switch_lang, switch_unreachable,
};
use crate::ast::*;
use crate::desugar::Desugarer;
use crate::error::{
CompleteArtifact, IncompleteArtifact, ParseError, ParseErrors, ParseResult, ParserRunnerError,
ParserRunnerErrors,
};
use crate::lex::Lexer;
use crate::token::{Token, TokenCategory, TokenKind, TokenStream};
use TokenCategory as TC;
use TokenKind::*;
#[macro_export]
macro_rules! debug_call_info {
($self: ident) => {
$self.level += 1;
log!(
c DEBUG_MAIN,
"\n{} ({}) entered {}, cur: {}",
"・".repeat(($self.level as f32 / 4.0).floor() as usize),
$self.level,
fn_name!(),
$self.peek().unwrap_or(&$crate::token::Token::DUMMY)
);
};
}
#[macro_export]
macro_rules! debug_exit_info {
($self: ident) => {
$self.level -= 1;
log!(
c DEBUG_MAIN,
"\n{} ({}) exit {}, cur: {}",
"・".repeat(($self.level as f32 / 4.0).floor() as usize),
$self.level,
fn_name!(),
$self.peek().unwrap_or(&$crate::token::Token::DUMMY)
);
};
}
macro_rules! expect_pop {
($self: ident, category $cate: expr) => {
if $self.cur_category_is($cate) {
$self.lpop()
} else {
let loc = $self.peek().map(|t| t.loc()).unwrap_or(Location::Unknown);
let got = $self.peek().map(|t| t.kind).unwrap_or(EOF);
let err = ParseError::unexpected_token(line!() as usize, loc, $cate, got);
$self.errs.push(err);
debug_exit_info!($self);
return Err(());
}
};
($self: ident, fail_next $kind: expr) => {
if $self.cur_is($kind) {
$self.lpop()
} else {
let loc = $self.peek().map(|t| t.loc()).unwrap_or(Location::Unknown);
let got = $self.peek().map(|t| t.kind).unwrap_or(EOF);
let err = ParseError::unexpected_token(line!() as usize, loc, $kind, got);
$self.next_line();
$self.errs.push(err);
debug_exit_info!($self);
return Err(());
}
};
($self: ident, $kind: expr) => {
if $self.cur_is($kind) {
$self.lpop()
} else {
let loc = $self.peek().map(|t| t.loc()).unwrap_or(Location::Unknown);
let got = $self.peek().map(|t| t.kind).unwrap_or(EOF);
let err = ParseError::unexpected_token(line!() as usize, loc, $kind, got);
$self.errs.push(err);
debug_exit_info!($self);
return Err(());
}
};
}
pub trait Parsable: 'static {
fn parse(code: String) -> Result<CompleteArtifact, IncompleteArtifact<Module, ParseErrors>>;
}
pub struct SimpleParser {}
impl Parsable for SimpleParser {
fn parse(code: String) -> Result<CompleteArtifact, IncompleteArtifact> {
let ts = Lexer::from_str(code).lex()?;
let mut parser = Parser::new(ts);
let mut desugarer = Desugarer::new();
let artifact = parser
.parse()
.map_err(|iart| iart.map_mod(|module| desugarer.desugar(module)))?;
Ok(artifact.map(|module| desugarer.desugar(module)))
}
}
enum ExprOrOp {
Expr(Expr),
Op(Token),
}
enum ArgKind {
Pos(PosArg),
Var(PosArg),
Kw(KwArg),
}
pub enum ArrayInner {
Normal(Args),
WithLength(PosArg, Expr),
Comprehension {
elem: PosArg,
generators: Vec<(Identifier, Expr)>,
guards: Vec<Expr>,
},
}
pub enum BraceContainer {
Set(Set),
Dict(Dict),
Record(Record),
}
impl_locational_for_enum!(BraceContainer; Set, Dict, Record);
impl_display_for_enum!(BraceContainer; Set, Dict, Record);
impl BraceContainer {
pub const fn kind(&self) -> &str {
match self {
BraceContainer::Set(_) => "Set",
BraceContainer::Dict(_) => "Dict",
BraceContainer::Record(_) => "Record",
}
}
}
pub enum ArgsStyle {
SingleCommaWithParen,
SingleCommaNoParen,
MultiComma, Colon, }
impl ArgsStyle {
pub const fn needs_parens(&self) -> bool {
match self {
Self::SingleCommaWithParen | Self::MultiComma => true,
Self::SingleCommaNoParen | Self::Colon => false,
}
}
pub const fn is_colon(&self) -> bool {
matches!(self, Self::Colon)
}
pub const fn is_multi_comma(&self) -> bool {
matches!(self, Self::MultiComma)
}
}
#[derive(Debug)]
pub struct Parser {
counter: DefId,
pub(super) level: usize, tokens: TokenStream,
warns: ParseErrors,
pub(crate) errs: ParseErrors,
}
impl Parser {
pub const fn new(ts: TokenStream) -> Self {
Self {
counter: DefId(0),
level: 0,
tokens: ts,
warns: ParseErrors::empty(),
errs: ParseErrors::empty(),
}
}
#[inline]
pub fn peek(&self) -> Option<&Token> {
self.tokens.first()
}
pub fn peek_kind(&self) -> Option<TokenKind> {
self.peek().map(|tok| tok.kind)
}
#[inline]
fn nth(&self, idx: usize) -> Option<&Token> {
self.tokens.get(idx)
}
#[inline]
fn skip(&mut self) {
self.tokens.pop_front();
}
#[inline]
fn lpop(&mut self) -> Token {
self.tokens.pop_front().unwrap()
}
fn cur_category_is(&self, category: TokenCategory) -> bool {
self.peek()
.map(|t| t.category_is(category))
.unwrap_or(false)
}
fn cur_is(&self, kind: TokenKind) -> bool {
self.peek().map(|t| t.is(kind)).unwrap_or(false)
}
fn nth_is(&self, idx: usize, kind: TokenKind) -> bool {
self.nth(idx).map(|t| t.is(kind)).unwrap_or(false)
}
fn next_expr(&mut self) {
while let Some(t) = self.peek() {
match t.category() {
TC::Separator | TC::DefOp | TC::LambdaOp => {
self.skip();
return;
}
TC::EOF => {
return;
}
_ => {
self.skip();
}
}
}
}
fn next_line(&mut self) {
while let Some(t) = self.peek() {
match t.kind {
Newline => {
self.skip();
return;
}
EOF => return,
_ => {
self.skip();
}
}
}
}
fn until_dedent(&mut self) {
let mut nest_cnt = 1;
while let Some(t) = self.peek() {
match t.kind {
Indent => {
self.skip();
nest_cnt += 1;
}
Dedent => {
self.skip();
nest_cnt -= 1;
if nest_cnt <= 0 {
return;
}
}
EOF => return,
_ => {
self.skip();
}
}
}
}
fn unexpected_none(&self, errno: u32, caused_by: &str) -> ParseError {
log!(err "error caused by: {caused_by}");
ParseError::invalid_none_match(0, Location::Unknown, file!(), errno)
}
fn skip_and_throw_syntax_err(&mut self, errno: u32, caused_by: &str) -> ParseError {
let loc = self.peek().map(|t| t.loc()).unwrap_or_default();
log!(err "error caused by: {caused_by}");
self.next_expr();
ParseError::simple_syntax_error(errno as usize, loc)
}
fn skip_and_throw_invalid_unclosed_err(
&mut self,
caused_by: &str,
line: u32,
closer: &str,
ty: &str,
) -> ParseError {
log!(err "error caused by: {caused_by}");
let loc = self.peek().map(|t| t.loc()).unwrap_or_default();
self.next_expr();
ParseError::unclosed_error(line as usize, loc, closer, ty)
}
fn skip_and_throw_invalid_seq_err<S: std::fmt::Display>(
&mut self,
caused_by: &str,
errno: usize,
expected: &[S],
found: TokenKind,
) -> ParseError {
log!(err "error caused by: {caused_by}");
let loc = self.peek().map(|t| t.loc()).unwrap_or_default();
self.next_expr();
ParseError::invalid_seq_elems_error(errno, loc, expected, found)
}
fn skip_and_throw_invalid_chunk_err(
&mut self,
caused_by: &str,
line: u32,
loc: Location,
) -> ParseError {
log!(err "error caused by: {caused_by}");
self.next_line();
ParseError::invalid_chunk_error(line as usize, loc)
}
fn get_stream_op_syntax_error(
&mut self,
errno: usize,
loc: Location,
caused_by: &str,
) -> ParseError {
log!(err "error caused by: {caused_by}");
self.next_expr();
ParseError::syntax_error(
errno,
loc,
switch_lang!(
"japanese" => "パイプ演算子の後には関数・メソッド・サブルーチンのみ呼び出しができます",
"simplified_chinese" => "流操作符后只能调用函数、方法或子程序",
"traditional_chinese" => "流操作符後只能調用函數、方法或子程序",
"english" => "Only a call of function, method or subroutine is available after stream operator",
),
None,
)
}
#[inline]
fn restore(&mut self, token: Token) {
self.tokens.push_front(token);
}
pub(crate) fn stack_dec(&mut self, fn_name: &str) {
self.level -= 1;
log!(
c DEBUG_MAIN,
"\n{} ({}) exit {}, cur: {}",
"・".repeat((self.level as f32 / 4.0).floor() as usize),
self.level,
fn_name,
self.peek().unwrap()
);
}
}
#[derive(Debug, Default)]
pub struct ParserRunner {
cfg: ErgConfig,
}
impl Runnable for ParserRunner {
type Err = ParserRunnerError;
type Errs = ParserRunnerErrors;
const NAME: &'static str = "Erg parser";
#[inline]
fn new(cfg: ErgConfig) -> Self {
Self { cfg }
}
#[inline]
fn cfg(&self) -> &ErgConfig {
&self.cfg
}
#[inline]
fn cfg_mut(&mut self) -> &mut ErgConfig {
&mut self.cfg
}
#[inline]
fn finish(&mut self) {}
#[inline]
fn initialize(&mut self) {}
#[inline]
fn clear(&mut self) {}
fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
let src = self.cfg_mut().input.read();
let artifact = self.parse(src).map_err(|iart| iart.errors)?;
println!("{}", artifact.ast);
Ok(ExitStatus::OK)
}
fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> {
let artifact = self.parse(src).map_err(|iart| iart.errors)?;
Ok(format!("{}", artifact.ast))
}
}
impl ParserRunner {
pub fn parse_token_stream(
&mut self,
ts: TokenStream,
) -> Result<CompleteArtifact, IncompleteArtifact<Module, ParserRunnerErrors>> {
Parser::new(ts)
.parse()
.map_err(|iart| iart.map_errs(|errs| ParserRunnerErrors::convert(self.input(), errs)))
}
pub fn parse(
&mut self,
src: String,
) -> Result<CompleteArtifact, IncompleteArtifact<Module, ParserRunnerErrors>> {
let ts = Lexer::new(Input::new(InputKind::Str(src), self.cfg.input.id()))
.lex()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
Parser::new(ts)
.parse()
.map_err(|iart| iart.map_errs(|errs| ParserRunnerErrors::convert(self.input(), errs)))
}
}
impl Parser {
pub fn parse(&mut self) -> Result<CompleteArtifact, IncompleteArtifact> {
if self.tokens.is_empty() {
return Ok(CompleteArtifact::new(Module::empty(), ParseErrors::empty()));
}
log!(info "the parsing process has started.");
log!(info "token stream: {}", self.tokens);
let module = match self.try_reduce_module() {
Ok(module) => module,
Err(_) => {
return Err(IncompleteArtifact::new(
None,
mem::take(&mut self.warns),
mem::take(&mut self.errs),
));
}
};
if !self.cur_is(EOF) {
let loc = self.peek().map(|t| t.loc()).unwrap_or_default();
self.errs
.push(ParseError::compiler_bug(0, loc, fn_name!(), line!()));
return Err(IncompleteArtifact::new(
Some(module),
mem::take(&mut self.warns),
mem::take(&mut self.errs),
));
}
log!(info "the parsing process has completed (errs: {}).", self.errs.len());
log!(info "AST:\n{module}");
if self.errs.is_empty() {
Ok(CompleteArtifact::new(module, mem::take(&mut self.warns)))
} else {
Err(IncompleteArtifact::new(
Some(module),
mem::take(&mut self.warns),
mem::take(&mut self.errs),
))
}
}
#[inline]
fn try_reduce_module(&mut self) -> ParseResult<Module> {
debug_call_info!(self);
let mut chunks = Module::empty();
loop {
match self.peek_kind() {
Some(Newline | Semi) => {
self.skip();
}
Some(EOF) => {
break;
}
Some(_) => {
if let Ok(expr) = self.try_reduce_chunk(true, false) {
if !self.cur_is(EOF) && !self.cur_category_is(TC::Separator) {
let err = self.skip_and_throw_invalid_chunk_err(
caused_by!(),
line!(),
expr.loc(),
);
self.errs.push(err);
}
chunks.push(expr);
}
}
None => {
if !self.errs.is_empty() {
debug_exit_info!(self);
self.errs.push(self.unexpected_none(line!(), caused_by!()));
return Err(());
} else {
switch_unreachable!()
}
}
}
}
debug_exit_info!(self);
Ok(chunks)
}
fn try_reduce_block(&mut self) -> ParseResult<Block> {
debug_call_info!(self);
let mut block = Block::with_capacity(2);
if !self.cur_is(Newline) {
let expr = self
.try_reduce_expr(true, false, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
block.push(expr);
if !self.cur_is(Dedent)
&& !self.cur_category_is(TC::Separator)
&& !self.cur_category_is(TC::REnclosure)
{
let err = self.skip_and_throw_invalid_chunk_err(
caused_by!(),
line!(),
block.last().unwrap().loc(),
);
debug_exit_info!(self);
self.errs.push(err);
}
if block.last().unwrap().is_definition() {
let err = ParseError::invalid_definition_of_last_block(
line!() as usize,
block.last().unwrap().loc(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
} else {
debug_exit_info!(self);
return Ok(block);
}
}
expect_pop!(self, Newline);
while self.cur_is(Newline) {
self.skip();
}
expect_pop!(self, Indent);
loop {
match self.peek_kind() {
Some(Newline) if self.nth_is(1, Dedent) => {
let nl = self.lpop();
self.skip();
self.restore(nl);
break;
}
Some(Dedent) => {
self.skip();
break;
}
Some(Newline | Semi) => {
self.skip();
}
Some(EOF) => {
break;
}
Some(_) => {
if let Ok(expr) = self.try_reduce_chunk(true, false) {
if !self.cur_is(Dedent) && !self.cur_category_is(TC::Separator) {
let err = self.skip_and_throw_invalid_chunk_err(
caused_by!(),
line!(),
expr.loc(),
);
debug_exit_info!(self);
self.errs.push(err);
}
block.push(expr);
}
}
None => {
let err =
ParseError::failed_to_analyze_block(line!() as usize, Location::Unknown);
self.errs.push(err);
break;
}
}
}
if block.is_empty() {
let loc = if let Some(u) = self.peek() {
u.loc()
} else {
Location::Unknown
};
let err = ParseError::failed_to_analyze_block(line!() as usize, loc);
self.errs.push(err);
debug_exit_info!(self);
Err(())
} else if block.last().unwrap().is_definition() {
let err =
ParseError::invalid_chunk_error(line!() as usize, block.last().unwrap().loc());
self.errs.push(err);
debug_exit_info!(self);
Err(())
} else {
debug_exit_info!(self);
Ok(block)
}
}
#[inline]
fn opt_reduce_decorator(&mut self) -> ParseResult<Option<Decorator>> {
debug_call_info!(self);
if self.cur_is(TokenKind::AtSign) {
self.lpop();
let expr = self
.try_reduce_expr(false, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: デコレータ",
"simplified_chinese" => "期望: 装饰器",
"traditional_chinese" => "期望: 裝飾器",
"english" => "expect: decorator",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(Some(Decorator::new(expr)))
} else {
debug_exit_info!(self);
Ok(None)
}
}
#[inline]
fn opt_reduce_decorators(&mut self) -> ParseResult<HashSet<Decorator>> {
debug_call_info!(self);
let mut decs = set![];
while let Some(deco) = self
.opt_reduce_decorator()
.map_err(|_| self.stack_dec(fn_name!()))?
{
decs.insert(deco);
expect_pop!(self, fail_next Newline);
}
debug_exit_info!(self);
Ok(decs)
}
fn try_reduce_type_app_args(&mut self) -> ParseResult<TypeAppArgs> {
debug_call_info!(self);
let l_vbar = expect_pop!(self, VBar);
let args = match self.peek_kind() {
Some(SubtypeOf) => {
let op = self.lpop();
let t_spec_as_expr =
self.try_reduce_expr(false, true, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 型指定",
"simplified_chinese" => "期望: 类型规范",
"traditional_chinese" => "期望: 類型規範",
"english" => "expect: type specification",
))
}
self.stack_dec(fn_name!())
})?;
match Parser::expr_to_type_spec(t_spec_as_expr.clone()) {
Ok(t_spec) => {
let t_spec = TypeSpecWithOp::new(op, t_spec, t_spec_as_expr);
TypeAppArgsKind::SubtypeOf(Box::new(t_spec))
}
Err(_) => {
let err = ParseError::simple_syntax_error(0, t_spec_as_expr.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
_ => {
let args = self
.try_reduce_args(true)
.map_err(|_| self.stack_dec(fn_name!()))?;
TypeAppArgsKind::Args(args)
}
};
let r_vbar = expect_pop!(self, VBar);
debug_exit_info!(self);
Ok(TypeAppArgs::new(l_vbar, args, r_vbar))
}
fn try_reduce_restriction(&mut self) -> ParseResult<VisRestriction> {
debug_call_info!(self);
expect_pop!(self, LSqBr);
let rest = match self.peek_kind() {
Some(SubtypeOf) => {
self.lpop();
let t_spec_as_expr = self
.try_reduce_expr(false, true, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
match Parser::expr_to_type_spec(t_spec_as_expr) {
Ok(t_spec) => VisRestriction::SubtypeOf(Box::new(t_spec)),
Err(err) => {
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
_ => {
let acc = self
.try_reduce_acc_lhs()
.map_err(|_| self.stack_dec(fn_name!()))?;
VisRestriction::Namespaces(Namespaces::new(vec![acc]))
}
};
expect_pop!(self, RSqBr);
debug_exit_info!(self);
Ok(rest)
}
fn try_reduce_acc_lhs(&mut self) -> ParseResult<Accessor> {
debug_call_info!(self);
let acc = match self.peek_kind() {
Some(Symbol | UBar) => Accessor::local(self.lpop()),
Some(Dot) => {
let dot = self.lpop();
let maybe_symbol = self.lpop();
if maybe_symbol.is(Symbol) {
Accessor::public(dot, maybe_symbol)
} else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
Some(DblColon) => {
let dbl_colon = self.lpop();
if let Some(LSqBr) = self.peek_kind() {
let rest = self
.try_reduce_restriction()
.map_err(|_| self.stack_dec(fn_name!()))?;
let symbol = expect_pop!(self, Symbol);
Accessor::restricted(rest, symbol)
} else {
let symbol = expect_pop!(self, Symbol);
Accessor::explicit_local(dbl_colon, symbol)
}
}
_ => {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
};
debug_exit_info!(self);
Ok(acc)
}
fn try_reduce_array_elems(&mut self) -> ParseResult<ArrayInner> {
debug_call_info!(self);
if self.cur_category_is(TC::REnclosure) {
let args = Args::empty();
debug_exit_info!(self);
return Ok(ArrayInner::Normal(args));
}
let first = self
.try_reduce_elem()
.map_err(|_| self.stack_dec(fn_name!()))?;
let mut elems = Args::single(first);
match self.peek_kind() {
Some(Semi) => {
self.lpop();
let len = self
.try_reduce_expr(false, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: Nat型",
"simplified_chinese" => "期望: Nat类型",
"traditional_chinese" => "期望: Nat類型",
"english" => "expect: Nat type",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
return Ok(ArrayInner::WithLength(elems.remove_pos(0), len));
}
Some(VBar) => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err =
ParseError::feature_error(line!() as usize, self.lpop().loc(), "comprehension");
self.lpop();
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(RParen | RSqBr | RBrace | Dedent | Comma) => {}
Some(_) => {
let elem = self
.try_reduce_elem()
.map_err(|_| self.stack_dec(fn_name!()))?;
elems.push_pos(elem);
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
loop {
match self.peek_kind() {
Some(Comma) => {
self.skip();
if self.cur_is(Comma) {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&["]", "element"],
Comma,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
elems.push_pos(
self.try_reduce_elem()
.map_err(|_| self.stack_dec(fn_name!()))?,
);
}
Some(RParen | RSqBr | RBrace | Dedent) => {
break;
}
Some(_other) => {
let err = self.skip_and_throw_invalid_unclosed_err(
caused_by!(),
line!(),
"]",
"array",
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
debug_exit_info!(self);
Ok(ArrayInner::Normal(elems))
}
fn try_reduce_elem(&mut self) -> ParseResult<PosArg> {
debug_call_info!(self);
match self.peek() {
Some(_) => {
let expr = self
.try_reduce_expr(false, false, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(PosArg::new(expr))
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
Err(())
}
}
}
fn opt_reduce_args(&mut self, in_type_args: bool) -> Option<ParseResult<Args>> {
debug_call_info!(self);
match self.peek() {
Some(t)
if t.category_is(TC::Literal)
|| t.is(StrInterpLeft)
|| t.is(Symbol)
|| t.category_is(TC::UnaryOp)
|| t.is(LParen)
|| t.is(LSqBr)
|| t.is(LBrace)
|| t.is(UBar) =>
{
Some(self.try_reduce_args(in_type_args))
}
Some(t)
if (t.is(Dot) || t.is(DblColon))
&& !self.nth_is(1, Newline)
&& !self.nth_is(1, LBrace) =>
{
Some(self.try_reduce_args(in_type_args))
}
_ => None,
}
}
fn try_reduce_args(&mut self, in_type_args: bool) -> ParseResult<Args> {
debug_call_info!(self);
let mut lp = None;
let rp;
if self.cur_is(LParen) {
lp = Some(self.lpop());
}
let mut style = if lp.is_some() {
ArgsStyle::SingleCommaWithParen
} else {
ArgsStyle::SingleCommaNoParen
};
match self.peek_kind() {
Some(RParen) => {
rp = Some(self.lpop());
debug_exit_info!(self);
return Ok(Args::pos_only(vec![], Some((lp.unwrap(), rp.unwrap()))));
}
Some(RBrace | RSqBr | Dedent) => {
debug_exit_info!(self);
return Ok(Args::empty());
}
Some(Newline) if style.needs_parens() => {
self.skip();
if self.cur_is(Indent) {
self.skip();
}
style = ArgsStyle::MultiComma;
}
_ => {}
}
let mut args = match self
.try_reduce_arg(in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?
{
ArgKind::Pos(arg) => Args::single(arg),
ArgKind::Var(arg) => Args::new(vec![], Some(arg), vec![], None),
ArgKind::Kw(arg) => Args::new(vec![], None, vec![arg], None),
};
loop {
match self.peek_kind() {
Some(Colon) if style.is_colon() || lp.is_some() => {
self.skip();
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(Colon) => {
self.skip();
style = ArgsStyle::Colon;
while self.cur_is(Newline) {
self.skip();
}
expect_pop!(self, fail_next Indent);
}
Some(Comma) => {
self.skip();
if style.is_colon() || self.cur_is(Comma) {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let loc = self.peek().map(|t| t.loc()).unwrap_or_default();
let err = ParseError::invalid_colon_style(line!() as usize, loc);
self.errs.push(err);
self.until_dedent();
debug_exit_info!(self);
return Err(());
}
if style.is_multi_comma() {
while self.cur_is(Newline) {
self.skip();
}
if self.cur_is(Dedent) {
self.skip();
}
}
if style.needs_parens() && self.cur_is(RParen) {
let rp = self.lpop();
args.set_parens((lp.unwrap(), rp));
break;
}
if !args.kw_is_empty() {
args.push_kw(
self.try_reduce_kw_arg(in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?,
);
} else {
match self
.try_reduce_arg(in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?
{
ArgKind::Pos(arg) => {
args.push_pos(arg);
}
ArgKind::Var(var) => {
args.set_var_args(var);
}
ArgKind::Kw(arg) => {
args.push_kw(arg);
}
}
}
}
Some(RParen) => {
if let Some(lp) = lp {
let rp = self.lpop();
args.set_parens((lp, rp));
} else {
let (pos_args, var_args, kw_args, _) = args.deconstruct();
args = Args::new(pos_args, var_args, kw_args, None);
}
break;
}
Some(Newline) => {
if !style.is_colon() {
if style.needs_parens() && !style.is_multi_comma() {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&[")"],
Newline,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
if style.is_multi_comma() {
self.skip();
while self.cur_is(Dedent) {
self.skip();
}
let rp = expect_pop!(self, fail_next RParen);
args.set_parens((lp.unwrap(), rp));
}
break;
}
let last = self.lpop();
if self.cur_is(Dedent) {
self.skip();
self.restore(last);
break;
}
}
Some(Dedent) if style.is_colon() => {
self.skip();
break;
}
Some(_) if style.is_colon() => {
if !args.kw_is_empty() {
args.push_kw(
self.try_reduce_kw_arg(in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?,
);
} else {
match self
.try_reduce_arg(in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?
{
ArgKind::Pos(arg) => {
args.push_pos(arg);
}
ArgKind::Var(var) => {
args.set_var_args(var);
}
ArgKind::Kw(arg) => {
args.push_kw(arg);
}
}
}
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
_ => break,
}
}
debug_exit_info!(self);
Ok(args)
}
fn try_reduce_arg(&mut self, in_type_args: bool) -> ParseResult<ArgKind> {
debug_call_info!(self);
match self.peek_kind() {
Some(Symbol) => {
if self.nth_is(1, Walrus) {
let acc = self
.try_reduce_acc_lhs()
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_power_assert!(self.cur_is(Walrus));
self.skip();
let kw = if let Accessor::Ident(n) = acc {
n.name.into_token()
} else {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_keyword(line!() as usize, acc.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
};
let expr = self
.try_reduce_expr(false, in_type_args, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: Nat型",
"simplified_chinese" => "期望: Nat类型",
"traditional_chinese" => "期望: Nat類型",
"english" => "expect: Nat type",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(ArgKind::Kw(KwArg::new(kw, None, expr)))
} else {
let expr = self
.try_reduce_expr(false, in_type_args, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 型指定",
"simplified_chinese" => "期望: 类型规范",
"traditional_chinese" => "期望: 類型規範",
"english" => "expect: type specification",
))
}
self.stack_dec(fn_name!())
})?;
if self.cur_is(Walrus) {
self.skip();
let (kw, t_spec) = match expr {
Expr::Accessor(Accessor::Ident(n)) => (n.name.into_token(), None),
Expr::TypeAscription(tasc) => {
if let Expr::Accessor(Accessor::Ident(n)) = *tasc.expr {
(n.name.into_token(), Some(tasc.t_spec))
} else {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&["right enclosure", "element"],
Comma,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
_ => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_keyword(line!() as usize, expr.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
};
let expr = self
.try_reduce_expr(false, in_type_args, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 型指定",
"simplified_chinese" => "期望: 类型规范",
"traditional_chinese" => "期望: 類型規範",
"english" => "expect: type specification",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(ArgKind::Kw(KwArg::new(kw, t_spec, expr)))
} else {
debug_exit_info!(self);
Ok(ArgKind::Pos(PosArg::new(expr)))
}
}
}
Some(PreStar) => {
self.skip();
let expr = self
.try_reduce_expr(false, in_type_args, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 型指定",
"simplified_chinese" => "期望: 类型规范",
"traditional_chinese" => "期望: 類型規範",
"english" => "expect: type specification",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(ArgKind::Var(PosArg::new(expr)))
}
Some(_) => {
let expr = self
.try_reduce_expr(false, in_type_args, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(ArgKind::Pos(PosArg::new(expr)))
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
Err(())
}
}
}
fn try_reduce_kw_arg(&mut self, in_type_args: bool) -> ParseResult<KwArg> {
debug_call_info!(self);
match self.peek() {
Some(t) if t.is(Symbol) => {
if self.nth_is(1, Walrus) {
let acc = self
.try_reduce_acc_lhs()
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_power_assert!(self.cur_is(Walrus));
self.skip();
let keyword = if let Accessor::Ident(n) = acc {
n.name.into_token()
} else {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_keyword(line!() as usize, acc.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
};
let expr = self
.try_reduce_expr(false, in_type_args, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 引数",
"simplified_chinese" => "期望: 参数",
"traditional_chinese" => "期望: 參數",
"english" => "expect: an argument",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(KwArg::new(keyword, None, expr))
} else if self.nth_is(1, Colon) {
let acc = self
.try_reduce_acc_lhs()
.map_err(|_| self.stack_dec(fn_name!()))?;
let colon = expect_pop!(self, Colon);
let t_spec_as_expr = self
.try_reduce_expr(false, true, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
let t_spec = match Parser::expr_to_type_spec(t_spec_as_expr.clone()) {
Ok(t_spec) => TypeSpecWithOp::new(colon, t_spec, t_spec_as_expr),
Err(err) => {
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
};
debug_power_assert!(self.cur_is(Walrus));
self.skip();
let keyword = if let Accessor::Ident(n) = acc {
n.name.into_token()
} else {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_keyword(line!() as usize, acc.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
};
let expr = self
.try_reduce_expr(false, in_type_args, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 引数",
"simplified_chinese" => "期望: 参数",
"traditional_chinese" => "期望: 參數",
"english" => "expect: an argument",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(KwArg::new(keyword, Some(t_spec), expr))
} else {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::invalid_non_default_parameter(line!() as usize, t.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
Err(())
}
}
Some(lit) if lit.category_is(TC::Literal) => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::invalid_non_default_parameter(line!() as usize, lit.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
Err(())
}
Some(other) => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_keyword(line!() as usize, other.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
Err(())
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
Err(())
}
}
}
fn try_reduce_class_attr_defs(
&mut self,
class: Expr,
vis: VisModifierSpec,
) -> ParseResult<Methods> {
debug_call_info!(self);
expect_pop!(self, fail_next Indent);
while self.cur_is(Newline) {
self.skip();
}
let first = self.try_reduce_chunk(false, false).map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "メソッドか属性のみ定義できます",
"simplified_chinese" => "只能定义方法或属性",
"traditional_chinese" => "只能定義方法或屬性",
"english" => "only a method or attribute can be defined",
))
}
self.stack_dec(fn_name!())
})?;
let first = match first {
Expr::Def(def) => ClassAttr::Def(def),
Expr::TypeAscription(tasc) => ClassAttr::Decl(tasc),
Expr::Literal(lit) if lit.is_doc_comment() => ClassAttr::Doc(lit),
other => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let hint = switch_lang!(
"japanese" => "メソッドか属性のみ定義できます",
"simplified_chinese" => "只能定义方法或属性",
"traditional_chinese" => "只能定義方法或屬性",
"english" => "only a method or attribute can be defined",
)
.to_string();
let err = ParseError::syntax_error(
line!() as usize,
other.loc(),
switch_lang!(
"japanese" => "クラス属性を定義するのに失敗しました",
"simplified_chinese" => "定义类属性失败",
"traditional_chinese" => "定義類屬性失敗",
"english" => "failed to define a class attribute",
),
Some(hint),
);
self.errs.push(err);
self.until_dedent();
debug_exit_info!(self);
return Err(());
}
};
let mut attrs = vec![first];
loop {
match self.peek() {
Some(t) if t.is(Newline) && self.nth_is(1, Dedent) => {
let nl = self.lpop();
self.skip();
self.restore(nl);
break;
}
Some(t) if t.is(Dedent) => {
self.skip();
break;
}
Some(t) if t.category_is(TC::Separator) => {
self.skip();
}
Some(_) => {
let def = self.try_reduce_chunk(false, false).map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "クラス属性かメソッドを定義してください",
"simplified_chinese" => "应声明类属性或方法",
"traditional_chinese" => "應聲明類屬性或方法",
"english" => "class attribute or method should be declared",
))
}
self.stack_dec(fn_name!())
})?;
match def {
Expr::Def(def) => {
attrs.push(ClassAttr::Def(def));
}
Expr::TypeAscription(tasc) => {
attrs.push(ClassAttr::Decl(tasc));
}
Expr::Literal(lit) if lit.is_doc_comment() => {
attrs.push(ClassAttr::Doc(lit));
}
other => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::syntax_error(
line!() as usize,
other.loc(),
switch_lang!(
"japanese" => "クラス属性を定義するのに失敗しました",
"simplified_chinese" => "定义类属性失败",
"traditional_chinese" => "定義類屬性失敗",
"english" => "failed to define a class attribute",
),
None,
);
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
}
match self.peek() {
Some(t) if !t.is(Dedent) && !t.category_is(TC::Separator) => {
let err = self.skip_and_throw_invalid_chunk_err(
caused_by!(),
line!(),
t.loc(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(_) => {}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
let attrs = ClassAttrs::from(attrs);
let t_spec = Self::expr_to_type_spec(class.clone()).map_err(|e| {
self.errs.push(e);
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(Methods::new(t_spec, class, vis, attrs))
}
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {
debug_call_info!(self);
let do_symbol = self.lpop();
let sig = LambdaSignature::do_sig(&do_symbol);
let op = match &do_symbol.inspect()[..] {
"do" => Token::from_str(FuncArrow, "->"),
"do!" => Token::from_str(ProcArrow, "=>"),
_ => unreachable!(),
};
if self.cur_is(Colon) {
self.lpop();
let body = self
.try_reduce_block()
.map_err(|_| self.stack_dec(fn_name!()))?;
self.counter.inc();
debug_exit_info!(self);
Ok(Lambda::new(sig, op, body, self.counter))
} else {
let expr = self
.try_reduce_expr(false, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 式",
"simplified_chinese" => "期望: 表达",
"traditional_chinese" => "期望: 表達",
"english" => "expect: expression",
))
}
self.stack_dec(fn_name!())
})?;
let block = Block::new(vec![expr]);
debug_exit_info!(self);
Ok(Lambda::new(sig, op, block, self.counter))
}
}
fn try_reduce_chunk(&mut self, winding: bool, in_brace: bool) -> ParseResult<Expr> {
debug_call_info!(self);
let mut stack = Vec::<ExprOrOp>::new();
stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs(false, in_brace)
.map_err(|_| self.stack_dec(fn_name!()))?,
));
loop {
match self.peek() {
Some(arg) if arg.is(Symbol) || arg.category_is(TC::Literal) => {
let args = self
.try_reduce_args(false)
.map_err(|_| self.stack_dec(fn_name!()))?;
let obj = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
stack.push(ExprOrOp::Expr(obj.call_expr(args)));
}
Some(op) if op.category_is(TC::DefOp) => {
let op = self.lpop();
let is_multiline_block = self.cur_is(Newline);
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let sig = self
.convert_rhs_to_sig(lhs)
.map_err(|_| self.stack_dec(fn_name!()))?;
self.counter.inc();
let block = if is_multiline_block {
self.try_reduce_block()
.map_err(|_| self.stack_dec(fn_name!()))?
} else {
let expr =
self.try_reduce_expr(true, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 式",
"simplified_chinese" => "期望: 表达",
"traditional_chinese" => "期望: 表達",
"english" => "expect: expression",
))
}
self.stack_dec(fn_name!())
})?;
Block::new(vec![expr])
};
let body = DefBody::new(op, block, self.counter);
debug_exit_info!(self);
return Ok(Expr::Def(Def::new(sig, body)));
}
Some(op) if op.category_is(TC::LambdaOp) => {
let op = self.lpop();
let is_multiline_block = self.cur_is(Newline);
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let sig = self
.convert_rhs_to_lambda_sig(lhs)
.map_err(|_| self.stack_dec(fn_name!()))?;
self.counter.inc();
let block = if is_multiline_block {
self.try_reduce_block()
.map_err(|_| self.stack_dec(fn_name!()))?
} else {
let expr =
self.try_reduce_expr(false, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 式",
"simplified_chinese" => "期望: 表达",
"traditional_chinese" => "期望: 表達",
"english" => "expect: expression",
))
}
self.stack_dec(fn_name!())
})?;
Block::new(vec![expr])
};
stack.push(ExprOrOp::Expr(Expr::Lambda(Lambda::new(
sig,
op,
block,
self.counter,
))));
}
Some(op)
if (op.is(Colon) && !self.nth_is(1, Newline))
|| (op.is(SubtypeOf) || op.is(SupertypeOf) || op.is(As)) =>
{
if in_brace {
while stack.len() >= 3 {
collect_last_binop_on_stack(&mut stack);
}
break;
}
let op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let t_spec_as_expr = self
.try_reduce_expr(false, false, false, false)
.map(Desugarer::desugar_simple_expr)
.map_err(|_| self.stack_dec(fn_name!()))?;
let t_spec = Self::expr_to_type_spec(t_spec_as_expr.clone()).map_err(|e| {
self.errs.push(e);
self.stack_dec(fn_name!())
})?;
let t_spec_op = TypeSpecWithOp::new(op, t_spec, t_spec_as_expr);
let expr = lhs.type_asc_expr(t_spec_op);
stack.push(ExprOrOp::Expr(expr));
}
Some(op) if op.category_is(TC::BinOp) => {
let op_prec = op.kind.precedence();
if stack.len() >= 2 {
while let Some(ExprOrOp::Op(prev_op)) = stack.get(stack.len() - 2) {
if prev_op.category_is(TC::BinOp)
&& prev_op.kind.precedence() >= op_prec
{
collect_last_binop_on_stack(&mut stack);
} else {
break;
}
if stack.len() <= 1 {
break;
}
}
}
stack.push(ExprOrOp::Op(self.lpop()));
stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs(false, in_brace).map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 数値、式",
"simplified_chinese" => "期望: 数字或表达式",
"traditional_chinese" => "期望: 數字或表達式",
"english" => "expect: number or expression",
));
}
self.stack_dec(fn_name!())
})?,
));
}
Some(t) if t.is(DblColon) => {
let vis = VisModifierSpec::ExplicitPrivate(self.lpop());
match self.lpop() {
symbol if symbol.is(Symbol) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
if let Some(args) = self
.opt_reduce_args(false)
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident =
Identifier::new(VisModifierSpec::Private, VarName::new(symbol));
let call = Call::new(obj, Some(ident), args);
stack.push(ExprOrOp::Expr(Expr::Call(call)));
} else {
let ident =
Identifier::new(VisModifierSpec::Private, VarName::new(symbol));
stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
}
}
line_break if line_break.is(Newline) => {
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let defs = self
.try_reduce_class_attr_defs(maybe_class, vis)
.map_err(|_| self.stack_dec(fn_name!()))?;
let expr = Expr::Methods(defs);
assert_eq!(stack.len(), 0);
debug_exit_info!(self);
return Ok(expr);
}
l_brace if l_brace.is(LBrace) => {
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
self.restore(l_brace);
let container = self
.try_reduce_brace_container()
.map_err(|_| self.stack_dec(fn_name!()))?;
match container {
BraceContainer::Record(args) => {
let pack = DataPack::new(maybe_class, vis, args);
stack.push(ExprOrOp::Expr(Expr::DataPack(pack)));
}
other => {
let err = ParseError::invalid_data_pack_definition(
line!() as usize,
other.loc(),
other.kind(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
other => {
self.restore(other);
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
Some(t) if t.is(Dot) => {
let dot = self.lpop();
match self.lpop() {
symbol if symbol.is(Symbol) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
if let Some(args) = self
.opt_reduce_args(false)
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident = Identifier::public_from_token(dot, symbol);
let call = Expr::Call(Call::new(obj, Some(ident), args));
stack.push(ExprOrOp::Expr(call));
} else {
let ident = Identifier::public_from_token(dot, symbol);
stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
}
}
line_break if line_break.is(Newline) => {
let vis = VisModifierSpec::Public(dot);
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let defs = self
.try_reduce_class_attr_defs(maybe_class, vis)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
return Ok(Expr::Methods(defs));
}
other => {
self.restore(other);
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
Some(t) if t.is(LSqBr) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
self.skip();
let index = self
.try_reduce_expr(false, false, in_brace, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: Nat型",
"simplified_chinese" => "期望: Nat类型",
"traditional_chinese" => "期望: Nat類型",
"english" => "expect: Nat type",
))
}
self.stack_dec(fn_name!())
})?;
let r_sqbr = expect_pop!(self, fail_next RSqBr);
let acc = Accessor::subscr(obj, index, r_sqbr);
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
}
Some(t) if t.is(Comma) && winding => {
let first_elem = ArgKind::Pos(PosArg::new(
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
));
let tup = self
.try_reduce_nonempty_tuple(first_elem, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
}
Some(t) if t.is(Walrus) && winding => {
let tuple = self
.try_reduce_default_parameters(&mut stack, in_brace)
.map_err(|_| self.stack_dec(fn_name!()))?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tuple)));
}
Some(t) if t.is(Pipe) => self
.try_reduce_stream_operator(&mut stack)
.map_err(|_| self.stack_dec(fn_name!()))?,
Some(t) if t.category_is(TC::Reserved) => {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
_ => {
if stack.len() <= 1 {
break;
}
else {
while stack.len() >= 3 {
collect_last_binop_on_stack(&mut stack);
}
}
}
}
}
match stack.pop() {
Some(ExprOrOp::Expr(expr)) if stack.is_empty() => {
debug_exit_info!(self);
Ok(expr)
}
Some(ExprOrOp::Expr(expr)) => {
let extra = stack.pop().unwrap();
let loc = match extra {
ExprOrOp::Expr(expr) => expr.loc(),
ExprOrOp::Op(op) => op.loc(),
};
self.warns
.push(ParseError::compiler_bug(0, loc, fn_name!(), line!()));
debug_exit_info!(self);
Ok(expr)
}
Some(ExprOrOp::Op(op)) => {
self.errs
.push(ParseError::compiler_bug(0, op.loc(), fn_name!(), line!()));
debug_exit_info!(self);
Err(())
}
_ => switch_unreachable!(),
}
}
fn try_reduce_expr(
&mut self,
winding: bool,
in_type_args: bool,
in_brace: bool,
line_break: bool,
) -> ParseResult<Expr> {
debug_call_info!(self);
let mut stack = Vec::<ExprOrOp>::new();
stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs(in_type_args, in_brace)
.map_err(|_| self.stack_dec(fn_name!()))?,
));
loop {
match self.peek() {
Some(op) if op.category_is(TC::LambdaOp) => {
let op = self.lpop();
let is_multiline_block = self.cur_is(Newline);
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let sig = self
.convert_rhs_to_lambda_sig(lhs)
.map_err(|_| self.stack_dec(fn_name!()))?;
self.counter.inc();
let block = if is_multiline_block {
self.try_reduce_block()
.map_err(|_| self.stack_dec(fn_name!()))?
} else {
let expr = self
.try_reduce_expr(false, false, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
Block::new(vec![expr])
};
stack.push(ExprOrOp::Expr(Expr::Lambda(Lambda::new(
sig,
op,
block,
self.counter,
))));
}
Some(op)
if (op.is(Colon) && !self.nth_is(1, Newline))
|| (op.is(SubtypeOf) || op.is(SupertypeOf) || op.is(As)) =>
{
if in_brace {
break;
}
let op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let t_spec_as_expr = self
.try_reduce_expr(false, in_type_args, in_brace, false)
.map(Desugarer::desugar_simple_expr)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: Nat型",
"simplified_chinese" => "期望: Nat类型",
"traditional_chinese" => "期望: Nat類型",
"english" => "expect: Nat type",
))
}
self.stack_dec(fn_name!())
})?;
let t_spec = Self::expr_to_type_spec(t_spec_as_expr.clone())
.map_err(|e| self.errs.push(e))?;
let t_spec_op = TypeSpecWithOp::new(op, t_spec, t_spec_as_expr);
let expr = lhs.type_asc_expr(t_spec_op);
stack.push(ExprOrOp::Expr(expr));
}
Some(op) if op.category_is(TC::BinOp) => {
let op_prec = op.kind.precedence();
if stack.len() >= 2 {
while let Some(ExprOrOp::Op(prev_op)) = stack.get(stack.len() - 2) {
if prev_op.category_is(TC::BinOp)
&& prev_op.kind.precedence() >= op_prec
{
let rhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let prev_op = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_)));
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let bin = BinOp::new(prev_op, lhs, rhs);
stack.push(ExprOrOp::Expr(Expr::BinOp(bin)));
} else {
break;
}
if stack.len() <= 1 {
break;
}
}
}
stack.push(ExprOrOp::Op(self.lpop()));
stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs(in_type_args, in_brace)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 式、被演算子",
"simplified_chinese" => "期望:表达式或操作数",
"traditional_chinese" => "期望:表達式或操作數",
"english" => "expect: expression or operand",
))
}
self.stack_dec(fn_name!())
})?,
));
}
Some(t) if t.is(Dot) => {
let vis = self.lpop();
match self.lpop() {
symbol if symbol.is(Symbol) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
if let Some(args) = self
.opt_reduce_args(in_type_args)
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident = Identifier::new(
VisModifierSpec::Public(vis),
VarName::new(symbol),
);
let call = Call::new(obj, Some(ident), args);
stack.push(ExprOrOp::Expr(Expr::Call(call)));
} else {
let ident = Identifier::new(
VisModifierSpec::Public(vis),
VarName::new(symbol),
);
stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
}
}
other => {
self.restore(other);
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
Some(t) if t.is(LSqBr) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
self.skip(); let index = self
.try_reduce_expr(false, false, in_brace, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: Nat型",
"simplified_chinese" => "期望: Nat类型",
"traditional_chinese" => "期望: Nat類型",
"english" => "expect: Nat type",
))
}
self.stack_dec(fn_name!());
})?;
let r_sqbr = self.lpop();
if !r_sqbr.is(RSqBr) {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_accessor(line!() as usize, index.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
let acc = Accessor::subscr(obj, index, r_sqbr);
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
}
Some(t) if t.is(Comma) && winding => {
let first_elem = ArgKind::Pos(PosArg::new(
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
));
let tup = self
.try_reduce_nonempty_tuple(first_elem, line_break)
.map_err(|_| self.stack_dec(fn_name!()))?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
}
Some(t) if t.is(Walrus) && winding => {
let tuple = self
.try_reduce_default_parameters(&mut stack, in_brace)
.map_err(|_| self.stack_dec(fn_name!()))?;
stack.push(ExprOrOp::Expr(Expr::Tuple(tuple)));
}
Some(t) if t.is(Pipe) => self
.try_reduce_stream_operator(&mut stack)
.map_err(|_| self.stack_dec(fn_name!()))?,
Some(t) if t.category_is(TC::Reserved) => {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
_ => {
if stack.len() <= 1 {
break;
}
else {
while stack.len() >= 3 {
collect_last_binop_on_stack(&mut stack);
}
}
}
}
}
match stack.pop() {
Some(ExprOrOp::Expr(expr)) if stack.is_empty() => {
debug_exit_info!(self);
Ok(expr)
}
Some(ExprOrOp::Expr(expr)) => {
let extra = stack.pop().unwrap();
let loc = match extra {
ExprOrOp::Expr(expr) => expr.loc(),
ExprOrOp::Op(op) => op.loc(),
};
self.warns
.push(ParseError::compiler_bug(0, loc, fn_name!(), line!()));
debug_exit_info!(self);
Ok(expr)
}
Some(ExprOrOp::Op(op)) => {
self.errs
.push(ParseError::compiler_bug(0, op.loc(), fn_name!(), line!()));
debug_exit_info!(self);
Err(())
}
_ => switch_unreachable!(),
}
}
#[inline]
fn try_reduce_default_parameters(
&mut self,
stack: &mut Vec<ExprOrOp>,
in_brace: bool,
) -> ParseResult<Tuple> {
debug_call_info!(self);
let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let (keyword, t_spec) = match first_elem {
Expr::Accessor(Accessor::Ident(ident)) => (ident.name.into_token(), None),
Expr::TypeAscription(tasc) => {
if let Expr::Accessor(Accessor::Ident(ident)) = *tasc.expr {
(ident.name.into_token(), Some(tasc.t_spec))
} else {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_keyword(line!() as usize, tasc.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
}
other => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_keyword(line!() as usize, other.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
};
self.skip(); let rhs = self
.try_reduce_expr(false, false, in_brace, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: デフォルト引数",
"simplified_chinese" => "期望: 默认参数",
"traditional_chinese" => "期望: 默認參數",
"english" => "expect: default parameter",
))
}
self.stack_dec(fn_name!())
})?;
let first_elem = ArgKind::Kw(KwArg::new(keyword, t_spec, rhs));
let tuple = self
.try_reduce_nonempty_tuple(first_elem, self.nth_is(1, Newline))
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(tuple)
}
fn try_reduce_bin_lhs(&mut self, in_type_args: bool, in_brace: bool) -> ParseResult<Expr> {
debug_call_info!(self);
match self.peek() {
Some(t) if &t.inspect()[..] == "do" || &t.inspect()[..] == "do!" => {
let lambda = self
.try_reduce_do_block()
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(Expr::Lambda(lambda))
}
Some(t) if t.category_is(TC::Literal) => {
let lit = self
.try_reduce_lit()
.map_err(|_| self.stack_dec(fn_name!()))?;
if let Some(tk) = self.peek() {
if tk.is(Mutate) {
self.skip();
let main_msg = switch_lang!(
"japanese" => "可変演算子は、後置演算子ではなく前置演算子です ",
"simplified_chinese" => "突变运算符是前缀运算符,不是后缀运算符",
"traditional_chinese" => "突變運算符是前綴運算符,不是後綴運算符",
"english" => "the mutation operator is a prefix operator, not a postfix operator ",
);
let lit_loc = lit.loc();
let lit = lit.token.inspect();
let err = ParseError::invalid_token_error(
line!() as usize,
lit_loc,
main_msg,
&format!("!{lit}"),
&format!("{lit}!"),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
debug_exit_info!(self);
Ok(Expr::Literal(lit))
}
Some(t) if t.is(StrInterpLeft) => {
let str_interp = self
.try_reduce_string_interpolation()
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(str_interp)
}
Some(t) if t.is(AtSign) => {
let decos = self.opt_reduce_decorators()?;
let expr = self.try_reduce_chunk(false, in_brace).map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "期待: デコレータ",
"simplified_chinese" => "期望: 装饰器",
"traditions_chinese" => "期望: 裝飾器",
"english" => "expect: decorator",
))
}
self.stack_dec(fn_name!())
})?;
let Expr::Def(mut def) = expr else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
match def.sig {
Signature::Subr(mut subr) => {
subr.decorators = decos;
let expr = Expr::Def(Def::new(Signature::Subr(subr), def.body));
debug_exit_info!(self);
Ok(expr)
}
Signature::Var(var) => {
let mut last = def.body.block.pop().unwrap();
for deco in decos.into_iter() {
last = deco.into_expr().call_expr(Args::single(PosArg::new(last)));
}
def.body.block.push(last);
let expr = Expr::Def(Def::new(Signature::Var(var), def.body));
debug_exit_info!(self);
Ok(expr)
}
}
}
Some(t) if t.is(Symbol) || t.is(Dot) || t.is(DblColon) || t.is(UBar) => {
let call_or_acc = self
.try_reduce_call_or_acc(in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(call_or_acc)
}
Some(t) if t.is(PreStar) => {
let _ = self.lpop();
let expr = self
.try_reduce_expr(false, in_type_args, in_brace, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "期待: 可変長引数",
"simplified_chinese" => "期望: 可变长度参数",
"traditional_chinese" => "期望: 可變長度參數",
"english" => "expect: variable-length arguments",
))
}
self.stack_dec(fn_name!())
})?;
let tuple = self
.try_reduce_nonempty_tuple(ArgKind::Var(PosArg::new(expr)), false)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(Expr::Tuple(tuple))
}
Some(t) if t.category_is(TC::UnaryOp) => {
let unaryop = self
.try_reduce_unary()
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(Expr::UnaryOp(unaryop))
}
Some(t) if t.is(LParen) => {
let lparen = self.lpop();
while self.cur_is(Newline) {
self.skip();
}
let line_break = if self.cur_is(Indent) {
self.skip();
true
} else {
false
};
if self.cur_is(RParen) {
let rparen = self.lpop();
let args = Args::pos_only(vec![], Some((lparen, rparen)));
let unit = Tuple::Normal(NormalTuple::new(args));
debug_exit_info!(self);
return Ok(Expr::Tuple(unit));
}
let mut expr = self
.try_reduce_expr(true, false, false, line_break)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "期待: 要素",
"simplified_chinese" => "期望: 元素",
"traditional_chinese" => "期望: 元素",
"english" => "expect: an element",
))
}
self.stack_dec(fn_name!())
})?;
if line_break {
while self.cur_is(Newline) {
self.skip();
}
if self.cur_is(Dedent) {
self.skip();
}
}
let rparen = match self.peek_kind() {
Some(RParen) => self.lpop(),
Some(_) => {
let err = self.skip_and_throw_invalid_unclosed_err(
caused_by!(),
line!(),
")",
"tuple",
);
self.errs.push(err);
return Err(());
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
};
if let Expr::Tuple(Tuple::Normal(tup)) = &mut expr {
tup.elems.paren = Some((lparen, rparen));
}
debug_exit_info!(self);
Ok(expr)
}
Some(t) if t.is(LSqBr) => {
let array = self
.try_reduce_array()
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(Expr::Array(array))
}
Some(t) if t.is(LBrace) => {
match self
.try_reduce_brace_container()
.map_err(|_| self.stack_dec(fn_name!()))?
{
BraceContainer::Dict(dic) => {
debug_exit_info!(self);
Ok(Expr::Dict(dic))
}
BraceContainer::Record(rec) => {
debug_exit_info!(self);
Ok(Expr::Record(rec))
}
BraceContainer::Set(set) => {
debug_exit_info!(self);
Ok(Expr::Set(set))
}
}
}
Some(t) if t.is(VBar) => {
let type_args = self
.try_reduce_type_app_args()
.map_err(|_| self.stack_dec(fn_name!()))?;
let bounds = self
.convert_type_args_to_bounds(type_args)
.map_err(|_| self.stack_dec(fn_name!()))?;
let args = self
.try_reduce_args(false)
.map_err(|_| self.stack_dec(fn_name!()))?;
let params = self
.convert_args_to_params(args)
.map_err(|_| self.stack_dec(fn_name!()))?;
let sig = LambdaSignature::new(params, None, bounds);
let op = expect_pop!(self, category TC::LambdaOp);
let block = self
.try_reduce_block()
.map_err(|_| self.stack_dec(fn_name!()))?;
self.counter.inc();
let lambda = Lambda::new(sig, op, block, self.counter);
debug_exit_info!(self);
Ok(Expr::Lambda(lambda))
}
Some(t) if t.is(UBar) => {
let token = self.lpop();
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
self.errs.push(ParseError::feature_error(
line!() as usize,
token.loc(),
"discard pattern",
));
debug_exit_info!(self);
Err(())
}
Some(_other) => {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
Err(())
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
Err(())
}
}
}
#[inline]
fn try_reduce_call_or_acc(&mut self, in_type_args: bool) -> ParseResult<Expr> {
debug_call_info!(self);
let acc = self
.try_reduce_acc_lhs()
.map_err(|_| self.stack_dec(fn_name!()))?;
let mut call_or_acc = self
.try_reduce_acc_chain(acc, in_type_args)
.map_err(|_| self.stack_dec(fn_name!()))?;
while let Some(res) = self.opt_reduce_args(in_type_args) {
let args = res.map_err(|_| self.stack_dec(fn_name!()))?;
let call = call_or_acc.call(args);
call_or_acc = Expr::Call(call);
}
debug_exit_info!(self);
Ok(call_or_acc)
}
#[inline]
fn try_reduce_acc_chain(&mut self, acc: Accessor, in_type_args: bool) -> ParseResult<Expr> {
debug_call_info!(self);
let mut obj = Expr::Accessor(acc);
loop {
match self.peek() {
Some(t) if t.is(LSqBr) && obj.col_end() == t.col_begin() => {
let _l_sqbr = self.lpop();
let index = self
.try_reduce_expr(true, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "期待: Nat型",
"simplified_chinese" => "期望: Nat类型",
"traditional_chinese" => "期望: Nat類型",
"english" => "expect: Nat type",
))
}
self.stack_dec(fn_name!())
})?;
let r_sqbr = expect_pop!(self, fail_next RSqBr);
obj = Expr::Accessor(Accessor::subscr(obj, index, r_sqbr));
}
Some(t) if t.is(Dot) && obj.col_end() == t.col_begin() => {
let vis = self.lpop();
let token = self.lpop();
match token.kind {
Symbol => {
let ident =
Identifier::new(VisModifierSpec::Public(vis), VarName::new(token));
obj = obj.attr_expr(ident);
}
NatLit => {
let index = Literal::from(token);
obj = obj.tuple_attr_expr(index);
}
Newline => {
self.restore(token);
self.restore(vis);
break;
}
_ => {
let err = ParseError::invalid_acc_chain(
line!() as usize,
token.loc(),
&token.inspect()[..],
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
Some(t) if t.is(RatioLit) && obj.col_end() == t.col_begin() => {
let mut token = self.lpop();
token.content = Str::rc(&token.content[1..]);
token.kind = NatLit;
token.col_begin += 1;
obj = obj.tuple_attr_expr(Literal::from(token));
}
Some(t) if t.is(DblColon) && obj.col_end() == t.col_begin() => {
let vis = self.lpop();
let token = self.lpop();
match token.kind {
Symbol => {
let ident = Identifier::new(
VisModifierSpec::ExplicitPrivate(vis),
VarName::new(token),
);
obj = obj.attr_expr(ident);
}
LBrace => {
self.restore(token);
let args = self
.try_reduce_brace_container()
.map_err(|_| self.stack_dec(fn_name!()))?;
match args {
BraceContainer::Record(args) => {
let vis = VisModifierSpec::ExplicitPrivate(vis);
obj = Expr::DataPack(DataPack::new(obj, vis, args));
}
other => {
let err = ParseError::invalid_data_pack_definition(
line!() as usize,
other.loc(),
other.kind(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
Newline => {
self.restore(token);
self.restore(vis);
break;
}
_ => {
self.restore(token);
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
Some(t) if t.is(LParen) && obj.col_end() == t.col_begin() => {
let args = self
.try_reduce_args(false)
.map_err(|_| self.stack_dec(fn_name!()))?;
let (receiver, attr_name) = match obj {
Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
other => (other, None),
};
let call = Call::new(receiver, attr_name, args);
obj = Expr::Call(call);
}
Some(t) if t.is(VBar) && !in_type_args => {
let type_args = self
.try_reduce_type_app_args()
.map_err(|_| self.stack_dec(fn_name!()))?;
obj = Expr::Accessor(Accessor::TypeApp(TypeApp::new(obj, type_args)));
}
_ => {
break;
}
}
}
debug_exit_info!(self);
Ok(obj)
}
#[inline]
fn try_reduce_unary(&mut self) -> ParseResult<UnaryOp> {
debug_call_info!(self);
let op = self.lpop();
let expr = self
.try_reduce_expr(false, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 式",
"simplified_chinese" => "期待:表达式",
"traditional_chinese" => "期待:表達式",
"english" => "expect: expression",
))
}
self.stack_dec(fn_name!())
})?;
debug_exit_info!(self);
Ok(UnaryOp::new(op, expr))
}
#[inline]
fn try_reduce_array(&mut self) -> ParseResult<Array> {
debug_call_info!(self);
let l_sqbr = expect_pop!(self, fail_next LSqBr);
let inner = self
.try_reduce_array_elems()
.map_err(|_| self.stack_dec(fn_name!()))?;
let r_sqbr = expect_pop!(self, fail_next RSqBr);
let arr = match inner {
ArrayInner::Normal(mut elems) => {
let elems = if elems
.pos_args()
.get(0)
.map(|pos| match &pos.expr {
Expr::Tuple(tup) => tup.paren().is_none(),
_ => false,
})
.unwrap_or(false)
{
enum_unwrap!(elems.remove_pos(0).expr, Expr::Tuple:(Tuple::Normal:(_))).elems
} else {
elems
};
Array::Normal(NormalArray::new(l_sqbr, r_sqbr, elems))
}
ArrayInner::WithLength(elem, len) => {
Array::WithLength(ArrayWithLength::new(l_sqbr, r_sqbr, elem, len))
}
ArrayInner::Comprehension { .. } => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
self.errs.push(ParseError::feature_error(
line!() as usize,
Location::concat(&l_sqbr, &r_sqbr),
"array comprehension",
));
debug_exit_info!(self);
return Err(());
}
};
debug_exit_info!(self);
Ok(arr)
}
fn try_reduce_brace_container(&mut self) -> ParseResult<BraceContainer> {
debug_call_info!(self);
let l_brace = expect_pop!(self, fail_next LBrace);
if self.cur_is(Newline) {
self.skip();
expect_pop!(self, fail_next Indent);
}
match self.peek_kind() {
Some(RBrace) => {
let r_brace = self.lpop();
let arg = Args::empty();
let set = NormalSet::new(l_brace, r_brace, arg);
debug_exit_info!(self);
return Ok(BraceContainer::Set(Set::Normal(set)));
}
Some(Assign) => {
let _eq = self.lpop();
if let Some(t) = self.peek() {
if t.is(RBrace) {
let r_brace = self.lpop();
debug_exit_info!(self);
return Ok(BraceContainer::Record(Record::empty(l_brace, r_brace)));
}
} else {
let caused_by = caused_by!();
let err = self.unexpected_none(line!(), caused_by);
self.errs.push(err);
return Err(());
}
let t = self.lpop();
let mut err = ParseError::invalid_token_error(
line!() as usize,
t.loc(),
switch_lang!(
"japanese" => "無効なレコードの宣言です",
"simplified_chinese" => "无效的Record定义",
"traditional_chinese" => "無效的Record定義",
"english" => "invalid record",
),
"}",
&t.inspect()[..],
);
err.set_hint(switch_lang!(
"japanese" => "空のレコードが期待されています: {=}",
"simplified_chinese" => "期望空Record: {=}",
"traditional_chinese" => "期望空Record: {=}",
"english" => "expect empty record: {=}",
));
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(Colon) => {
let _colon = self.lpop();
if let Some(t) = self.peek() {
if t.is(RBrace) {
let r_brace = self.lpop();
let dict = NormalDict::new(l_brace, r_brace, vec![]);
debug_exit_info!(self);
return Ok(BraceContainer::Dict(Dict::Normal(dict)));
}
} else {
let caused_by = caused_by!();
let err = self.unexpected_none(line!(), caused_by);
self.errs.push(err);
return Err(());
}
let t = self.lpop();
let mut err = ParseError::invalid_token_error(
line!() as usize,
t.loc(),
switch_lang!(
"japanese" => "無効な辞書の宣言です",
"simplified_chinese" => "无效的字典定义",
"traditional_chinese" => "無效的字典定義",
"english" => "invalid dict",
),
"}",
&t.inspect()[..],
);
err.set_hint(switch_lang!(
"japanese" => "空の辞書が期待されています: {:}",
"simplified_chinese" => "期望空字典: {:}",
"traditional_chinese" => "期望空字典: {:}",
"english" => "expect empty dict: {:}",
));
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
_ => {}
}
let first = self.try_reduce_chunk(false, true).map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "期待: 要素",
"simplified_chinese" => "期望: 元素",
"traditional_chinese" => "期望: 元素",
"english" => "expect: an element",
))
}
self.stack_dec(fn_name!())
})?;
match first {
Expr::Def(def) => {
let attr = RecordAttrOrIdent::Attr(def);
let record = self
.try_reduce_record(l_brace, attr)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(BraceContainer::Record(record))
}
Expr::Accessor(acc)
if self.cur_is(Semi)
&& !self.nth_is(1, TokenKind::NatLit)
&& !self.nth_is(1, UBar) =>
{
let ident = match acc {
Accessor::Ident(ident) => ident,
other => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err =
ParseError::invalid_record_element_err(line!() as usize, other.loc());
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
};
let attr = RecordAttrOrIdent::Ident(ident);
let record = self
.try_reduce_record(l_brace, attr)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(BraceContainer::Record(record))
}
other if self.cur_is(Colon) => {
let res = self
.try_reduce_normal_dict_or_set_comp(l_brace, other)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(res)
}
other => {
match self.peek() {
Some(r_brace) if r_brace.is(RBrace) => {
let arg = Args::new(vec![PosArg::new(other)], None, vec![], None);
let r_brace = self.lpop();
return Ok(BraceContainer::Set(Set::Normal(NormalSet::new(
l_brace, r_brace, arg,
))));
}
_ => {}
}
let set = self
.try_reduce_set(l_brace, other)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(BraceContainer::Set(set))
}
}
}
fn try_reduce_record(
&mut self,
l_brace: Token,
first_attr: RecordAttrOrIdent,
) -> ParseResult<Record> {
debug_call_info!(self);
let mut attrs = vec![first_attr];
loop {
match self.peek_kind() {
Some(Newline | Semi) => {
self.skip();
match self.peek() {
Some(t) if t.is(Semi) => {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&["}", "element"],
Semi,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(_) => {}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
Some(Dedent) => {
self.skip();
let r_brace = expect_pop!(self, fail_next RBrace);
debug_exit_info!(self);
return Ok(Record::new_mixed(l_brace, r_brace, attrs));
}
Some(RBrace) => {
let r_brace = self.lpop();
debug_exit_info!(self);
return Ok(Record::new_mixed(l_brace, r_brace, attrs));
}
Some(_) => {
let next = self.try_reduce_chunk(false, false).map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: 属性",
"simplified_chinese" => "期望: 属性",
"traditional_chinese" => "期望: 屬性",
"english" => "expect: an attribute",
))
}
self.stack_dec(fn_name!())
})?;
match next {
Expr::Def(def) => {
if attrs.iter().any(|attr| {
attr.ident()
.zip(def.sig.ident())
.is_some_and(|(l, r)| l == r)
}) {
self.warns.push(ParseError::duplicate_elem_warning(
line!() as usize,
def.sig.loc(),
def.sig.to_string(),
));
}
attrs.push(RecordAttrOrIdent::Attr(def));
}
Expr::Accessor(acc) => {
let ident = match acc {
Accessor::Ident(ident) => ident,
other => {
let err = ParseError::invalid_record_element_err(
line!() as usize,
other.loc(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
};
attrs.push(RecordAttrOrIdent::Ident(ident));
}
other => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::invalid_record_element_err(
line!() as usize,
other.loc(),
);
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
}
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
}
fn try_reduce_normal_dict_or_set_comp(
&mut self,
l_brace: Token,
lhs: Expr,
) -> ParseResult<BraceContainer> {
debug_call_info!(self);
let colon = expect_pop!(self, fail_next Colon);
let rhs = self
.try_reduce_expr(false, true, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
if self.cur_is(VBar) {
self.skip();
let Expr::Accessor(Accessor::Ident(var)) = lhs else {
let err = ParseError::simple_syntax_error(line!() as usize, lhs.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
let pred = self
.try_reduce_chunk(false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
let r_brace = expect_pop!(self, fail_next RBrace);
let set_comp =
SetComprehension::new(l_brace, r_brace, var.name.into_token(), colon, rhs, pred);
debug_exit_info!(self);
Ok(BraceContainer::Set(Set::Comprehension(set_comp)))
} else {
let dict = self
.try_reduce_normal_dict(l_brace, lhs, rhs)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(BraceContainer::Dict(Dict::Normal(dict)))
}
}
fn try_reduce_normal_dict(
&mut self,
l_brace: Token,
first_key: Expr,
value: Expr,
) -> ParseResult<NormalDict> {
debug_call_info!(self);
let mut kvs = vec![KeyValue::new(first_key, value)];
loop {
match self.peek_kind() {
Some(Comma) => {
self.skip();
match self.peek_kind() {
Some(Comma) => {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&["}", "element"],
Comma,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(RBrace) => {
let dict = NormalDict::new(l_brace, self.lpop(), kvs);
debug_exit_info!(self);
return Ok(dict);
}
Some(Newline) => {
self.skip();
}
_ => {}
}
let key = self
.try_reduce_expr(false, false, true, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
expect_pop!(self, fail_next Colon);
let value = self.try_reduce_chunk(false, false).map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: キー",
"simplified_chinese" => "期望: 关键",
"traditional_chinese" => "期望: 關鍵",
"english" => "expect: key",
))
}
self.stack_dec(fn_name!())
})?;
kvs.push(KeyValue::new(key, value));
}
Some(Newline | Indent | Dedent) => {
self.skip();
}
Some(RBrace) => {
let dict = NormalDict::new(l_brace, self.lpop(), kvs);
debug_exit_info!(self);
return Ok(dict);
}
Some(_) => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::unclosed_error(
line!() as usize,
self.lpop().loc(),
"}",
"dict",
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
_ => break,
}
}
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
debug_exit_info!(self);
Err(())
}
fn try_reduce_set(&mut self, l_brace: Token, first_elem: Expr) -> ParseResult<Set> {
debug_call_info!(self);
if self.cur_is(Semi) {
match first_elem {
Expr::Accessor(_) => {}
other => {
let err = ParseError::expect_type_specified(line!() as usize, other.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
self.skip();
let len = self
.try_reduce_expr(false, false, false, false)
.map_err(|_| {
if let Some(err) = self.errs.last_mut() {
err.set_hint(switch_lang!(
"japanese" => "予期: }か要素",
"simplified_chinese" => "期望: }或元素",
"traditional_chinese" => "期望: }或元素",
"english" => "expect: } or element",
))
}
self.stack_dec(fn_name!())
})?;
let r_brace = self.lpop();
if !r_brace.is(RBrace) {
let err = self.skip_and_throw_invalid_unclosed_err(
caused_by!(),
line!(),
"}",
"set type specification",
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
return Ok(Set::WithLength(SetWithLength::new(
l_brace,
r_brace,
PosArg::new(first_elem),
len,
)));
}
let mut args = Args::single(PosArg::new(first_elem));
loop {
match self.peek_kind() {
Some(Comma) => {
self.skip();
match self.peek_kind() {
Some(Comma) => {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&["}", "element"],
Comma,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(RBrace) => {
let set = Set::Normal(NormalSet::new(l_brace, self.lpop(), args));
debug_exit_info!(self);
return Ok(set);
}
Some(Newline | Indent | Dedent) => {
self.skip();
}
_ => {}
}
match self
.try_reduce_arg(false)
.map_err(|_| self.stack_dec(fn_name!()))?
{
ArgKind::Pos(arg) => match arg.expr {
Expr::Set(Set::Normal(set)) if set.elems.paren.is_none() => {
args.extend_pos(set.elems.into_iters().0);
}
other => {
let pos = PosArg::new(other);
if !args.has_pos_arg(&pos) {
args.push_pos(pos);
}
}
},
ArgKind::Var(var) => {
let err = ParseError::simple_syntax_error(line!() as usize, var.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
ArgKind::Kw(arg) => {
let err = ParseError::simple_syntax_error(line!() as usize, arg.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
}
Some(Newline | Indent | Dedent) => {
self.skip();
}
Some(RBrace) => {
let set = Set::Normal(NormalSet::new(l_brace, self.lpop(), args));
debug_exit_info!(self);
return Ok(set);
}
Some(other) => {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&["}", "element"],
other,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
}
fn try_reduce_nonempty_tuple(
&mut self,
first_elem: ArgKind,
line_break: bool,
) -> ParseResult<Tuple> {
debug_call_info!(self);
let mut args = match first_elem {
ArgKind::Pos(pos) => Args::single(pos),
ArgKind::Var(var) => Args::new(vec![], Some(var), vec![], None),
ArgKind::Kw(kw) => Args::new(vec![], None, vec![kw], None),
};
#[allow(clippy::while_let_loop)]
loop {
match self.peek_kind() {
Some(Comma) => {
self.skip();
while self.cur_is(Newline) && line_break {
self.skip();
}
if self.cur_is(Comma) {
let err = self.skip_and_throw_invalid_seq_err(
caused_by!(),
line!() as usize,
&[")", "element"],
Comma,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
} else if self.cur_is(Dedent) || self.cur_is(RParen) {
break;
}
match self
.try_reduce_arg(false)
.map_err(|_| self.stack_dec(fn_name!()))?
{
ArgKind::Pos(arg) if args.kw_is_empty() && args.var_args.is_none() => {
match arg.expr {
Expr::Tuple(Tuple::Normal(tup)) if tup.elems.paren.is_none() => {
args.extend_pos(tup.elems.into_iters().0);
}
other => {
args.push_pos(PosArg::new(other));
}
}
}
ArgKind::Var(var) => {
args.set_var_args(var);
}
ArgKind::Pos(arg) => {
let err = ParseError::syntax_error(
line!() as usize,
arg.loc(),
switch_lang!(
"japanese" => "非デフォルト引数はデフォルト引数の後に指定できません",
"simplified_chinese" => "不能在默认参数之后指定非默认参数",
"traditional_chinese" => "不能在默認參數之後指定非默認參數",
"english" => "Non-default arguments cannot be specified after default arguments",
),
None,
);
self.errs.push(err);
self.next_expr();
debug_exit_info!(self);
return Err(());
}
ArgKind::Kw(arg) => {
args.push_kw(arg);
}
}
}
Some(_other) => {
break;
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
let tup = Tuple::Normal(NormalTuple::new(args));
debug_exit_info!(self);
Ok(tup)
}
#[inline]
fn try_reduce_lit(&mut self) -> ParseResult<Literal> {
debug_call_info!(self);
match self.peek() {
Some(t) if t.category_is(TC::Literal) => Ok(Literal::from(self.lpop())),
Some(other) => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::unexpected_token_error(
line!() as usize,
other.loc(),
&other.inspect()[..],
);
self.errs.push(err);
debug_exit_info!(self);
Err(())
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
Err(())
}
}
}
fn try_reduce_string_interpolation(&mut self) -> ParseResult<Expr> {
debug_call_info!(self);
let mut left = self.lpop();
left.content = Str::from(left.content.trim_end_matches("\\{").to_string() + "\"");
left.kind = StrLit;
let mut expr = Expr::Literal(Literal::from(left));
loop {
match self.peek() {
Some(l) if l.is(StrInterpRight) => {
let mut right = self.lpop();
right.content =
Str::from(format!("\"{}", right.content.trim_start_matches('}')));
right.kind = StrLit;
let right = Expr::Literal(Literal::from(right));
let op = Token::new(
Plus,
"+",
right.ln_begin().unwrap(),
right.col_begin().unwrap(),
);
expr = Expr::BinOp(BinOp::new(op, expr, right));
debug_exit_info!(self);
return Ok(expr);
}
Some(t) if t.is(EOF) => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::syntax_error(
line!() as usize,
expr.loc(),
switch_lang!(
"japanese" => "文字列補間の終わりが見つかりませんでした",
"simplified_chinese" => "未找到字符串的结束插值",
"traditional_chinese" => "未找到字符串的結束插值",
"english" => "end of a string interpolation not found",
),
None,
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
Some(_) => {
let mid_expr = self
.try_reduce_expr(true, false, false, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
let str_func = Expr::local(
"str",
mid_expr.ln_begin().unwrap(),
mid_expr.col_begin().unwrap(),
);
let call = Call::new(str_func, None, Args::single(PosArg::new(mid_expr)));
let op = Token::new(
Plus,
"+",
call.ln_begin().unwrap(),
call.col_begin().unwrap(),
);
let bin = BinOp::new(op, expr, Expr::Call(call));
expr = Expr::BinOp(bin);
if self.cur_is(StrInterpMid) {
let mut mid = self.lpop();
mid.content = Str::from(format!(
"\"{}\"",
mid.content.trim_start_matches('}').trim_end_matches("\\{")
));
mid.kind = StrLit;
let mid = Expr::Literal(Literal::from(mid));
let op = Token::new(
Plus,
"+",
mid.ln_begin().unwrap(),
mid.col_begin().unwrap(),
);
expr = Expr::BinOp(BinOp::new(op, expr, mid));
}
}
None => {
self.errs.push(self.unexpected_none(line!(), caused_by!()));
debug_exit_info!(self);
return Err(());
}
}
}
}
fn try_reduce_stream_operator(&mut self, stack: &mut Vec<ExprOrOp>) -> ParseResult<()> {
debug_call_info!(self);
let op = self.lpop();
while stack.len() >= 3 {
collect_last_binop_on_stack(stack);
}
if stack.len() == 2 {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::compiler_bug(0, op.loc(), fn_name!(), line!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
if matches!(self.peek_kind(), Some(Dot)) {
let vis = self.lpop();
match self.lpop() {
symbol if symbol.is(Symbol) => {
let Some(ExprOrOp::Expr(obj)) = stack.pop() else {
let err = self.skip_and_throw_syntax_err(line!(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
if let Some(args) = self
.opt_reduce_args(false)
.transpose()
.map_err(|_| self.stack_dec(fn_name!()))?
{
let ident =
Identifier::new(VisModifierSpec::Public(vis), VarName::new(symbol));
let mut call = Expr::Call(Call::new(obj, Some(ident), args));
while let Some(res) = self.opt_reduce_args(false) {
let args = res.map_err(|_| self.stack_dec(fn_name!()))?;
call = call.call_expr(args);
}
stack.push(ExprOrOp::Expr(call));
} else {
let err = self.get_stream_op_syntax_error(
line!() as usize,
obj.loc(),
caused_by!(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
other => {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = ParseError::expect_method_error(line!() as usize, other.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}
} else {
let expect_call = self
.try_reduce_call_or_acc(false)
.map_err(|_| self.stack_dec(fn_name!()))?;
let Expr::Call(mut call) = expect_call else {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
let err = self.get_stream_op_syntax_error(line!() as usize, expect_call.loc(), caused_by!());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
};
let ExprOrOp::Expr(first_arg) = stack.pop().unwrap() else {
let caused_by = caused_by!();
log!(err "error caused by: {caused_by}");
self.errs
.push(ParseError::compiler_bug(line!() as usize, call.loc(), fn_name!(), line!()));
debug_exit_info!(self);
return Err(());
};
call.args.insert_pos(0, PosArg::new(first_arg));
stack.push(ExprOrOp::Expr(Expr::Call(call)));
}
debug_exit_info!(self);
Ok(())
}
}
fn collect_last_binop_on_stack(stack: &mut Vec<ExprOrOp>) {
let rhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let op = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_)));
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let bin = BinOp::new(op, lhs, rhs);
stack.push(ExprOrOp::Expr(Expr::BinOp(bin)));
}