tamer: obj::xmlo::reader: Parse package attributes

Finally we get to do some actual parsing with all of the preparatory work!

This means that we're finally ready to fully replace the old XmloReader,
provided that I'm okay with some boilerplate / lack of abstractions for
now (and I am, because all I've been doing is working on abstractions to
prepare lowering operations).

DEV-10863
main
Mike Gerwitz 2022-03-23 16:48:51 -04:00
parent ad8616aaa1
commit fab7b16ea0
2 changed files with 111 additions and 55 deletions

View File

@ -45,19 +45,26 @@ mod new {
//! it exists to make feature-flagging less confusing and error-prone.
use super::{XmloError, XmloEvent};
use crate::parse::{ParseState, Transition};
use crate::parse::{ParseState, Transition, TransitionResult};
use crate::sym::st::*;
use crate::xir::attr::Attr;
use crate::xir::flat::Object as Xirf;
qname_const! {
QN_LV_PACKAGE: L_LV:L_PACKAGE,
QN_PACKAGE: :L_PACKAGE,
QN_NAME: :L_NAME,
QN_UUROOTPATH: :L_UUROOTPATH,
QN_PROGRAM: :L_PROGRAM,
QN_PREPROC_ELIG_CLASS_YIELDS: L_PREPROC:L_ELIG_CLASS_YIELDS,
}
#[derive(Debug, Default, PartialEq, Eq)]
pub enum XmloReader {
#[default]
Ready,
Package,
Done,
}
impl ParseState for XmloReader {
@ -65,24 +72,40 @@ mod new {
type Object = XmloEvent;
type Error = XmloError;
fn parse_token(
self,
tok: Self::Token,
) -> crate::parse::TransitionResult<Self> {
use XmloReader::Ready;
fn parse_token(self, tok: Self::Token) -> TransitionResult<Self> {
use XmloReader::{Done, Package, Ready};
match (self, tok) {
(Ready, Xirf::Open(QN_LV_PACKAGE | QN_PACKAGE, _, _)) => {
todo!("PackageAttrs removed");
(Ready, Xirf::Open(QN_LV_PACKAGE | QN_PACKAGE, ..)) => {
Transition(Package).incomplete()
}
(Ready, _) => Transition(Ready).err(XmloError::UnexpectedRoot),
(Package, Xirf::Attr(Attr(name, value, _))) => {
Transition(Package).with(match name {
QN_NAME => XmloEvent::PkgName(value),
QN_UUROOTPATH => XmloEvent::PkgRootPath(value),
QN_PROGRAM => XmloEvent::PkgProgramFlag,
QN_PREPROC_ELIG_CLASS_YIELDS => {
XmloEvent::PkgEligClassYields(value)
}
// Ignore unknown attributes for now to maintain BC,
// since no strict xmlo schema has been defined.
_ => return Transition(Package).incomplete(),
})
}
// Empty package (should we allow this?);
// XIRF guarantees a matching closing tag.
(Package, Xirf::Close(..)) => Transition(Done).incomplete(),
todo => todo!("{todo:?}"),
}
}
fn is_accepting(&self) -> bool {
// TODO
todo!("XmloReader::is_accepting")
*self == Self::Done
}
}
}

View File

@ -22,14 +22,20 @@ use std::assert_matches::assert_matches;
use super::*;
use crate::{
convert::ExpectInto,
parse::{ParseError, ParseState},
span::DUMMY_SPAN as DS,
parse::{ParseError, ParseState, Parsed},
span::{Span, DUMMY_SPAN},
xir::{
attr::Attr,
flat::{Depth, Object as Xirf},
QName,
},
};
const S1: Span = DUMMY_SPAN;
const S2: Span = S1.offset_add(1).unwrap();
const S3: Span = S2.offset_add(1).unwrap();
const S4: Span = S3.offset_add(1).unwrap();
type Sut = XmloReader;
#[test]
@ -37,7 +43,7 @@ fn fails_on_invalid_root() {
let mut sut = Sut::parse(
[Xirf::Open(
"not-a-valid-package-node".unwrap_into(),
DS,
S1,
Depth(0),
)]
.into_iter(),
@ -49,54 +55,81 @@ fn fails_on_invalid_root() {
);
}
//#[test]
fn _parses_package_attrs() {
fn common_parses_package_attrs(package: QName) {
let name = "pkgroot".into();
let relroot = "../../".into();
let elig = "elig-class-yields".into();
let mut sut = Sut::parse(
[
Xirf::Open("package".unwrap_into(), DS, Depth(0)),
Xirf::Attr(Attr::new("name".unwrap_into(), name, (DS, DS))),
Xirf::Attr(Attr::new(
"__rootpath".unwrap_into(),
relroot,
(DS, DS),
)),
Xirf::Attr(Attr::new(
"program".unwrap_into(),
crate::sym::st::raw::L_TRUE,
(DS, DS),
)),
Xirf::Attr(Attr::new(
("preproc", "elig-class-yields").unwrap_into(),
elig,
(DS, DS),
)),
]
.into_iter(),
let toks = [
Xirf::Open(package, S1, Depth(0)),
Xirf::Attr(Attr::new("name".unwrap_into(), name, (S2, S3))),
Xirf::Attr(Attr::new("__rootpath".unwrap_into(), relroot, (S2, S3))),
Xirf::Attr(Attr::new(
"program".unwrap_into(),
crate::sym::st::raw::L_TRUE,
(S3, S4),
)),
Xirf::Attr(Attr::new(
("preproc", "elig-class-yields").unwrap_into(),
elig,
(S3, S4),
)),
Xirf::Close(Some(package), S2, Depth(0)),
]
.into_iter();
let sut = Sut::parse(toks);
assert_eq!(
Ok(vec![
Parsed::Incomplete,
Parsed::Object(XmloEvent::PkgName(name)),
Parsed::Object(XmloEvent::PkgRootPath(relroot)),
Parsed::Object(XmloEvent::PkgProgramFlag),
Parsed::Object(XmloEvent::PkgEligClassYields(elig)),
Parsed::Incomplete,
]),
sut.collect(),
);
let _result = sut.next();
todo!()
}
// The linker does not [yet] parse namespaces.
//#[test]
fn _parses_package_attrs_with_ns_prefix() {
let name = "pkgrootns".into();
let mut sut = Sut::parse(
[
Xirf::Open(("lv", "package").unwrap_into(), DS, Depth(0)),
Xirf::Attr(Attr::new("name".unwrap_into(), name, (DS, DS))),
]
.into_iter(),
);
let _result = sut.next();
todo!()
#[test]
fn parses_package_attrs_without_ns_prefix() {
common_parses_package_attrs("package".unwrap_into());
}
// The linker does not [yet] parse namespaces.
#[test]
fn parses_package_attrs_with_ns_prefix() {
common_parses_package_attrs(("lv", "package").unwrap_into());
}
// Maintains BC with existing system,
// but this ought to reject in the future.
#[test]
fn ignores_unknown_package_attr() {
let package = "package".unwrap_into();
let name = "pkgroot".into();
let toks = [
Xirf::Open(package, S1, Depth(0)),
Xirf::Attr(Attr::new("name".unwrap_into(), name, (S2, S3))),
// This is ignored.
Xirf::Attr(Attr::new("unknown".unwrap_into(), name, (S2, S3))),
Xirf::Close(Some(package), S2, Depth(0)),
]
.into_iter();
let sut = Sut::parse(toks);
assert_eq!(
Ok(vec![
Parsed::Incomplete,
Parsed::Object(XmloEvent::PkgName(name)),
Parsed::Incomplete, // The unknown attribute
Parsed::Incomplete,
]),
sut.collect(),
);
}