put record stuff into separate file

This commit is contained in:
Alain Zscheile 2023-09-26 14:12:43 +02:00
parent bbebc9a518
commit 5e776b963d
2 changed files with 107 additions and 94 deletions

View file

@ -13,6 +13,9 @@ use parser::{
mod pat;
pub use pat::{FullPattern, Pattern};
mod record;
pub use record::{Record, RecordEntry};
pub mod typeck;
use core::cmp;
@ -63,12 +66,6 @@ impl<'a> From<&'a EvEqSourceSpan> for SourceSpan {
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Record<V> {
pub span: EvEqSourceSpan,
pub fields: Vec<(Option<Box<str>>, V)>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
TyTy,
@ -115,94 +112,6 @@ pub enum Expr {
},
}
impl<T: Parse> MaybeParse for Record<T> {
const DFL_CTX: &'static str = "record";
fn maybe_parse(env: &mut ParseEnv<'_>) -> Result<Option<Self>, Perr> {
let start_offset = match env.lxr.got(Tok::LBrace) {
None => return Ok(None),
Some(x) => x,
};
let mut fields: Vec<(Option<Box<str>>, _)> = Vec::new();
loop {
let lxrbak = env.lxr.clone();
let name = {
let Token { kind, offset } = env.lxr.next_in_noeof("record")?;
if let Tok::DotIdent(i) = kind {
if env.lxr.expect(Tok::Assign, "record =").is_ok() {
if fields
.iter()
.find(|(j, _)| j.as_ref() == Some(&i))
.is_some()
{
env.lxr = lxrbak;
return Err(Perr {
offset: usize::try_from(offset).unwrap(),
kind: Pek::RcdDupIdent(i),
});
}
Some(i)
} else {
None
}
} else if let Tok::RBrace = kind {
env.lxr = lxrbak;
break;
} else {
None
}
};
if name.is_none() {
// backtrack
env.lxr = lxrbak;
}
let expr = T::parse(env)?;
env.lxr.expect(Tok::SemiColon, "record ;")?;
fields.push((name, expr));
}
let end_offset = env.lxr.expect(Tok::RBrace, "record")?;
Ok(Some(Record {
span: (usize::try_from(start_offset).unwrap()..usize::try_from(end_offset).unwrap())
.into(),
fields,
}))
}
}
pub enum RecordEntry<'a> {
Name(&'a str),
Ref(usize),
}
impl<T> Record<T> {
pub fn lookup_mut(&mut self, name: RecordEntry<'_>) -> Option<&mut T> {
match name {
RecordEntry::Name(name) => self
.fields
.iter_mut()
.find(|(j, _)| j.as_ref().map(|x| &**x) == Some(name)),
RecordEntry::Ref(i) => self.fields.get_mut(i),
}
.map(|x| &mut x.1)
}
pub fn lookup(&self, name: RecordEntry<'_>) -> Option<&T> {
match name {
RecordEntry::Name(name) => self
.fields
.iter()
.find(|(j, _)| j.as_ref().map(|x| &**x) == Some(name)),
RecordEntry::Ref(i) => self.fields.get(i),
}
.map(|x| &x.1)
}
}
fn parse_minexpr(env: &mut ParseEnv<'_>) -> Result<Expr, Perr> {
let Token {
offset: fi_offset,

View file

@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: 2023 Alain Zscheile <fogti+devel@ytrizja.de>
*
* SPDX-License-Identifier: Apache-2.0
*/
use crate::parser::{
Env as ParseEnv, Error as Perr, ErrorKind as Pek, MaybeParse, Parse, Token, TokenKind as Tok,
};
use crate::EvEqSourceSpan;
#[derive(Clone, Debug, PartialEq)]
pub struct Record<V> {
pub span: EvEqSourceSpan,
pub fields: Vec<(Option<Box<str>>, V)>,
}
impl<T: Parse> MaybeParse for Record<T> {
const DFL_CTX: &'static str = "record";
fn maybe_parse(env: &mut ParseEnv<'_>) -> Result<Option<Self>, Perr> {
let start_offset = match env.lxr.got(Tok::LBrace) {
None => return Ok(None),
Some(x) => x,
};
let mut fields: Vec<(Option<Box<str>>, _)> = Vec::new();
loop {
let lxrbak = env.lxr.clone();
let name = {
let Token { kind, offset } = env.lxr.next_in_noeof("record")?;
if let Tok::DotIdent(i) = kind {
if env.lxr.expect(Tok::Assign, "record =").is_ok() {
if fields
.iter()
.find(|(j, _)| j.as_ref() == Some(&i))
.is_some()
{
env.lxr = lxrbak;
return Err(Perr {
offset: usize::try_from(offset).unwrap(),
kind: Pek::RcdDupIdent(i),
});
}
Some(i)
} else {
None
}
} else if let Tok::RBrace = kind {
env.lxr = lxrbak;
break;
} else {
None
}
};
if name.is_none() {
// backtrack
env.lxr = lxrbak;
}
let expr = T::parse(env)?;
env.lxr.expect(Tok::SemiColon, "record ;")?;
fields.push((name, expr));
}
let end_offset = env.lxr.expect(Tok::RBrace, "record")?;
Ok(Some(Record {
span: (usize::try_from(start_offset).unwrap()..usize::try_from(end_offset).unwrap())
.into(),
fields,
}))
}
}
pub enum RecordEntry<'a> {
Name(&'a str),
Ref(usize),
}
impl<T> Record<T> {
pub fn lookup_mut(&mut self, name: RecordEntry<'_>) -> Option<&mut T> {
match name {
RecordEntry::Name(name) => self
.fields
.iter_mut()
.find(|(j, _)| j.as_ref().map(|x| &**x) == Some(name)),
RecordEntry::Ref(i) => self.fields.get_mut(i),
}
.map(|x| &mut x.1)
}
pub fn lookup(&self, name: RecordEntry<'_>) -> Option<&T> {
match name {
RecordEntry::Name(name) => self
.fields
.iter()
.find(|(j, _)| j.as_ref().map(|x| &**x) == Some(name)),
RecordEntry::Ref(i) => self.fields.get(i),
}
.map(|x| &x.1)
}
}