mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
Impl Tuple parsing
This commit is contained in:
parent
e3135778d5
commit
2f225c4630
2 changed files with 117 additions and 30 deletions
|
@ -130,7 +130,7 @@ impl KwArg {
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
pos_args: Vec<PosArg>,
|
pos_args: Vec<PosArg>,
|
||||||
kw_args: Vec<KwArg>,
|
kw_args: Vec<KwArg>,
|
||||||
paren: Option<(Token, Token)>,
|
pub paren: Option<(Token, Token)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for Args {
|
impl NestedDisplay for Args {
|
||||||
|
@ -358,6 +358,10 @@ impl Accessor {
|
||||||
Self::Attr(Attribute::new(obj, name))
|
Self::Attr(Attribute::new(obj, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tuple_attr(obj: Expr, index: Literal) -> Self {
|
||||||
|
Self::TupleAttr(TupleAttribute::new(obj, index))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn subscr(obj: Expr, index: Expr) -> Self {
|
pub fn subscr(obj: Expr, index: Expr) -> Self {
|
||||||
Self::Subscr(Subscript::new(obj, index))
|
Self::Subscr(Subscript::new(obj, index))
|
||||||
}
|
}
|
||||||
|
@ -497,8 +501,10 @@ pub struct NormalTuple {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for NormalTuple {
|
impl NestedDisplay for NormalTuple {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "({})", self.elems)
|
writeln!(f, "(")?;
|
||||||
|
self.elems.fmt_nest(f, level + 1)?;
|
||||||
|
write!(f, "\n{})", " ".repeat(level))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,9 +513,7 @@ impl_locational!(NormalTuple, elems, elems);
|
||||||
|
|
||||||
impl NormalTuple {
|
impl NormalTuple {
|
||||||
pub fn new(elems: Args) -> Self {
|
pub fn new(elems: Args) -> Self {
|
||||||
Self {
|
Self { elems }
|
||||||
elems,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,6 +769,30 @@ impl ConstAttribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ConstTupleAttribute {
|
||||||
|
tup: Box<ConstExpr>,
|
||||||
|
index: Literal,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for ConstTupleAttribute {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
|
write!(f, "{}.{}", self.tup, self.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(ConstTupleAttribute);
|
||||||
|
impl_locational!(ConstTupleAttribute, tup, index);
|
||||||
|
|
||||||
|
impl ConstTupleAttribute {
|
||||||
|
pub fn new(tup: ConstExpr, index: Literal) -> Self {
|
||||||
|
Self {
|
||||||
|
tup: Box::new(tup),
|
||||||
|
index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstSubscript {
|
pub struct ConstSubscript {
|
||||||
obj: Box<ConstExpr>,
|
obj: Box<ConstExpr>,
|
||||||
|
@ -794,12 +822,13 @@ pub enum ConstAccessor {
|
||||||
Local(ConstLocal),
|
Local(ConstLocal),
|
||||||
SelfDot(ConstLocal),
|
SelfDot(ConstLocal),
|
||||||
Attr(ConstAttribute),
|
Attr(ConstAttribute),
|
||||||
|
TupleAttr(ConstTupleAttribute),
|
||||||
Subscr(ConstSubscript),
|
Subscr(ConstSubscript),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_enum!(ConstAccessor; Local, SelfDot, Attr, Subscr);
|
impl_nested_display_for_enum!(ConstAccessor; Local, SelfDot, Attr, TupleAttr, Subscr);
|
||||||
impl_display_from_nested!(ConstAccessor);
|
impl_display_from_nested!(ConstAccessor);
|
||||||
impl_locational_for_enum!(ConstAccessor; Local, SelfDot, Attr, Subscr);
|
impl_locational_for_enum!(ConstAccessor; Local, SelfDot, Attr, TupleAttr, Subscr);
|
||||||
|
|
||||||
impl ConstAccessor {
|
impl ConstAccessor {
|
||||||
pub const fn local(symbol: Token) -> Self {
|
pub const fn local(symbol: Token) -> Self {
|
||||||
|
|
|
@ -659,11 +659,25 @@ impl Parser {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Dot) => {
|
Some(t) if t.is(Dot) => {
|
||||||
self.skip();
|
self.skip();
|
||||||
let symbol = self.lpop();
|
let token = self.lpop();
|
||||||
debug_power_assert!(symbol.is(Symbol));
|
match token.kind {
|
||||||
let attr = Local::new(symbol);
|
Symbol => {
|
||||||
|
let attr = Local::new(token);
|
||||||
acc = Accessor::attr(Expr::Accessor(acc), attr);
|
acc = Accessor::attr(Expr::Accessor(acc), attr);
|
||||||
}
|
}
|
||||||
|
NatLit => {
|
||||||
|
let attr = Literal::from(token);
|
||||||
|
acc = Accessor::tuple_attr(Expr::Accessor(acc), attr);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.restore(token);
|
||||||
|
self.level -= 1;
|
||||||
|
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||||
|
self.errs.push(err);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some(t) if t.is(LSqBr) => {
|
Some(t) if t.is(LSqBr) => {
|
||||||
self.skip();
|
self.skip();
|
||||||
let index = self.try_reduce_expr().map_err(|_| self.stack_dec())?;
|
let index = self.try_reduce_expr().map_err(|_| self.stack_dec())?;
|
||||||
|
@ -1681,6 +1695,14 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(t) if t.is(Comma) => {
|
||||||
|
let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
|
let tup = self
|
||||||
|
.try_reduce_tuple(first_elem)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
return Ok(Expr::Tuple(tup));
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if stack.len() <= 1 {
|
if stack.len() <= 1 {
|
||||||
break;
|
break;
|
||||||
|
@ -1755,9 +1777,24 @@ impl Parser {
|
||||||
Ok(Expr::Lambda(lambda))
|
Ok(Expr::Lambda(lambda))
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LParen) => {
|
Some(t) if t.is(LParen) => {
|
||||||
let tuple = self.try_reduce_tuple().map_err(|_| self.stack_dec())?;
|
let lparen = self.lpop();
|
||||||
|
if self.cur_is(RParen) {
|
||||||
|
let rparen = self.lpop();
|
||||||
|
let args = Args::new(vec![], vec![], Some((lparen, rparen)));
|
||||||
|
let unit = Tuple::Normal(NormalTuple::new(args));
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Expr::Tuple(tuple))
|
return Ok(Expr::Tuple(unit));
|
||||||
|
}
|
||||||
|
let mut expr = self.try_reduce_expr().map_err(|_| self.stack_dec())?;
|
||||||
|
let rparen = self.lpop();
|
||||||
|
match &mut expr {
|
||||||
|
Expr::Tuple(Tuple::Normal(tup)) => {
|
||||||
|
tup.elems.paren = Some((lparen, rparen));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(expr)
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LSqBr) => {
|
Some(t) if t.is(LSqBr) => {
|
||||||
let array = self.try_reduce_array().map_err(|_| self.stack_dec())?;
|
let array = self.try_reduce_array().map_err(|_| self.stack_dec())?;
|
||||||
|
@ -1852,24 +1889,45 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_reduce_tuple(&mut self) -> ParseResult<Tuple> {
|
fn try_reduce_tuple(&mut self, first_elem: Expr) -> ParseResult<Tuple> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
|
let mut args = Args::new(vec![PosArg::new(first_elem)], vec![], None);
|
||||||
|
loop {
|
||||||
|
match self.peek() {
|
||||||
|
Some(t) if t.is(Comma) => {
|
||||||
self.skip();
|
self.skip();
|
||||||
let inner = self.try_reduce_elems().map_err(|_| self.stack_dec())?;
|
if self.cur_is(Comma) {
|
||||||
self.skip();
|
|
||||||
let tpl = match inner {
|
|
||||||
ArrayInner::Normal(elems) => {
|
|
||||||
Tuple::Normal(NormalTuple::new(elems))
|
|
||||||
},
|
|
||||||
ArrayInner::Comprehension {
|
|
||||||
elem: _,
|
|
||||||
generators: _,
|
|
||||||
guards: _,
|
|
||||||
} => todo!(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(tpl)
|
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||||
|
self.errs.push(err);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
match self.try_reduce_arg().map_err(|_| self.stack_dec())? {
|
||||||
|
PosOrKwArg::Pos(arg) => {
|
||||||
|
args.push_pos(arg);
|
||||||
|
}
|
||||||
|
PosOrKwArg::Kw(_arg) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(t) if t.is(Newline) => {
|
||||||
|
while self.cur_is(Newline) {
|
||||||
|
self.skip();
|
||||||
|
}
|
||||||
|
match self.try_reduce_arg().map_err(|_| self.stack_dec())? {
|
||||||
|
PosOrKwArg::Pos(arg) => {
|
||||||
|
args.push_pos(arg);
|
||||||
|
}
|
||||||
|
PosOrKwArg::Kw(_arg) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let tup = Tuple::Normal(NormalTuple::new(args));
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(tup)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue