Merge remote-tracking branch 'github-desktop-GreasySlug/feature-parse-tuple'

This commit is contained in:
Shunsuke Shibayama 2022-08-29 12:22:28 +09:00
commit 11e89576e1
2 changed files with 149 additions and 18 deletions

View file

@ -109,7 +109,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 {
@ -367,6 +367,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))
} }
@ -503,6 +507,38 @@ impl_nested_display_for_enum!(Array; Normal, WithLength, Comprehension);
impl_display_for_enum!(Array; Normal, WithLength, Comprehension); impl_display_for_enum!(Array; Normal, WithLength, Comprehension);
impl_locational_for_enum!(Array; Normal, WithLength, Comprehension); impl_locational_for_enum!(Array; Normal, WithLength, Comprehension);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct NormalTuple {
pub elems: Args,
}
impl NestedDisplay for NormalTuple {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
writeln!(f, "(")?;
self.elems.fmt_nest(f, level + 1)?;
write!(f, "\n{})", " ".repeat(level))
}
}
impl_display_from_nested!(NormalTuple);
impl_locational!(NormalTuple, elems, elems);
impl NormalTuple {
pub fn new(elems: Args) -> Self {
Self { elems }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Tuple {
Normal(NormalTuple),
// Comprehension(TupleComprehension),
}
impl_nested_display_for_enum!(Tuple; Normal);
impl_display_for_enum!(Tuple; Normal);
impl_locational_for_enum!(Tuple; Normal);
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NormalDict { pub struct NormalDict {
l_brace: Token, l_brace: Token,
@ -832,6 +868,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>,
@ -861,12 +921,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 {
@ -2426,6 +2487,7 @@ pub enum Expr {
Lit(Literal), Lit(Literal),
Accessor(Accessor), Accessor(Accessor),
Array(Array), Array(Array),
Tuple(Tuple),
Dict(Dict), Dict(Dict),
Set(Set), Set(Set),
Record(Record), Record(Record),
@ -2437,9 +2499,9 @@ pub enum Expr {
Def(Def), Def(Def),
} }
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_display_from_nested!(Expr); impl_display_from_nested!(Expr);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl Expr { impl Expr {
pub fn is_match_call(&self) -> bool { pub fn is_match_call(&self) -> bool {

View file

@ -686,10 +686,24 @@ 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 => {
acc = Accessor::attr(Expr::Accessor(acc), attr); let attr = Local::new(token);
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();
@ -1778,6 +1792,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;
@ -1852,18 +1874,24 @@ impl Parser {
Ok(Expr::Lambda(lambda)) Ok(Expr::Lambda(lambda))
} }
Some(t) if t.is(LParen) => { Some(t) if t.is(LParen) => {
self.skip(); let lparen = self.lpop();
let expr = self.try_reduce_expr().map_err(|_| self.stack_dec())?;
if self.cur_is(RParen) { if self.cur_is(RParen) {
self.skip(); 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) return Ok(Expr::Tuple(unit));
} else {
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
} }
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())?;
@ -2033,6 +2061,47 @@ impl Parser {
todo!() todo!()
} }
fn try_reduce_tuple(&mut self, first_elem: Expr) -> ParseResult<Tuple> {
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();
if self.cur_is(Comma) {
self.level -= 1;
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]
fn try_reduce_ident(&mut self) -> ParseResult<Identifier> { fn try_reduce_ident(&mut self) -> ParseResult<Identifier> {
debug_call_info!(self); debug_call_info!(self);