diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/pest_meta/src/parser.rs | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/pest_meta/src/parser.rs')
-rw-r--r-- | vendor/pest_meta/src/parser.rs | 146 |
1 files changed, 129 insertions, 17 deletions
diff --git a/vendor/pest_meta/src/parser.rs b/vendor/pest_meta/src/parser.rs index eb957a163..a4e8d1b33 100644 --- a/vendor/pest_meta/src/parser.rs +++ b/vendor/pest_meta/src/parser.rs @@ -15,20 +15,18 @@ use std::iter::Peekable; use pest::error::{Error, ErrorVariant}; use pest::iterators::{Pair, Pairs}; use pest::pratt_parser::{Assoc, Op, PrattParser}; -use pest::{Parser, Span}; +use pest::{Parser, Position, Span}; use crate::ast::{Expr, Rule as AstRule, RuleType}; use crate::validator; -/// TODO: fix the generator to at least add explicit lifetimes -#[allow( - missing_docs, - unused_attributes, - elided_lifetimes_in_paths, - unused_qualifications -)] +#[allow(missing_docs, unused_qualifications)] mod grammar { + #[cfg(not(feature = "not-bootstrap-in-src"))] include!("grammar.rs"); + + #[cfg(feature = "not-bootstrap-in-src")] + include!(concat!(env!("OUT_DIR"), "/__pest_grammar.rs")); } pub use self::grammar::*; @@ -76,7 +74,6 @@ impl<'i> ParserNode<'i> { } match node.expr { - // TODO: Use box syntax when it gets stabilized. ParserExpr::PosPred(node) => { filter_internal(*node, f, result); } @@ -164,6 +161,9 @@ pub enum ParserExpr<'i> { RepMinMax(Box<ParserNode<'i>>, u32, u32), /// Matches an expression and pushes it to the stack, e.g. `push(e)` Push(Box<ParserNode<'i>>), + /// Matches an expression and assigns a label to it, e.g. #label = exp + #[cfg(feature = "grammar-extras")] + NodeTag(Box<ParserNode<'i>>, String), } fn convert_rule(rule: ParserRule<'_>) -> AstRule { @@ -199,6 +199,8 @@ fn convert_node(node: ParserNode<'_>) -> Expr { Expr::RepMinMax(Box::new(convert_node(*node)), min, max) } ParserExpr::Push(node) => Expr::Push(Box::new(convert_node(*node))), + #[cfg(feature = "grammar-extras")] + ParserExpr::NodeTag(node, tag) => Expr::NodeTag(Box::new(convert_node(*node)), tag), } } @@ -305,6 +307,29 @@ fn consume_rules_with_spans( .collect() } +fn get_node_tag<'i>( + pairs: &mut Peekable<Pairs<'i, Rule>>, +) -> (Pair<'i, Rule>, Option<(String, Position<'i>)>) { + let pair_or_tag = pairs.next().unwrap(); + if let Some(next_pair) = pairs.peek() { + if next_pair.as_rule() == Rule::assignment_operator { + pairs.next().unwrap(); + let pair = pairs.next().unwrap(); + ( + pair, + Some(( + pair_or_tag.as_str()[1..].to_string(), + pair_or_tag.as_span().start_pos(), + )), + ) + } else { + (pair_or_tag, None) + } + } else { + (pair_or_tag, None) + } +} + fn consume_expr<'i>( pairs: Peekable<Pairs<'i, Rule>>, pratt: &PrattParser<Rule>, @@ -313,7 +338,10 @@ fn consume_expr<'i>( mut pairs: Peekable<Pairs<'i, Rule>>, pratt: &PrattParser<Rule>, ) -> Result<ParserNode<'i>, Vec<Error<Rule>>> { - let pair = pairs.next().unwrap(); + #[cfg(feature = "grammar-extras")] + let (pair, tag_start) = get_node_tag(&mut pairs); + #[cfg(not(feature = "grammar-extras"))] + let (pair, _tag_start) = get_node_tag(&mut pairs); let node = match pair.as_rule() { Rule::opening_paren => { @@ -370,7 +398,7 @@ fn consume_expr<'i>( pairs.next().unwrap(); // .. pair_start.as_str().parse().unwrap() } - _ => unreachable!(), + _ => unreachable!("peek start"), }; let pair_end = pairs.next().unwrap(); // integer or } let end: Option<i32> = match pair_end.as_rule() { @@ -379,7 +407,7 @@ fn consume_expr<'i>( pairs.next().unwrap(); // } Some(pair_end.as_str().parse().unwrap()) } - _ => unreachable!(), + _ => unreachable!("peek end"), }; ParserNode { expr: ParserExpr::PeekSlice(start, end), @@ -422,7 +450,7 @@ fn consume_expr<'i>( span: start_pos.span(&end_pos), } } - _ => unreachable!(), + x => unreachable!("other rule: {:?}", x), }; pairs.fold( @@ -600,7 +628,7 @@ fn consume_expr<'i>( span: start.span(&pair.as_span().end_pos()), } } - _ => unreachable!(), + rule => unreachable!("node: {:?}", rule), }; Ok(node) @@ -608,7 +636,17 @@ fn consume_expr<'i>( )? } }; - + #[cfg(feature = "grammar-extras")] + if let Some((tag, start)) = tag_start { + let span = start.span(&node.span.end_pos()); + Ok(ParserNode { + expr: ParserExpr::NodeTag(Box::new(node), tag), + span, + }) + } else { + Ok(node) + } + #[cfg(not(feature = "grammar-extras"))] Ok(node) } @@ -640,7 +678,7 @@ fn consume_expr<'i>( span: start.span(&end), }) } - _ => unreachable!(), + _ => unreachable!("infix"), }; pratt.map_primary(term).map_infix(infix).parse(pairs) @@ -1143,7 +1181,7 @@ mod tests { parser: PestParser, input: "0", rule: Rule::grammar_rules, - positives: vec![Rule::grammar_rule, Rule::grammar_doc], + positives: vec![Rule::EOI, Rule::grammar_rule, Rule::grammar_doc], negatives: vec![], pos: 0 }; @@ -1358,6 +1396,80 @@ mod tests { } #[test] + fn node_tag() { + parses_to! { + parser: PestParser, + input: "#a = a", + rule: Rule::expression, + tokens: [ + expression(0, 6, [ + term(0, 6, [ + tag_id(0, 2), + assignment_operator(3, 4), + identifier(5, 6) + ]) + ]) + ] + }; + } + + #[test] + fn incomplete_node_tag() { + fails_with! { + parser: PestParser, + input: "a = { # }", + rule: Rule::grammar_rules, + positives: vec![ + Rule::expression + ], + negatives: vec![], + pos: 6 + }; + } + + #[test] + fn incomplete_node_tag_assignment() { + fails_with! { + parser: PestParser, + input: "a = { #a = }", + rule: Rule::grammar_rules, + positives: vec![ + Rule::opening_paren, + Rule::positive_predicate_operator, + Rule::negative_predicate_operator, + Rule::_push, + Rule::peek_slice, + Rule::identifier, + Rule::insensitive_string, + Rule::quote, + Rule::single_quote + ], + negatives: vec![], + pos: 11 + }; + } + + #[test] + fn incomplete_node_tag_pound_key() { + fails_with! { + parser: PestParser, + input: "a = { a = a }", + rule: Rule::grammar_rules, + positives: vec![ + Rule::opening_brace, + Rule::closing_brace, + Rule::sequence_operator, + Rule::choice_operator, + Rule::optional_operator, + Rule::repeat_operator, + Rule::repeat_once_operator + ], + negatives: vec![], + pos: 8 + }; + } + + #[test] fn ast() { let input = r##" /// This is line comment |