put record stuff into separate file
This commit is contained in:
parent
bbebc9a518
commit
5e776b963d
|
@ -13,6 +13,9 @@ use parser::{
|
||||||
mod pat;
|
mod pat;
|
||||||
pub use pat::{FullPattern, Pattern};
|
pub use pat::{FullPattern, Pattern};
|
||||||
|
|
||||||
|
mod record;
|
||||||
|
pub use record::{Record, RecordEntry};
|
||||||
|
|
||||||
pub mod typeck;
|
pub mod typeck;
|
||||||
|
|
||||||
use core::cmp;
|
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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
TyTy,
|
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> {
|
fn parse_minexpr(env: &mut ParseEnv<'_>) -> Result<Expr, Perr> {
|
||||||
let Token {
|
let Token {
|
||||||
offset: fi_offset,
|
offset: fi_offset,
|
||||||
|
|
104
crates/yn-qgy4hbz-core/src/record.rs
Normal file
104
crates/yn-qgy4hbz-core/src/record.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue