From 2311084748705f8be14de87311c812d038b12f24 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Wed, 15 May 2024 09:12:24 +0100 Subject: [PATCH] Allow `%prec` to define a token in the grammar. Previously if `%prec 'x'` was the first mention of the token `x` then cfgrammar would say "'x' isn't a token" which is clearly incorrect. This commit is maybe best thought of as a quick fix of sorts: it makes `%prec 'x'` define a token `x` if it doesn't already exist. However -- and my memory is completely fuzzy as to whether this is a Yacc compatibility thing or not -- this means that `%prec 'x'` and `%prec x' (i.e. with and without quote marks) have the semantic meaning because `parse_token` treats both interchangeably. This seems consistent with other parts of the grammar even if a little odd. --- cfgrammar/src/lib/yacc/parser.rs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/cfgrammar/src/lib/yacc/parser.rs b/cfgrammar/src/lib/yacc/parser.rs index 576f95f4a..31410da95 100644 --- a/cfgrammar/src/lib/yacc/parser.rs +++ b/cfgrammar/src/lib/yacc/parser.rs @@ -677,12 +677,11 @@ impl YaccParser { syms.push(Symbol::Token(sym, span)); } else if let Some(j) = self.lookahead_is("%prec", i) { i = self.parse_ws(j, true)?; - let (k, sym, _) = self.parse_token(i)?; - if self.ast.tokens.contains(&sym) { - prec = Some(sym); - } else { - return Err(self.mk_error(YaccGrammarErrorKind::PrecNotFollowedByToken, i)); + let (k, sym, span) = self.parse_token(i)?; + if self.ast.tokens.insert(sym.clone()) { + self.ast.spans.push(span); } + prec = Some(sym); i = k; } else if self.lookahead_is("{", i).is_some() { let (j, a) = self.parse_action(i)?; @@ -1736,17 +1735,6 @@ x" src, ) .expect_error_at_line(src, YaccGrammarErrorKind::IllegalString, 3); - - let src = " - %% - S: 'A' %prec B; - B: ; - "; - parse( - YaccKind::Original(YaccOriginalActionKind::GenericParseTree), - src, - ) - .expect_error_at_line(src, YaccGrammarErrorKind::PrecNotFollowedByToken, 3); } #[test]