diff --git a/tamer/src/nir.rs b/tamer/src/nir.rs index 7687c775..6f768f76 100644 --- a/tamer/src/nir.rs +++ b/tamer/src/nir.rs @@ -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 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; - -impl TryFrom for Literal { - type Error = NirAttrParseError; - - fn try_from(attr: Attr) -> Result { - 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( + value: SPair, +) -> Result { + 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 { match self { - Self::LiteralMismatch(_, span, expected) => span + Self::LiteralMismatch(span, expected) => span .error(format!("expecting {}", TtQuote::wrap(expected))) .into(), } diff --git a/tamer/src/nir/air.rs b/tamer/src/nir/air.rs index 5a6678de..3e27923e 100644 --- a/tamer/src/nir/air.rs +++ b/tamer/src/nir/air.rs @@ -245,6 +245,8 @@ impl ParseState for NirToAir { (Ready, Todo(..) | TodoAttr(..)) => { Transition(Ready).ok(Air::Todo(UNKNOWN_SPAN)) } + + (st, Noop(_)) => Transition(st).incomplete(), } } diff --git a/tamer/src/nir/parse.rs b/tamer/src/nir/parse.rs index 31f1bc1e..2de373c1 100644 --- a/tamer/src/nir/parse.rs +++ b/tamer/src/nir/parse.rs @@ -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, diff --git a/tamer/src/xir/parse/ele.rs b/tamer/src/xir/parse/ele.rs index ab515af0..6c5918c8 100644 --- a/tamer/src/xir/parse/ele.rs +++ b/tamer/src/xir/parse/ele.rs @@ -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 diff --git a/tamer/src/xir/parse/error.rs b/tamer/src/xir/parse/error.rs index 10561c5d..d6ad9101 100644 --- a/tamer/src/xir/parse/error.rs +++ b/tamer/src/xir/parse/error.rs @@ -21,6 +21,7 @@ use core::fmt::Debug; use std::{ + convert::Infallible, error::Error, fmt::{Display, Formatter}, marker::PhantomData, @@ -71,6 +72,12 @@ impl Error for NtError { } } +impl From for NtError { + fn from(_value: Infallible) -> Self { + unreachable!("From") + } +} + impl Display for NtError { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { use crate::xir::fmt::{TtCloseXmlEle, TtOpenXmlEle};