@@ -6,36 +6,38 @@ use std::{
66use indexmap:: { IndexMap , IndexSet } ;
77
88use 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.
1619pub struct ASTWithValidityInfo {
17- yacc_kind : Option < YaccKind > ,
20+ yacc_kind : YaccKind ,
1821 ast : GrammarAST ,
19- errs : Vec < ParserError > ,
22+ errs : Vec < YaccGrammarError > ,
2023}
2124
2225impl 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}
0 commit comments