tamer: Re-introduce literal parsing for xmlns in NIR for PackageStmt

This _only_ re-introduces for PackageStmt since that's all I have tests for
at present.  More will be re-added later.

They were previously removed when the attribute parsing was upended in
`ele_parse!`.

This does lose the attribute name, compared to before; that'll ideally be
re-added, and I'll explore options for doing so later, since I also want
them in other contexts.  But it needs to be done generically (not
XML-related).

This had to be done before blowing up on TODOs, or system tests would fail.

DEV-13708
main
Mike Gerwitz 2023-04-10 15:23:13 -04:00
parent acafe91ab9
commit 647e0ccbbd
5 changed files with 56 additions and 28 deletions

View File

@ -63,7 +63,6 @@ use crate::{
sym::SymbolId,
xir::{
attr::{Attr, AttrSpan},
fmt::TtXmlAttr,
QName,
},
};
@ -145,6 +144,19 @@ pub enum Nir {
/// it may represent literate documentation or a literal in a
/// metavariable definition.
Text(SPair),
/// "No-op" (no operation) that does nothing.
///
/// Since this is taking user input and effectively discarding it,
/// this contains a [`Span`],
/// so that we can clearly see the source code associated with what we
/// chose to discard.
///
/// Ideally this can be eliminated in the future by causing an
/// incomplete parse,
/// which is all this does in the end.
/// See its uses for more information.
Noop(Span),
}
impl Nir {
@ -167,6 +179,8 @@ impl Nir {
BindIdent(spair) | RefSubject(spair) | Ref(spair) | Desc(spair)
| Text(spair) => Some(spair.symbol()),
Noop(_) => None,
}
}
}
@ -200,6 +214,8 @@ impl Functor<SymbolId> for Nir {
Ref(spair) => Ref(spair.map(f)),
Desc(spair) => Desc(spair.map(f)),
Text(spair) => Text(spair.map(f)),
Noop(_) => self,
}
}
}
@ -321,6 +337,11 @@ impl Token for Nir {
BindIdent(spair) | RefSubject(spair) | Ref(spair) | Desc(spair)
| Text(spair) => spair.span(),
// A no-op is discarding user input,
// so we still want to know where that is so that we can
// explicitly inquire about and report on it.
Noop(span) => *span,
}
}
}
@ -352,6 +373,8 @@ impl Display for Nir {
// need to determine how to handle newlines and other types of
// output.
Text(_) => write!(f, "text"),
Noop(_) => write!(f, "no-op"),
}
}
}
@ -511,21 +534,14 @@ pub enum PkgType {
Mod,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Literal<const S: SymbolId>;
impl<const S: SymbolId> TryFrom<Attr> for Literal<S> {
type Error = NirAttrParseError;
fn try_from(attr: Attr) -> Result<Self, Self::Error> {
match attr {
Attr(_, val, _) if val == S => Ok(Literal),
Attr(name, _, aspan) => Err(NirAttrParseError::LiteralMismatch(
name,
aspan.value_span(),
S,
)),
}
/// Assert that a literal value `S` was provided,
/// yielding a [`Nir::Noop`] if successful.
pub fn literal<const S: SymbolId>(
value: SPair,
) -> Result<Nir, NirAttrParseError> {
match value {
SPair(val, span) if val == S => Ok(Nir::Noop(span)),
_ => Err(NirAttrParseError::LiteralMismatch(value.span(), S)),
}
}
@ -539,7 +555,7 @@ type ExpectedSymbolId = SymbolId;
#[derive(Debug, PartialEq, Eq)]
pub enum NirAttrParseError {
LiteralMismatch(QName, Span, ExpectedSymbolId),
LiteralMismatch(Span, ExpectedSymbolId),
}
impl Error for NirAttrParseError {
@ -551,8 +567,8 @@ impl Error for NirAttrParseError {
impl Display for NirAttrParseError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::LiteralMismatch(name, _, _) => {
write!(f, "unexpected value for {}", TtXmlAttr::wrap(name),)
Self::LiteralMismatch(_, expected) => {
write!(f, "expected literal {}", TtQuote::wrap(expected),)
}
}
}
@ -561,7 +577,7 @@ impl Display for NirAttrParseError {
impl Diagnostic for NirAttrParseError {
fn describe(&self) -> Vec<crate::diagnose::AnnotatedSpan> {
match self {
Self::LiteralMismatch(_, span, expected) => span
Self::LiteralMismatch(span, expected) => span
.error(format!("expecting {}", TtQuote::wrap(expected)))
.into(),
}

View File

@ -245,6 +245,8 @@ impl ParseState for NirToAir {
(Ready, Todo(..) | TodoAttr(..)) => {
Transition(Ready).ok(Air::Todo(UNKNOWN_SPAN))
}
(st, Noop(_)) => Transition(st).incomplete(),
}
}

View File

@ -119,6 +119,7 @@
use super::{Nir::*, *};
use crate::{
ele_parse,
sym::st::raw::*,
xir::st::{prefix::*, qname::*},
};
@ -227,15 +228,15 @@ ele_parse! {
/// different package types.
PackageStmt := QN_PACKAGE(_, ospan) {
@ {
QN_XMLNS => TodoAttr,
QN_XMLNS_C => TodoAttr,
QN_XMLNS_T => TodoAttr,
QN_XMLNS => literal::<{URI_LV_RATER}>,
QN_XMLNS_C => literal::<{URI_LV_CALC}>,
QN_XMLNS_T => literal::<{URI_LV_TPL}>,
// TODO: Having trouble getting rid of `@xmlns:lv` using Saxon
// for `progui-pkg`,
// so just allow for now.
// It can't actually be used on nodes.
QN_XMLNS_LV => TodoAttr,
QN_XMLNS_LV => literal::<{URI_LV_RATER}>,
QN_ID => TodoAttr,
QN_TITLE => TodoAttr,

View File

@ -507,10 +507,12 @@ macro_rules! ele_parse {
let $open_span = span;
)?
Transition(Self(Attrs(
(qname, span, depth),
parse_attrs(qname, span)
))).ok(<$objty>::from($attrmap))
<$objty>::try_from($attrmap)
.map($crate::parse::ParseStatus::Object)
.transition(Self(Attrs(
(qname, span, depth),
parse_attrs(qname, span)
)))
},
// We only attempt recovery when encountering an

View File

@ -21,6 +21,7 @@
use core::fmt::Debug;
use std::{
convert::Infallible,
error::Error,
fmt::{Display, Formatter},
marker::PhantomData,
@ -71,6 +72,12 @@ impl<NT: Nt> Error for NtError<NT> {
}
}
impl<NT: Nt> From<Infallible> for NtError<NT> {
fn from(_value: Infallible) -> Self {
unreachable!("From<Infallible>")
}
}
impl<NT: Nt> Display for NtError<NT> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
use crate::xir::fmt::{TtCloseXmlEle, TtOpenXmlEle};