Impl Dict parsing

This commit is contained in:
Shunsuke Shibayama 2022-10-08 12:44:11 +09:00
parent 7d659da6a5
commit ec196d0695
3 changed files with 174 additions and 49 deletions

View file

@ -590,16 +590,40 @@ impl Tuple {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyValue {
pub key: Box<Expr>,
pub value: Box<Expr>,
}
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)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NormalDict { pub struct NormalDict {
l_brace: Token, pub(crate) l_brace: Token,
r_brace: Token, pub(crate) r_brace: Token,
pub attrs: Args, // TODO: Impl K: V Pair pub kvs: Vec<KeyValue>,
} }
impl NestedDisplay for NormalDict { impl NestedDisplay for NormalDict {
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.attrs) write!(f, "{{{}}}", fmt_vec(&self.kvs))
} }
} }
@ -607,11 +631,11 @@ impl_display_from_nested!(NormalDict);
impl_locational!(NormalDict, l_brace, r_brace); impl_locational!(NormalDict, l_brace, r_brace);
impl NormalDict { 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<KeyValue>) -> Self {
Self { Self {
l_brace, l_brace,
r_brace, r_brace,
attrs, kvs,
} }
} }
} }

View file

@ -12,11 +12,11 @@ use erg_common::{enum_unwrap, get_hash, log, set};
use crate::ast::{ use crate::ast::{
Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def, Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def,
DefBody, DefId, Expr, Identifier, KwArg, Lambda, LambdaSignature, Literal, Methods, Module, DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal,
NormalArray, NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamSignature, Params, Methods, Module, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern,
PosArg, Record, RecordAttrs, Set as astSet, SetWithLength, ShortenedRecord, Signature, ParamSignature, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength,
SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, UnaryOp, VarName, VarPattern, ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
VarRecordAttr, VarSignature, UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
}; };
use crate::token::{Token, TokenKind}; use crate::token::{Token, TokenKind};
@ -439,9 +439,22 @@ impl Desugarer {
Expr::Set(astSet::WithLength(set)) Expr::Set(astSet::WithLength(set))
} }
}, },
Expr::Dict(dict) => { Expr::Dict(dict) => match dict {
todo!("{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) => { Expr::BinOp(binop) => {
let mut args = binop.args.into_iter(); let mut args = binop.args.into_iter();
let lhs = self.rec_desugar_shortened_record(*args.next().unwrap()); let lhs = self.rec_desugar_shortened_record(*args.next().unwrap());

View file

@ -264,7 +264,7 @@ impl Parser {
switch_unreachable!() switch_unreachable!()
} }
Some(_) => { Some(_) => {
if let Ok(expr) = self.try_reduce_chunk(true) { if let Ok(expr) = self.try_reduce_chunk(true, false) {
chunks.push(expr); chunks.push(expr);
} }
} }
@ -280,7 +280,9 @@ impl Parser {
let mut block = Block::with_capacity(2); let mut block = Block::with_capacity(2);
// single line block // single line block
if !self.cur_is(Newline) { 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); block.push(chunk);
self.level -= 1; self.level -= 1;
return Ok(block); return Ok(block);
@ -304,7 +306,7 @@ impl Parser {
break; break;
} }
Some(_) => { Some(_) => {
if let Ok(expr) = self.try_reduce_chunk(true) { if let Ok(expr) = self.try_reduce_chunk(true, false) {
block.push(expr); block.push(expr);
} }
} }
@ -343,7 +345,7 @@ impl Parser {
if self.cur_is(TokenKind::AtSign) { if self.cur_is(TokenKind::AtSign) {
self.lpop(); self.lpop();
let expr = self let expr = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(Some(Decorator::new(expr))) Ok(Some(Decorator::new(expr)))
@ -472,7 +474,7 @@ impl Parser {
Some(t) if t.is(LSqBr) => { Some(t) if t.is(LSqBr) => {
self.skip(); self.skip();
let index = self let index = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
if self.cur_is(RSqBr) { if self.cur_is(RSqBr) {
self.skip(); self.skip();
@ -568,7 +570,7 @@ impl Parser {
Some(semi) if semi.is(Semi) => { Some(semi) if semi.is(Semi) => {
self.lpop(); self.lpop();
let len = self let len = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
return Ok(ArrayInner::WithLength(elems.remove_pos(0), len)); return Ok(ArrayInner::WithLength(elems.remove_pos(0), len));
@ -625,7 +627,7 @@ impl Parser {
match self.peek() { match self.peek() {
Some(_) => { Some(_) => {
let expr = self let expr = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(PosArg::new(expr)) Ok(PosArg::new(expr))
@ -814,13 +816,13 @@ impl Parser {
return Err(()); return Err(());
}; };
let expr = self let expr = self
.try_reduce_expr(false, in_type_args) .try_reduce_expr(false, in_type_args, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(PosOrKwArg::Kw(KwArg::new(kw, None, expr))) Ok(PosOrKwArg::Kw(KwArg::new(kw, None, expr)))
} else { } else {
let expr = self let expr = self
.try_reduce_expr(false, in_type_args) .try_reduce_expr(false, in_type_args, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(PosOrKwArg::Pos(PosArg::new(expr))) Ok(PosOrKwArg::Pos(PosArg::new(expr)))
@ -828,7 +830,7 @@ impl Parser {
} }
Some(_) => { Some(_) => {
let expr = self let expr = self
.try_reduce_expr(false, in_type_args) .try_reduce_expr(false, in_type_args, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(PosOrKwArg::Pos(PosArg::new(expr))) Ok(PosOrKwArg::Pos(PosArg::new(expr)))
@ -867,7 +869,7 @@ impl Parser {
None None
};*/ };*/
let expr = self let expr = self
.try_reduce_expr(false, in_type_args) .try_reduce_expr(false, in_type_args, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(KwArg::new(keyword, None, expr)) Ok(KwArg::new(keyword, None, expr))
@ -901,7 +903,9 @@ impl Parser {
while self.cur_is(Newline) { while self.cur_is(Newline) {
self.skip(); 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) { let first = if let Some(fst) = option_enum_unwrap!(first, Expr::Def) {
fst fst
} else { } else {
@ -924,7 +928,9 @@ impl Parser {
self.skip(); self.skip();
} }
Some(_) => { 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 { match def {
Expr::Def(def) => { Expr::Def(def) => {
defs.push(def); defs.push(def);
@ -968,7 +974,7 @@ impl Parser {
Ok(Lambda::new(sig, op, body, self.counter)) Ok(Lambda::new(sig, op, body, self.counter))
} else { } else {
let expr = self let expr = self
.try_reduce_expr(true, false) .try_reduce_expr(true, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
let block = Block::new(vec![expr]); let block = Block::new(vec![expr]);
self.level -= 1; self.level -= 1;
@ -977,11 +983,11 @@ impl Parser {
} }
/// chunk = normal expr + def /// chunk = normal expr + def
fn try_reduce_chunk(&mut self, winding: bool) -> ParseResult<Expr> { fn try_reduce_chunk(&mut self, winding: bool, in_brace: bool) -> ParseResult<Expr> {
debug_call_info!(self); debug_call_info!(self);
let mut stack = Vec::<ExprOrOp>::new(); let mut stack = Vec::<ExprOrOp>::new();
stack.push(ExprOrOp::Expr( stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs(false) self.try_reduce_bin_lhs(false, in_brace)
.map_err(|_| self.stack_dec())?, .map_err(|_| self.stack_dec())?,
)); ));
loop { loop {
@ -1016,14 +1022,19 @@ impl Parser {
self.counter, self.counter,
)))); ))));
} }
// type ascription
Some(op) Some(op)
if (op.is(Colon) && !self.nth_is(1, Newline)) if (op.is(Colon) && !self.nth_is(1, Newline))
|| (op.is(SubtypeOf) || op.is(SupertypeOf)) => || (op.is(SubtypeOf) || op.is(SupertypeOf)) =>
{ {
// "a": 1 (key-value pair)
if in_brace {
break;
}
let op = self.lpop(); let op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let t_spec = self let t_spec = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
let t_spec = self let t_spec = self
.convert_rhs_to_type_spec(t_spec) .convert_rhs_to_type_spec(t_spec)
@ -1053,7 +1064,7 @@ impl Parser {
} }
stack.push(ExprOrOp::Op(self.lpop())); stack.push(ExprOrOp::Op(self.lpop()));
stack.push(ExprOrOp::Expr( stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs(false) self.try_reduce_bin_lhs(false, in_brace)
.map_err(|_| self.stack_dec())?, .map_err(|_| self.stack_dec())?,
)); ));
} }
@ -1225,11 +1236,17 @@ impl Parser {
/// chunk = expr + def /// chunk = expr + def
/// winding: true => parse paren-less tuple /// winding: true => parse paren-less tuple
fn try_reduce_expr(&mut self, winding: bool, in_type_args: bool) -> ParseResult<Expr> { /// 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<Expr> {
debug_call_info!(self); debug_call_info!(self);
let mut stack = Vec::<ExprOrOp>::new(); let mut stack = Vec::<ExprOrOp>::new();
stack.push(ExprOrOp::Expr( 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())?, .map_err(|_| self.stack_dec())?,
)); ));
loop { loop {
@ -1249,14 +1266,19 @@ impl Parser {
self.counter, self.counter,
)))); ))));
} }
// type ascription
Some(op) Some(op)
if (op.is(Colon) && !self.nth_is(1, Newline)) if (op.is(Colon) && !self.nth_is(1, Newline))
|| (op.is(SubtypeOf) || op.is(SupertypeOf)) => || (op.is(SubtypeOf) || op.is(SupertypeOf)) =>
{ {
// "a": 1 (key-value pair)
if in_brace {
break;
}
let op = self.lpop(); let op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let t_spec = self 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())?; .map_err(|_| self.stack_dec())?;
let t_spec = self let t_spec = self
.convert_rhs_to_type_spec(t_spec) .convert_rhs_to_type_spec(t_spec)
@ -1286,7 +1308,7 @@ impl Parser {
} }
stack.push(ExprOrOp::Op(self.lpop())); stack.push(ExprOrOp::Op(self.lpop()));
stack.push(ExprOrOp::Expr( 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())?, .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. /// "LHS" is the smallest unit that can be the left-hand side of an BinOp.
/// e.g. Call, Name, UnaryOp, Lambda /// e.g. Call, Name, UnaryOp, Lambda
fn try_reduce_bin_lhs(&mut self, in_type_args: bool) -> ParseResult<Expr> { fn try_reduce_bin_lhs(&mut self, in_type_args: bool, in_brace: bool) -> ParseResult<Expr> {
debug_call_info!(self); debug_call_info!(self);
match self.peek() { match self.peek() {
Some(t) if t.category_is(TC::Literal) => { Some(t) if t.category_is(TC::Literal) => {
@ -1394,7 +1416,7 @@ impl Parser {
} }
Some(t) if t.is(AtSign) => { Some(t) if t.is(AtSign) => {
let decos = self.opt_reduce_decorators()?; 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) { let mut def = if let Some(def) = option_enum_unwrap!(expr, Expr::Def) {
def def
} else { } else {
@ -1447,7 +1469,7 @@ impl Parser {
return Ok(Expr::Tuple(unit)); return Ok(Expr::Tuple(unit));
} }
let mut expr = self let mut expr = self
.try_reduce_expr(true, false) .try_reduce_expr(true, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
let rparen = self.lpop(); let rparen = self.lpop();
if let Expr::Tuple(Tuple::Normal(tup)) = &mut expr { if let Expr::Tuple(Tuple::Normal(tup)) = &mut expr {
@ -1533,7 +1555,7 @@ impl Parser {
debug_call_info!(self); debug_call_info!(self);
let op = self.lpop(); let op = self.lpop();
let expr = self let expr = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
self.level -= 1; self.level -= 1;
Ok(UnaryOp::new(op, expr)) Ok(UnaryOp::new(op, expr))
@ -1620,6 +1642,9 @@ impl Parser {
return Ok(BraceContainer::Record(Record::Normal(rec))); 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(()); return Err(());
} }
if first.is(Colon) { if first.is(Colon) {
@ -1627,16 +1652,20 @@ impl Parser {
if let Some(t) = self.peek() { if let Some(t) = self.peek() {
if t.is(RBrace) { if t.is(RBrace) {
let r_brace = self.lpop(); let r_brace = self.lpop();
let arg = Args::empty(); let dict = NormalDict::new(l_brace, r_brace, vec![]);
let dict = NormalDict::new(l_brace, r_brace, arg);
return Ok(BraceContainer::Dict(Dict::Normal(dict))); 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(()); 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 { match first {
Expr::Def(def) => { Expr::Def(def) => {
let record = self let record = self
@ -1645,8 +1674,6 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(BraceContainer::Record(Record::Normal(record))) Ok(BraceContainer::Record(Record::Normal(record)))
} }
// Dict
Expr::TypeAsc(_) => todo!(),
// TODO: {X; Y} will conflict with Set // TODO: {X; Y} will conflict with Set
Expr::Accessor(acc) Expr::Accessor(acc)
if self.cur_is(Semi) if self.cur_is(Semi)
@ -1659,6 +1686,14 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(BraceContainer::Record(Record::Shortened(record))) 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 => { other => {
let set = self let set = self
.try_reduce_set(l_brace, other) .try_reduce_set(l_brace, other)
@ -1704,7 +1739,9 @@ impl Parser {
return Ok(NormalRecord::new(l_brace, r_brace, attrs)); return Ok(NormalRecord::new(l_brace, r_brace, attrs));
} }
Some(_) => { 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) { let def = if let Some(def) = option_enum_unwrap!(def, Expr::Def) {
def def
} else { } else {
@ -1791,8 +1828,59 @@ impl Parser {
} }
} }
fn _try_reduce_dict() -> ParseResult<Dict> { fn try_reduce_normal_dict(
todo!() &mut self,
l_brace: Token,
first_key: Expr,
) -> ParseResult<NormalDict> {
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<Set> { fn try_reduce_set(&mut self, l_brace: Token, first_elem: Expr) -> ParseResult<Set> {
@ -1800,7 +1888,7 @@ impl Parser {
if self.cur_is(Semi) { if self.cur_is(Semi) {
self.skip(); self.skip();
let len = self let len = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
let r_brace = self.lpop(); let r_brace = self.lpop();
return Ok(Set::WithLength(SetWithLength::new( return Ok(Set::WithLength(SetWithLength::new(