diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index bd245415..4811e9bc 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -590,16 +590,40 @@ impl Tuple { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct KeyValue { + pub key: Box, + pub value: Box, +} + +impl NestedDisplay for KeyValue { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + write!(f, "{}: {}", self.key, self.value) + } +} + +impl_display_from_nested!(KeyValue); +impl_locational!(KeyValue, key, value); + +impl KeyValue { + pub fn new(key: Expr, value: Expr) -> Self { + Self { + key: Box::new(key), + value: Box::new(value), + } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct NormalDict { - l_brace: Token, - r_brace: Token, - pub attrs: Args, // TODO: Impl K: V Pair + pub(crate) l_brace: Token, + pub(crate) r_brace: Token, + pub kvs: Vec, } impl NestedDisplay for NormalDict { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - write!(f, "{{{}}}", self.attrs) + write!(f, "{{{}}}", fmt_vec(&self.kvs)) } } @@ -607,11 +631,11 @@ impl_display_from_nested!(NormalDict); impl_locational!(NormalDict, l_brace, r_brace); impl NormalDict { - pub fn new(l_brace: Token, r_brace: Token, attrs: Args) -> Self { + pub fn new(l_brace: Token, r_brace: Token, kvs: Vec) -> Self { Self { l_brace, r_brace, - attrs, + kvs, } } } diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index c2e76464..38925008 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -12,11 +12,11 @@ use erg_common::{enum_unwrap, get_hash, log, set}; use crate::ast::{ Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def, - DefBody, DefId, Expr, Identifier, KwArg, Lambda, LambdaSignature, Literal, Methods, Module, - NormalArray, NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamSignature, Params, - PosArg, Record, RecordAttrs, Set as astSet, SetWithLength, ShortenedRecord, Signature, - SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, UnaryOp, VarName, VarPattern, - VarRecordAttr, VarSignature, + DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, + Methods, Module, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern, + ParamSignature, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength, + ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, + UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, }; use crate::token::{Token, TokenKind}; @@ -439,9 +439,22 @@ impl Desugarer { Expr::Set(astSet::WithLength(set)) } }, - Expr::Dict(dict) => { - todo!("{dict}") - } + Expr::Dict(dict) => match dict { + Dict::Normal(dic) => { + let new_kvs = dic + .kvs + .into_iter() + .map(|elem| { + let key = self.rec_desugar_shortened_record(*elem.key); + let value = self.rec_desugar_shortened_record(*elem.value); + KeyValue::new(key, value) + }) + .collect(); + let tup = NormalDict::new(dic.l_brace, dic.r_brace, new_kvs); + Expr::Dict(Dict::Normal(tup)) + } + _ => todo!("dict comprehension"), + }, Expr::BinOp(binop) => { let mut args = binop.args.into_iter(); let lhs = self.rec_desugar_shortened_record(*args.next().unwrap()); diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index e83d5976..6dfe2a99 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -264,7 +264,7 @@ impl Parser { switch_unreachable!() } Some(_) => { - if let Ok(expr) = self.try_reduce_chunk(true) { + if let Ok(expr) = self.try_reduce_chunk(true, false) { chunks.push(expr); } } @@ -280,7 +280,9 @@ impl Parser { let mut block = Block::with_capacity(2); // single line block if !self.cur_is(Newline) { - let chunk = self.try_reduce_chunk(true).map_err(|_| self.stack_dec())?; + let chunk = self + .try_reduce_chunk(true, false) + .map_err(|_| self.stack_dec())?; block.push(chunk); self.level -= 1; return Ok(block); @@ -304,7 +306,7 @@ impl Parser { break; } Some(_) => { - if let Ok(expr) = self.try_reduce_chunk(true) { + if let Ok(expr) = self.try_reduce_chunk(true, false) { block.push(expr); } } @@ -343,7 +345,7 @@ impl Parser { if self.cur_is(TokenKind::AtSign) { self.lpop(); let expr = self - .try_reduce_expr(false, false) + .try_reduce_expr(false, false, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(Some(Decorator::new(expr))) @@ -472,7 +474,7 @@ impl Parser { Some(t) if t.is(LSqBr) => { self.skip(); let index = self - .try_reduce_expr(false, false) + .try_reduce_expr(false, false, false) .map_err(|_| self.stack_dec())?; if self.cur_is(RSqBr) { self.skip(); @@ -568,7 +570,7 @@ impl Parser { Some(semi) if semi.is(Semi) => { self.lpop(); let len = self - .try_reduce_expr(false, false) + .try_reduce_expr(false, false, false) .map_err(|_| self.stack_dec())?; self.level -= 1; return Ok(ArrayInner::WithLength(elems.remove_pos(0), len)); @@ -625,7 +627,7 @@ impl Parser { match self.peek() { Some(_) => { let expr = self - .try_reduce_expr(false, false) + .try_reduce_expr(false, false, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(PosArg::new(expr)) @@ -814,13 +816,13 @@ impl Parser { return Err(()); }; let expr = self - .try_reduce_expr(false, in_type_args) + .try_reduce_expr(false, in_type_args, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(PosOrKwArg::Kw(KwArg::new(kw, None, expr))) } else { let expr = self - .try_reduce_expr(false, in_type_args) + .try_reduce_expr(false, in_type_args, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(PosOrKwArg::Pos(PosArg::new(expr))) @@ -828,7 +830,7 @@ impl Parser { } Some(_) => { let expr = self - .try_reduce_expr(false, in_type_args) + .try_reduce_expr(false, in_type_args, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(PosOrKwArg::Pos(PosArg::new(expr))) @@ -867,7 +869,7 @@ impl Parser { None };*/ let expr = self - .try_reduce_expr(false, in_type_args) + .try_reduce_expr(false, in_type_args, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(KwArg::new(keyword, None, expr)) @@ -901,7 +903,9 @@ impl Parser { while self.cur_is(Newline) { self.skip(); } - let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; + let first = self + .try_reduce_chunk(false, false) + .map_err(|_| self.stack_dec())?; let first = if let Some(fst) = option_enum_unwrap!(first, Expr::Def) { fst } else { @@ -924,7 +928,9 @@ impl Parser { self.skip(); } Some(_) => { - let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; + let def = self + .try_reduce_chunk(false, false) + .map_err(|_| self.stack_dec())?; match def { Expr::Def(def) => { defs.push(def); @@ -968,7 +974,7 @@ impl Parser { Ok(Lambda::new(sig, op, body, self.counter)) } else { let expr = self - .try_reduce_expr(true, false) + .try_reduce_expr(true, false, false) .map_err(|_| self.stack_dec())?; let block = Block::new(vec![expr]); self.level -= 1; @@ -977,11 +983,11 @@ impl Parser { } /// chunk = normal expr + def - fn try_reduce_chunk(&mut self, winding: bool) -> ParseResult { + fn try_reduce_chunk(&mut self, winding: bool, in_brace: bool) -> ParseResult { debug_call_info!(self); let mut stack = Vec::::new(); stack.push(ExprOrOp::Expr( - self.try_reduce_bin_lhs(false) + self.try_reduce_bin_lhs(false, in_brace) .map_err(|_| self.stack_dec())?, )); loop { @@ -1016,14 +1022,19 @@ impl Parser { self.counter, )))); } + // type ascription Some(op) if (op.is(Colon) && !self.nth_is(1, Newline)) || (op.is(SubtypeOf) || op.is(SupertypeOf)) => { + // "a": 1 (key-value pair) + if in_brace { + break; + } let op = self.lpop(); let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); let t_spec = self - .try_reduce_expr(false, false) + .try_reduce_expr(false, false, false) .map_err(|_| self.stack_dec())?; let t_spec = self .convert_rhs_to_type_spec(t_spec) @@ -1053,7 +1064,7 @@ impl Parser { } stack.push(ExprOrOp::Op(self.lpop())); stack.push(ExprOrOp::Expr( - self.try_reduce_bin_lhs(false) + self.try_reduce_bin_lhs(false, in_brace) .map_err(|_| self.stack_dec())?, )); } @@ -1225,11 +1236,17 @@ impl Parser { /// chunk = expr + def /// winding: true => parse paren-less tuple - fn try_reduce_expr(&mut self, winding: bool, in_type_args: bool) -> ParseResult { + /// in_brace: true => (1: 1) will not be a syntax error (key-value pair) + fn try_reduce_expr( + &mut self, + winding: bool, + in_type_args: bool, + in_brace: bool, + ) -> ParseResult { debug_call_info!(self); let mut stack = Vec::::new(); stack.push(ExprOrOp::Expr( - self.try_reduce_bin_lhs(in_type_args) + self.try_reduce_bin_lhs(in_type_args, in_brace) .map_err(|_| self.stack_dec())?, )); loop { @@ -1249,14 +1266,19 @@ impl Parser { self.counter, )))); } + // type ascription Some(op) if (op.is(Colon) && !self.nth_is(1, Newline)) || (op.is(SubtypeOf) || op.is(SupertypeOf)) => { + // "a": 1 (key-value pair) + if in_brace { + break; + } let op = self.lpop(); let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); let t_spec = self - .try_reduce_expr(false, in_type_args) + .try_reduce_expr(false, in_type_args, in_brace) .map_err(|_| self.stack_dec())?; let t_spec = self .convert_rhs_to_type_spec(t_spec) @@ -1286,7 +1308,7 @@ impl Parser { } stack.push(ExprOrOp::Op(self.lpop())); stack.push(ExprOrOp::Expr( - self.try_reduce_bin_lhs(in_type_args) + self.try_reduce_bin_lhs(in_type_args, in_brace) .map_err(|_| self.stack_dec())?, )); } @@ -1383,7 +1405,7 @@ impl Parser { /// "LHS" is the smallest unit that can be the left-hand side of an BinOp. /// e.g. Call, Name, UnaryOp, Lambda - fn try_reduce_bin_lhs(&mut self, in_type_args: bool) -> ParseResult { + fn try_reduce_bin_lhs(&mut self, in_type_args: bool, in_brace: bool) -> ParseResult { debug_call_info!(self); match self.peek() { Some(t) if t.category_is(TC::Literal) => { @@ -1394,7 +1416,7 @@ impl Parser { } Some(t) if t.is(AtSign) => { let decos = self.opt_reduce_decorators()?; - let expr = self.try_reduce_chunk(false)?; + let expr = self.try_reduce_chunk(false, in_brace)?; let mut def = if let Some(def) = option_enum_unwrap!(expr, Expr::Def) { def } else { @@ -1447,7 +1469,7 @@ impl Parser { return Ok(Expr::Tuple(unit)); } let mut expr = self - .try_reduce_expr(true, false) + .try_reduce_expr(true, false, false) .map_err(|_| self.stack_dec())?; let rparen = self.lpop(); if let Expr::Tuple(Tuple::Normal(tup)) = &mut expr { @@ -1533,7 +1555,7 @@ impl Parser { debug_call_info!(self); let op = self.lpop(); let expr = self - .try_reduce_expr(false, false) + .try_reduce_expr(false, false, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(UnaryOp::new(op, expr)) @@ -1620,6 +1642,9 @@ impl Parser { return Ok(BraceContainer::Record(Record::Normal(rec))); } } + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); return Err(()); } if first.is(Colon) { @@ -1627,16 +1652,20 @@ impl Parser { if let Some(t) = self.peek() { if t.is(RBrace) { let r_brace = self.lpop(); - let arg = Args::empty(); - let dict = NormalDict::new(l_brace, r_brace, arg); + let dict = NormalDict::new(l_brace, r_brace, vec![]); return Ok(BraceContainer::Dict(Dict::Normal(dict))); } } + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); return Err(()); } } - let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; + let first = self + .try_reduce_chunk(false, true) + .map_err(|_| self.stack_dec())?; match first { Expr::Def(def) => { let record = self @@ -1645,8 +1674,6 @@ impl Parser { self.level -= 1; Ok(BraceContainer::Record(Record::Normal(record))) } - // Dict - Expr::TypeAsc(_) => todo!(), // TODO: {X; Y} will conflict with Set Expr::Accessor(acc) if self.cur_is(Semi) @@ -1659,6 +1686,14 @@ impl Parser { self.level -= 1; Ok(BraceContainer::Record(Record::Shortened(record))) } + // Dict + other if self.cur_is(Colon) => { + let dict = self + .try_reduce_normal_dict(l_brace, other) + .map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(BraceContainer::Dict(Dict::Normal(dict))) + } other => { let set = self .try_reduce_set(l_brace, other) @@ -1704,7 +1739,9 @@ impl Parser { return Ok(NormalRecord::new(l_brace, r_brace, attrs)); } Some(_) => { - let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; + let def = self + .try_reduce_chunk(false, false) + .map_err(|_| self.stack_dec())?; let def = if let Some(def) = option_enum_unwrap!(def, Expr::Def) { def } else { @@ -1791,8 +1828,59 @@ impl Parser { } } - fn _try_reduce_dict() -> ParseResult { - todo!() + fn try_reduce_normal_dict( + &mut self, + l_brace: Token, + first_key: Expr, + ) -> ParseResult { + debug_call_info!(self); + assert!(self.cur_is(Colon)); + self.skip(); + let value = self + .try_reduce_chunk(false, false) + .map_err(|_| self.stack_dec())?; + let mut kvs = vec![KeyValue::new(first_key, value)]; + 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(()); + } else if self.cur_is(RBrace) { + let dict = NormalDict::new(l_brace, self.lpop(), kvs); + self.level -= 1; + return Ok(dict); + } + let key = self + .try_reduce_expr(false, false, true) + .map_err(|_| self.stack_dec())?; + if self.cur_is(Colon) { + self.skip(); + let value = self + .try_reduce_chunk(false, false) + .map_err(|_| self.stack_dec())?; + kvs.push(KeyValue::new(key, value)); + } else { + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); + return Err(()); + } + } + Some(t) if t.is(RBrace) => { + let dict = NormalDict::new(l_brace, self.lpop(), kvs); + self.level -= 1; + return Ok(dict); + } + _ => { + break; + } + } + } + Err(()) } fn try_reduce_set(&mut self, l_brace: Token, first_elem: Expr) -> ParseResult { @@ -1800,7 +1888,7 @@ impl Parser { if self.cur_is(Semi) { self.skip(); let len = self - .try_reduce_expr(false, false) + .try_reduce_expr(false, false, false) .map_err(|_| self.stack_dec())?; let r_brace = self.lpop(); return Ok(Set::WithLength(SetWithLength::new(