1- //! Contains utilities for parsing text files, separating lines into
2- //! strings, stubs and solutions so that they can be more easily filtered accordingly
1+ //! Contains utilities for parsing annotated exercise source files, separating lines into
2+ //! strings, stubs and solutions so that they can be more easily filtered later.
33
44use crate :: { Result , TmcError } ;
55use lazy_static:: lazy_static;
6- use log:: debug;
76use regex:: { Captures , Regex } ;
87use std:: io:: { BufRead , BufReader , Read } ;
98
10- // Meta syntaxes for each comment syntax
9+ // rules for finding comments in various languages
1110lazy_static ! {
1211 static ref META_SYNTAXES_C : [ MetaSyntax ; 2 ] = [
1312 MetaSyntax :: new( "//" , None ) ,
@@ -17,7 +16,7 @@ lazy_static! {
1716 static ref META_SYNTAXES_PY : [ MetaSyntax ; 1 ] = [ MetaSyntax :: new( "#" , None ) ] ;
1817}
1918
20- // Used to classify lines of code based on the annotations in the file
19+ /// Used to classify lines of code based on the annotations in the file.
2120#[ derive( Debug , PartialEq , Eq ) ]
2221pub enum MetaString {
2322 String ( String ) ,
@@ -26,7 +25,6 @@ pub enum MetaString {
2625}
2726
2827impl MetaString {
29- // Borrows the underlying line of text
3028 pub fn as_str ( & self ) -> & str {
3129 match self {
3230 Self :: String ( s) => & s,
@@ -36,7 +34,7 @@ impl MetaString {
3634 }
3735}
3836
39- // Contains the needed regexes for a given comment syntax
37+ /// Contains the needed regexes for a given comment syntax.
4038#[ derive( Debug ) ]
4139struct MetaSyntax {
4240 solution_file : Regex ,
@@ -48,11 +46,14 @@ struct MetaSyntax {
4846
4947impl MetaSyntax {
5048 fn new ( comment_start : & ' static str , comment_end : Option < & ' static str > ) -> Self {
49+ // comment patterns
5150 let comment_start_pattern = format ! ( "^(\\ s*){}\\ s*" , comment_start) ;
5251 let comment_end_pattern = match comment_end {
5352 Some ( s) => format ! ( "(.*){}\\ s*" , s) ,
5453 None => "(.*)" . to_string ( ) ,
5554 } ;
55+
56+ // annotation patterns
5657 let solution_file = Regex :: new ( & format ! (
5758 "{}SOLUTION\\ s+FILE{}" ,
5859 comment_start_pattern, comment_end_pattern
@@ -81,7 +82,7 @@ impl MetaSyntax {
8182 }
8283}
8384
84- /// Parses a given text file into an iterator of `MetaString`s
85+ /// Parses a given text file into an iterator of `MetaString`s.
8586#[ derive( Debug ) ]
8687pub struct MetaSyntaxParser < B : BufRead > {
8788 meta_syntaxes : & ' static [ MetaSyntax ] ,
@@ -95,13 +96,14 @@ pub struct MetaSyntaxParser<B: BufRead> {
9596impl < R : Read > MetaSyntaxParser < BufReader < R > > {
9697 pub fn new ( target : R , target_extension : & str ) -> Self {
9798 let reader = BufReader :: new ( target) ;
98- // Assigns each supported file extension with the proper comment syntax
99+ // assigns each supported file extension with the proper comment syntax
99100 let meta_syntaxes: & [ MetaSyntax ] = match target_extension {
100101 "java" | "c" | "cpp" | "h" | "hpp" | "js" | "css" | "rs" | "qml" => & * META_SYNTAXES_C ,
101102 "xml" | "http" | "html" | "qrc" => & * META_SYNTAXES_HTML ,
102103 "properties" | "py" | "R" | "pro" => & * META_SYNTAXES_PY ,
103104 _ => & [ ] ,
104105 } ;
106+
105107 Self {
106108 meta_syntaxes,
107109 reader,
@@ -125,37 +127,39 @@ impl<B: BufRead> Iterator for MetaSyntaxParser<B> {
125127 for meta_syntax in self . meta_syntaxes {
126128 // check for stub
127129 if self . in_stub . is_none ( ) && meta_syntax. stub_begin . is_match ( & s) {
128- debug ! ( "stub start: '{}'" , s) ;
130+ log :: debug!( "stub start: '{}'" , s) ;
129131 // save the syntax that started the current stub
130132 self . in_stub = Some ( meta_syntax) ;
131133 // remove stub start
132134 s = meta_syntax
133135 . stub_begin
134136 . replace ( & s, |caps : & Captures | caps[ 1 ] . to_string ( ) )
135137 . to_string ( ) ;
136- debug ! ( "parsed: '{}'" , s) ;
138+ log :: debug!( "parsed: '{}'" , s) ;
137139 if s. trim ( ) . is_empty ( ) {
138140 // only metadata, skip
139141 return self . next ( ) ;
140142 }
141143 }
142144 // if the line matches stub_end and the saved syntax matches
143- // the start of the current meta syntax
145+ // the start of the current meta syntax, return stub contents if any
144146 if meta_syntax. stub_end . is_match ( & s)
145147 && self . in_stub . map ( |r| r. stub_begin . as_str ( ) )
146148 == Some ( meta_syntax. stub_begin . as_str ( ) )
147149 {
148- debug ! ( "stub end: '{}'" , s) ;
150+ log :: debug!( "stub end: '{}'" , s) ;
149151 self . in_stub = None ;
152+ // remove stub end
150153 s = meta_syntax
151154 . stub_end
152155 . replace ( & s, |caps : & Captures | caps[ 1 ] . to_string ( ) )
153156 . to_string ( ) ;
154- debug ! ( "parsed: '{}'" , s) ;
157+ log :: debug!( "parsed: '{}'" , s) ;
155158 if s. trim ( ) . is_empty ( ) {
156159 // only metadata, skip
157160 return self . next ( ) ;
158161 }
162+ // return the stub contents
159163 return Some ( Ok ( MetaString :: Stub ( s) ) ) ;
160164 }
161165
@@ -173,13 +177,13 @@ impl<B: BufRead> Iterator for MetaSyntaxParser<B> {
173177 // after processing the line with each meta syntax,
174178 // parse the current line accordingly
175179 if self . in_solution {
176- debug ! ( "solution: '{}'" , s) ;
180+ log :: debug!( "solution: '{}'" , s) ;
177181 Some ( Ok ( MetaString :: Solution ( s) ) )
178182 } else if self . in_stub . is_some ( ) {
179- debug ! ( "stub: '{}'" , s) ;
183+ log :: debug!( "stub: '{}'" , s) ;
180184 Some ( Ok ( MetaString :: Stub ( s) ) )
181185 } else {
182- debug ! ( "string: '{}'" , s) ;
186+ log :: debug!( "string: '{}'" , s) ;
183187 Some ( Ok ( MetaString :: String ( s) ) )
184188 }
185189 }
0 commit comments