Merge branch 'erg-lang:main' into fix/test

This commit is contained in:
Slug 2022-09-15 08:25:12 +09:00 committed by GitHub
commit 02d43dd7af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 802 additions and 340 deletions

View file

@ -1,8 +1,8 @@
[package]
name = "erg_parser"
version = "0.4.1"
version = "0.4.6"
description = "The Erg parser"
authors = ["mtshiba <sbym1346@gmail.com>"]
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2021"
repository = "https://github.com/erg-lang/erg/tree/main/src/erg_compiler/erg_parser"
@ -16,7 +16,7 @@ simplified_chinese = [ "erg_common/simplified_chinese" ]
traditional_chinese = [ "erg_common/traditional_chinese" ]
[dependencies]
erg_common = { version = "0.4.1", path = "../erg_common" }
erg_common = { version = "0.4.6", path = "../erg_common" }
[lib]
path = "lib.rs"

View file

@ -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,

View file

@ -1,10 +1,10 @@
//! defines `ParseError` and others.
//!
//! パーサーが出すエラーを定義
use erg_common::astr::AtomicStr;
use erg_common::config::Input;
use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay};
use erg_common::traits::Stream;
use erg_common::Str;
use erg_common::{impl_stream_for_wrapper, switch_lang};
#[derive(Debug)]
@ -65,20 +65,20 @@ impl LexError {
))
}
pub fn syntax_error<S: Into<Str>>(
pub fn syntax_error<S: Into<AtomicStr>>(
errno: usize,
loc: Location,
desc: S,
hint: Option<Str>,
hint: Option<AtomicStr>,
) -> Self {
Self::new(ErrorCore::new(errno, SyntaxError, loc, desc, hint))
}
pub fn syntax_warning<S: Into<Str>>(
pub fn syntax_warning<S: Into<AtomicStr>>(
errno: usize,
loc: Location,
desc: S,
hint: Option<Str>,
hint: Option<AtomicStr>,
) -> Self {
Self::new(ErrorCore::new(errno, SyntaxWarning, loc, desc, hint))
}

View file

@ -5,7 +5,6 @@ use erg_common::cache::CacheSet;
use erg_common::config::ErgConfig;
use erg_common::config::Input;
use erg_common::traits::{Locational, Runnable, Stream};
use erg_common::Str;
use erg_common::{debug_power_assert, fn_name_full, normalize_newline, switch_lang};
use crate::error::{LexError, LexErrors, LexResult, LexerRunnerError, LexerRunnerErrors};
@ -47,7 +46,7 @@ impl Runnable for LexerRunner {
Ok(())
}
fn eval(&mut self, src: Str) -> Result<String, LexerRunnerErrors> {
fn eval(&mut self, src: String) -> Result<String, LexerRunnerErrors> {
let lexer = Lexer::from_str(src);
if cfg!(feature = "debug") {
let ts = lexer
@ -97,7 +96,7 @@ impl Lexer /*<'a>*/ {
}
#[allow(clippy::should_implement_trait)]
pub fn from_str(src: Str) -> Self {
pub fn from_str(src: String) -> Self {
let escaped = normalize_newline(&src);
Lexer {
str_cache: CacheSet::new(),

View file

@ -194,7 +194,7 @@ impl Runnable for ParserRunner {
Ok(())
}
fn eval(&mut self, src: Str) -> Result<String, ParserRunnerErrors> {
fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> {
let ast = self.parse_with_input(src)?;
Ok(format!("{ast}"))
}
@ -224,7 +224,7 @@ impl ParserRunner {
self_.parse()
}
fn parse_with_input(&mut self, src: Str) -> Result<AST, ParserRunnerErrors> {
fn parse_with_input(&mut self, src: String) -> Result<AST, ParserRunnerErrors> {
let ts = Lexer::new(Input::Str(src))
.lex()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
@ -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;
}
@ -763,7 +759,7 @@ impl Parser {
self.errs.push(err);
return Err(());
};
let t_spec = if self.cur_is(Colon) {
/*let t_spec = if self.cur_is(Colon) {
self.skip();
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
let t_spec = self
@ -772,10 +768,10 @@ impl Parser {
Some(t_spec)
} else {
None
};
};*/
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(PosOrKwArg::Kw(KwArg::new(kw, t_spec, expr)))
Ok(PosOrKwArg::Kw(KwArg::new(kw, None, expr)))
} else {
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
self.level -= 1;
@ -808,7 +804,7 @@ impl Parser {
.push(ParseError::simple_syntax_error(0, acc.loc()));
return Err(());
};
let t_spec = if self.cur_is(Colon) {
/*let t_spec = if self.cur_is(Colon) {
self.skip();
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
let t_spec = self
@ -817,10 +813,10 @@ impl Parser {
Some(t_spec)
} else {
None
};
};*/
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(KwArg::new(keyword, t_spec, expr))
Ok(KwArg::new(keyword, None, expr))
} else {
let loc = t.loc();
self.level -= 1;
@ -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();
@ -926,7 +925,8 @@ impl Parser {
self.counter.inc();
let block = self.try_reduce_block().map_err(|_| self.stack_dec())?;
let body = DefBody::new(op, block, self.counter);
stack.push(ExprOrOp::Expr(Expr::Def(Def::new(sig, body))));
self.level -= 1;
return Ok(Expr::Def(Def::new(sig, body)));
}
Some(op) if op.category_is(TC::LambdaOp) => {
let op = self.lpop();
@ -943,7 +943,7 @@ impl Parser {
self.counter,
))));
}
Some(op) if op.is(Colon) => {
Some(op) if op.is(Colon) && !self.nth_is(1, Newline) => {
let _op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let t_spec = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
@ -1139,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);
@ -1163,7 +1164,7 @@ impl Parser {
self.counter,
))));
}
Some(op) if op.is(Colon) => {
Some(op) if op.is(Colon) && !self.nth_is(1, Newline) => {
let _op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let t_spec = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
@ -1325,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())?;
@ -1720,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))
}
@ -2054,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> {
@ -2146,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))
}
@ -2185,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> {

View file

@ -49,6 +49,7 @@ fn parse_test_from_code(file_path: &'static str) -> Result<(), ParserRunnerError
dump_as_pyc: false,
python_ver: None,
py_server_timeout: 100,
quiet_startup: false,
input: input.clone(),
module: "<module>",
verbose: 2,