mirror of
https://github.com/erg-lang/erg.git
synced 2025-12-23 05:36:48 +00:00
Update Parser
This commit is contained in:
parent
aa2aa79de9
commit
424f82cf9e
4 changed files with 151 additions and 60 deletions
|
|
@ -2138,10 +2138,55 @@ impl ParamTuplePattern {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ParamRecordAttr {
|
||||
pub lhs: Identifier,
|
||||
pub rhs: ParamSignature,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ParamRecordAttr {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "{} = {}", self.lhs, self.rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ParamRecordAttr);
|
||||
impl_locational!(ParamRecordAttr, lhs, rhs);
|
||||
|
||||
impl ParamRecordAttr {
|
||||
pub const fn new(lhs: Identifier, rhs: ParamSignature) -> Self {
|
||||
Self { lhs, rhs }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ParamRecordAttrs {
|
||||
pub(crate) elems: Vec<ParamRecordAttr>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ParamRecordAttrs {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "{}", fmt_vec_split_with(&self.elems, "; "))
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ParamRecordAttrs);
|
||||
impl_stream!(ParamRecordAttrs, ParamRecordAttr, elems);
|
||||
|
||||
impl ParamRecordAttrs {
|
||||
pub const fn new(elems: Vec<ParamRecordAttr>) -> Self {
|
||||
Self { elems }
|
||||
}
|
||||
|
||||
pub const fn empty() -> Self {
|
||||
Self::new(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ParamRecordPattern {
|
||||
l_brace: Token,
|
||||
pub(crate) elems: Params,
|
||||
pub(crate) elems: ParamRecordAttrs,
|
||||
r_brace: Token,
|
||||
}
|
||||
|
||||
|
|
@ -2155,7 +2200,7 @@ impl_display_from_nested!(ParamRecordPattern);
|
|||
impl_locational!(ParamRecordPattern, l_brace, r_brace);
|
||||
|
||||
impl ParamRecordPattern {
|
||||
pub const fn new(l_brace: Token, elems: Params, r_brace: Token) -> Self {
|
||||
pub const fn new(l_brace: Token, elems: ParamRecordAttrs, r_brace: Token) -> Self {
|
||||
Self {
|
||||
l_brace,
|
||||
elems,
|
||||
|
|
|
|||
|
|
@ -309,18 +309,21 @@ impl Parser {
|
|||
self.level -= 1;
|
||||
return Ok(block);
|
||||
}
|
||||
assert!(self.cur_is(Newline));
|
||||
self.skip();
|
||||
assert!(self.cur_is(Indent));
|
||||
self.skip();
|
||||
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.category_is(TC::Separator) => {
|
||||
self.skip();
|
||||
}
|
||||
Some(t) if t.is(Indent) => {
|
||||
self.skip();
|
||||
}
|
||||
Some(t) if t.is(Dedent) => {
|
||||
self.skip();
|
||||
break;
|
||||
}
|
||||
Some(t) if t.is(EOF) => {
|
||||
break;
|
||||
}
|
||||
|
|
@ -391,7 +394,7 @@ impl Parser {
|
|||
fn try_reduce_acc(&mut self) -> ParseResult<Accessor> {
|
||||
debug_call_info!(self);
|
||||
let mut acc = match self.peek() {
|
||||
Some(t) if t.is(Symbol) => Accessor::local(self.lpop()),
|
||||
Some(t) if t.is(Symbol) || t.is(UBar) => Accessor::local(self.lpop()),
|
||||
Some(t) if t.is(Dot) => {
|
||||
let dot = self.lpop();
|
||||
let maybe_symbol = self.lpop();
|
||||
|
|
@ -609,7 +612,8 @@ impl Parser {
|
|||
|| t.category_is(TC::UnaryOp)
|
||||
|| t.is(LParen)
|
||||
|| t.is(LSqBr)
|
||||
|| t.is(LBrace) =>
|
||||
|| t.is(LBrace)
|
||||
|| t.is(UBar) =>
|
||||
{
|
||||
Some(self.try_reduce_args())
|
||||
}
|
||||
|
|
@ -670,18 +674,6 @@ impl Parser {
|
|||
}
|
||||
debug_power_assert!(self.cur_is(Indent));
|
||||
self.skip();
|
||||
if !args.kw_is_empty() {
|
||||
args.push_kw(self.try_reduce_kw_arg().map_err(|_| self.stack_dec())?);
|
||||
} else {
|
||||
match self.try_reduce_arg().map_err(|_| self.stack_dec())? {
|
||||
PosOrKwArg::Pos(arg) => {
|
||||
args.push_pos(arg);
|
||||
}
|
||||
PosOrKwArg::Kw(arg) => {
|
||||
args.push_kw(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(Comma) => {
|
||||
self.skip();
|
||||
|
|
@ -704,14 +696,24 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(Newline) && colon_style => {
|
||||
while self.cur_is(Newline) {
|
||||
self.skip();
|
||||
}
|
||||
if self.cur_is(Dedent) {
|
||||
self.skip();
|
||||
Some(t) if t.is(RParen) => {
|
||||
rp = Some(self.lpop());
|
||||
let (pos_args, kw_args, _) = args.deconstruct();
|
||||
args = Args::new(pos_args, kw_args, Some((lp.unwrap(), rp.unwrap())));
|
||||
break;
|
||||
}
|
||||
Some(t) if t.is(Newline) => {
|
||||
if !colon_style {
|
||||
break;
|
||||
}
|
||||
let last = self.lpop();
|
||||
if self.cur_is(Dedent) {
|
||||
self.skip();
|
||||
self.restore(last);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Some(_) if colon_style => {
|
||||
if !args.kw_is_empty() {
|
||||
args.push_kw(self.try_reduce_kw_arg().map_err(|_| self.stack_dec())?);
|
||||
} else {
|
||||
|
|
@ -725,12 +727,6 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(RParen) => {
|
||||
rp = Some(self.lpop());
|
||||
let (pos_args, kw_args, _) = args.deconstruct();
|
||||
args = Args::new(pos_args, kw_args, Some((lp.unwrap(), rp.unwrap())));
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
|
|
@ -853,13 +849,15 @@ impl Parser {
|
|||
let mut defs = 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.category_is(TC::Separator) => {
|
||||
self.skip();
|
||||
}
|
||||
Some(t) if t.is(Dedent) => {
|
||||
self.skip();
|
||||
break;
|
||||
}
|
||||
Some(_) => {
|
||||
let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
|
||||
match def {
|
||||
|
|
@ -906,6 +904,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// chunk = normal expr + def
|
||||
fn try_reduce_chunk(&mut self, winding: bool) -> ParseResult<Expr> {
|
||||
debug_call_info!(self);
|
||||
let mut stack = Vec::<ExprOrOp>::new();
|
||||
|
|
@ -1140,6 +1139,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// chunk = expr + def
|
||||
/// winding: true => parse paren-less tuple
|
||||
fn try_reduce_expr(&mut self, winding: bool) -> ParseResult<Expr> {
|
||||
debug_call_info!(self);
|
||||
|
|
@ -1326,7 +1326,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(Symbol) || t.is(Dot) => {
|
||||
Some(t) if t.is(Symbol) || t.is(Dot) || t.is(UBar) => {
|
||||
let call_or_acc = self
|
||||
.try_reduce_call_or_acc()
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
|
|
@ -1721,7 +1721,11 @@ impl Parser {
|
|||
debug_call_info!(self);
|
||||
match accessor {
|
||||
Accessor::Ident(ident) => {
|
||||
let pat = VarPattern::Ident(ident);
|
||||
let pat = if &ident.inspect()[..] == "_" {
|
||||
VarPattern::Discard(ident.name.into_token())
|
||||
} else {
|
||||
VarPattern::Ident(ident)
|
||||
};
|
||||
self.level -= 1;
|
||||
Ok(VarSignature::new(pat, None))
|
||||
}
|
||||
|
|
@ -2055,10 +2059,41 @@ impl Parser {
|
|||
|
||||
fn convert_record_to_param_record_pat(
|
||||
&mut self,
|
||||
_record: Record,
|
||||
record: Record,
|
||||
) -> ParseResult<ParamRecordPattern> {
|
||||
debug_call_info!(self);
|
||||
todo!()
|
||||
match record {
|
||||
Record::Normal(rec) => {
|
||||
let mut pats = vec![];
|
||||
for mut attr in rec.attrs.into_iter() {
|
||||
let lhs =
|
||||
option_enum_unwrap!(attr.sig, Signature::Var).unwrap_or_else(|| todo!());
|
||||
let lhs =
|
||||
option_enum_unwrap!(lhs.pat, VarPattern::Ident).unwrap_or_else(|| todo!());
|
||||
assert_eq!(attr.body.block.len(), 1);
|
||||
let rhs = option_enum_unwrap!(attr.body.block.remove(0), Expr::Accessor)
|
||||
.unwrap_or_else(|| todo!());
|
||||
let rhs = self
|
||||
.convert_accessor_to_param_sig(rhs)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
pats.push(ParamRecordAttr::new(lhs, rhs));
|
||||
}
|
||||
let attrs = ParamRecordAttrs::new(pats);
|
||||
self.level -= 1;
|
||||
Ok(ParamRecordPattern::new(rec.l_brace, attrs, rec.r_brace))
|
||||
}
|
||||
Record::Shortened(rec) => {
|
||||
let mut pats = vec![];
|
||||
for ident in rec.idents.into_iter() {
|
||||
let rhs =
|
||||
ParamSignature::new(ParamPattern::VarName(ident.name.clone()), None, None);
|
||||
pats.push(ParamRecordAttr::new(ident.clone(), rhs));
|
||||
}
|
||||
let attrs = ParamRecordAttrs::new(pats);
|
||||
self.level -= 1;
|
||||
Ok(ParamRecordPattern::new(rec.l_brace, attrs, rec.r_brace))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_tuple_to_param_tuple_pat(&mut self, tuple: Tuple) -> ParseResult<ParamTuplePattern> {
|
||||
|
|
@ -2147,7 +2182,11 @@ impl Parser {
|
|||
debug_call_info!(self);
|
||||
match accessor {
|
||||
Accessor::Ident(ident) => {
|
||||
let pat = ParamPattern::VarName(ident.name);
|
||||
let pat = if &ident.name.inspect()[..] == "_" {
|
||||
ParamPattern::Discard(ident.name.into_token())
|
||||
} else {
|
||||
ParamPattern::VarName(ident.name)
|
||||
};
|
||||
self.level -= 1;
|
||||
Ok(ParamSignature::new(pat, None, None))
|
||||
}
|
||||
|
|
@ -2186,10 +2225,18 @@ impl Parser {
|
|||
|
||||
fn convert_type_asc_to_lambda_sig(
|
||||
&mut self,
|
||||
_tasc: TypeAscription,
|
||||
tasc: TypeAscription,
|
||||
) -> ParseResult<LambdaSignature> {
|
||||
debug_call_info!(self);
|
||||
todo!()
|
||||
let sig = self
|
||||
.convert_rhs_to_param(*tasc.expr, true)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
self.level -= 1;
|
||||
Ok(LambdaSignature::new(
|
||||
Params::new(vec![sig], None, vec![], None),
|
||||
None,
|
||||
TypeBoundSpecs::empty(),
|
||||
))
|
||||
}
|
||||
|
||||
fn convert_rhs_to_type_spec(&mut self, rhs: Expr) -> ParseResult<TypeSpec> {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ sum = match a:
|
|||
[x, y, z] -> x + y + z
|
||||
(x, y, z) -> x + y + z
|
||||
{x; y; z} -> x + y + z
|
||||
i: Int -> i
|
||||
(i: Int) -> i
|
||||
_ -> panic "unknown object"
|
||||
|
||||
for! 0.., i =>
|
||||
for! 0..1000, i =>
|
||||
print! "i = {i}"
|
||||
if i >= 100:
|
||||
do return break()
|
||||
|
|
|
|||
|
|
@ -1,26 +1,25 @@
|
|||
LitExpr = Class {.i = Int}, Impl := Show
|
||||
LitExpr.
|
||||
new i = Self::__new__ {.i;}
|
||||
show &self = "{self.i}"
|
||||
show self = "{self.i}"
|
||||
AddExpr = Class {.lhs = Expr, .rhs = Expr}, Impl := Show
|
||||
AddExpr.
|
||||
new lhs, rhs = Self::__new__ {.lhs; .rhs}
|
||||
show &self = "{self.lhs} + {self.rhs}"
|
||||
show self = "{self.lhs} + {self.rhs}"
|
||||
SubExpr = Class {.lhs = Expr, .rhs = Expr}, Impl := Show
|
||||
SubExpr.
|
||||
new lhs, rhs = Self::__new__ {.lhs; .rhs}
|
||||
show &self = "{self.lhs} - {self.rhs}"
|
||||
show self = "{self.lhs} - {self.rhs}"
|
||||
PosExpr = Class {.expr = Expr}, Impl := Show
|
||||
PosExpr.
|
||||
new expr = Self::__new__ {.expr;}
|
||||
show &self = "+{self.expr}"
|
||||
show self = "+{self.expr}"
|
||||
NegExpr = Class {.expr = Expr}, Impl := Show
|
||||
NegExpr.
|
||||
new expr = Self::__new__ {.expr;}
|
||||
show &self = "-{self.expr}"
|
||||
show self = "-{self.expr}"
|
||||
|
||||
Expr = Enum:
|
||||
LitExpr
|
||||
Expr = Enum LitExpr:
|
||||
AddExpr
|
||||
SubExpr
|
||||
NegExpr
|
||||
|
|
@ -29,11 +28,11 @@ Expr.
|
|||
add = Self.cons(AddExpr)
|
||||
eval self =
|
||||
match self:
|
||||
l: Expr.LitExpr -> l.i
|
||||
a: Expr.AddExpr -> a.lhs + a.rhs
|
||||
s: Expr.SubExpr -> s.lhs - s.rhs
|
||||
p: Expr.PosExpr -> p.expr
|
||||
n: Expr.NegExpr -> -n.expr
|
||||
(l: Expr.LitExpr) -> l.i
|
||||
(a: Expr.AddExpr) -> a.lhs + a.rhs
|
||||
(s: Expr.SubExpr) -> s.lhs - s.rhs
|
||||
(p: Expr.PosExpr) -> p.expr
|
||||
(n: Expr.NegExpr) -> -n.expr
|
||||
|
||||
expr = Expr.add Expr.lit(1), Expr.lit(2)
|
||||
print! expr # 1 + 2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue