Skip to content

Commit 0639f7e

Browse files
committed
First take at removing HeaderError from YaccParser internals
1 parent 04ae392 commit 0639f7e

18 files changed

Lines changed: 258 additions & 345 deletions

File tree

cfgrammar/src/lib/markmap.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::borrow::Borrow;
2+
use std::error::Error;
3+
use std::fmt;
24

35
// MarkMap is a key value data structure that uses an API similar to that of
46
// `std::collections::HashMap` and `std::collections::BTreeMap`.
@@ -47,6 +49,18 @@ pub enum MergeError<K, V> {
4749
Exclusivity(K, V),
4850
}
4951

52+
impl<K: fmt::Debug, V: fmt::Debug> Error for MergeError<K, V> {}
53+
54+
impl<K: fmt::Debug, V> fmt::Display for MergeError<K, V> {
55+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56+
match self {
57+
Self::Exclusivity(k, _) => {
58+
write!(f, "Merge behavior forbids overriding key: {:?}", k)
59+
}
60+
}
61+
}
62+
}
63+
5064
/// A view into a single entry in a `MarkMap`, which may either be vacant or occupied.
5165
#[doc(hidden)]
5266
pub enum Entry<'a, K, V> {

cfgrammar/src/lib/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ mod idxnewtype;
6161
pub mod markmap;
6262
pub mod newlinecache;
6363
pub mod span;
64-
#[cfg(test)]
65-
pub mod test_utils;
6664
pub mod yacc;
6765

6866
pub use newlinecache::NewlineCache;

cfgrammar/src/lib/test_utils.rs

Lines changed: 0 additions & 25 deletions
This file was deleted.

cfgrammar/src/lib/yacc/ast.rs

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,38 @@ use std::{
66
use indexmap::{IndexMap, IndexSet};
77

88
use super::{
9-
parser::YaccParser, ParserError, Precedence, YaccGrammarError, YaccGrammarErrorKind,
10-
YaccGrammarWarning, YaccGrammarWarningKind, YaccKind,
9+
parser::YaccParser, Precedence, YaccGrammarError, YaccGrammarErrorKind, YaccGrammarWarning,
10+
YaccGrammarWarningKind, YaccKind,
1111
};
1212

13-
use crate::{header::Header, Span};
13+
use crate::{
14+
header::{GrmtoolsSectionParser, HeaderError, HeaderErrorKind},
15+
Span,
16+
};
1417
/// Contains a `GrammarAST` structure produced from a grammar source file.
1518
/// As well as any errors which occurred during the construction of the AST.
1619
pub struct ASTWithValidityInfo {
17-
yacc_kind: Option<YaccKind>,
20+
yacc_kind: YaccKind,
1821
ast: GrammarAST,
19-
errs: Vec<ParserError>,
22+
errs: Vec<YaccGrammarError>,
2023
}
2124

2225
impl ASTWithValidityInfo {
2326
/// Parses a source file into an AST, returning an ast and any errors that were
2427
/// encountered during the construction of it. The `ASTWithValidityInfo` can be
2528
/// then unused to construct a `YaccGrammar`, which will either produce an
2629
/// `Ok(YaccGrammar)` or an `Err` which includes these errors.
27-
pub fn new(header: &mut Header, s: &str) -> Self {
30+
///
31+
/// This function ignores the `%grmtools` section entirely, assuming that the caller has
32+
/// already extracted the `YaccKind` if any.
33+
pub fn new(yacc_kind: YaccKind, s: &str) -> Self {
2834
let mut errs = Vec::new();
29-
let (yacc_kind, ast) = {
30-
let mut yp = YaccParser::new(header, s.to_string());
35+
let ast = {
36+
let mut yp = YaccParser::new(yacc_kind, s);
3137
yp.parse().map_err(|e| errs.extend(e)).ok();
32-
let (yacc_kind, mut ast) = yp.build();
33-
if yacc_kind.is_some() {
34-
ast.complete_and_validate()
35-
.map_err(|e| errs.push(e.into()))
36-
.ok();
37-
}
38-
(yacc_kind, ast)
38+
let mut ast = yp.build();
39+
ast.complete_and_validate().map_err(|e| errs.push(e)).ok();
40+
ast
3941
};
4042
ASTWithValidityInfo {
4143
ast,
@@ -44,6 +46,33 @@ impl ASTWithValidityInfo {
4446
}
4547
}
4648

49+
/// Parses the `%grmtools section` expecting it to contain a `yacckind` entry.
50+
pub fn from_src(src: &str) -> Result<Self, Vec<HeaderError>> {
51+
let mut errs = Vec::new();
52+
let (header, _) = GrmtoolsSectionParser::new(src, true).parse()?;
53+
if let Some((_, yk_val)) = header.get("yacckind") {
54+
let yacc_kind = YaccKind::try_from(yk_val).map_err(|e| vec![e])?;
55+
let ast = {
56+
// We don't want to strip off the header so that span's will be correct.
57+
let mut yp = YaccParser::new(yacc_kind, src);
58+
yp.parse().map_err(|e| errs.extend(e)).ok();
59+
let mut ast = yp.build();
60+
ast.complete_and_validate().map_err(|e| errs.push(e)).ok();
61+
ast
62+
};
63+
Ok(ASTWithValidityInfo {
64+
ast,
65+
errs,
66+
yacc_kind,
67+
})
68+
} else {
69+
Err(vec![HeaderError {
70+
kind: HeaderErrorKind::InvalidEntry("yacckind"),
71+
locations: vec![],
72+
}])
73+
}
74+
}
75+
4776
/// Returns a `GrammarAST` constructed as the result of parsing a source file.
4877
/// When errors have occurred and `is_valid` returns false, this AST is the
4978
/// subset of the source file which parsed correctly while not encountering
@@ -59,12 +88,12 @@ impl ASTWithValidityInfo {
5988
}
6089

6190
/// Returns the `YaccKind` that was used to parse the `GrammarAST`.
62-
pub fn yacc_kind(&self) -> Option<YaccKind> {
91+
pub fn yacc_kind(&self) -> YaccKind {
6392
self.yacc_kind
6493
}
6594

6695
/// Returns all errors which were encountered during AST construction.
67-
pub fn errors(&self) -> &[ParserError] {
96+
pub fn errors(&self) -> &[YaccGrammarError] {
6897
self.errs.as_slice()
6998
}
7099
}

cfgrammar/src/lib/yacc/firsts.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ mod test {
147147
super::{YaccGrammar, YaccKind, YaccOriginalActionKind},
148148
YaccFirsts,
149149
};
150-
use crate::test_utils::*;
151150
use num_traits::{AsPrimitive, PrimInt, Unsigned};
152151

153152
fn has<StorageT: 'static + PrimInt + Unsigned>(
@@ -182,7 +181,7 @@ mod test {
182181
#[test]
183182
fn test_first() {
184183
let grm = YaccGrammar::new(
185-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
184+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
186185
"
187186
%start C
188187
%token c d
@@ -204,7 +203,7 @@ mod test {
204203
#[test]
205204
fn test_first_no_subsequent_rules() {
206205
let grm = YaccGrammar::new(
207-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
206+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
208207
"
209208
%start C
210209
%token c d
@@ -222,7 +221,7 @@ mod test {
222221
#[test]
223222
fn test_first_epsilon() {
224223
let grm = YaccGrammar::new(
225-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
224+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
226225
"
227226
%start A
228227
%token a b c
@@ -243,7 +242,7 @@ mod test {
243242
#[test]
244243
fn test_last_epsilon() {
245244
let grm = YaccGrammar::new(
246-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
245+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
247246
"
248247
%start A
249248
%token b c
@@ -263,7 +262,7 @@ mod test {
263262
#[test]
264263
fn test_first_no_multiples() {
265264
let grm = YaccGrammar::new(
266-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
265+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
267266
"
268267
%start A
269268
%token b c
@@ -279,7 +278,7 @@ mod test {
279278

280279
fn eco_grammar() -> YaccGrammar {
281280
YaccGrammar::new(
282-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
281+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
283282
"
284283
%start S
285284
%token a b c d f
@@ -310,7 +309,7 @@ mod test {
310309
#[test]
311310
fn test_first_from_eco_bug() {
312311
let grm = YaccGrammar::new(
313-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
312+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
314313
"
315314
%start E
316315
%token a b c d e f

cfgrammar/src/lib/yacc/follows.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ mod test {
119119
super::{YaccGrammar, YaccKind, YaccOriginalActionKind},
120120
YaccFollows,
121121
};
122-
use crate::test_utils::*;
123122
use num_traits::{AsPrimitive, PrimInt, Unsigned};
124123

125124
fn has<StorageT: 'static + PrimInt + Unsigned>(
@@ -151,7 +150,7 @@ mod test {
151150
fn test_follow() {
152151
// Adapted from p2 of https://www.cs.uaf.edu/~cs331/notes/FirstFollow.pdf
153152
let grm = YaccGrammar::new(
154-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
153+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
155154
"
156155
%start E
157156
%%
@@ -175,7 +174,7 @@ mod test {
175174
fn test_follow2() {
176175
// Adapted from https://www.l2f.inesc-id.pt/~david/w/pt/Top-Down_Parsing/Exercise_5:_Test_2010/07/01
177176
let grm = YaccGrammar::new(
178-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
177+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
179178
"
180179
%start A
181180
%%
@@ -198,7 +197,7 @@ mod test {
198197
#[test]
199198
fn test_follow3() {
200199
let grm = YaccGrammar::new(
201-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
200+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
202201
"
203202
%start S
204203
%%
@@ -215,7 +214,7 @@ mod test {
215214
#[test]
216215
fn test_follow_corchuelo() {
217216
let grm = YaccGrammar::new(
218-
&mut header_for_yacckind!(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)),
217+
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
219218
"
220219
%start E
221220
%%

0 commit comments

Comments
 (0)