Skip to content

Commit ece804d

Browse files
committed
use nom for parsing points
1 parent 980c42c commit ece804d

File tree

18 files changed

+344
-30
lines changed

18 files changed

+344
-30
lines changed

plugins/csharp/src/plugin.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use tmc_langs_framework::{
1717
},
1818
error::FileIo,
1919
io::file_util,
20+
nom::{self, IResult},
2021
plugin::Language,
2122
zip::ZipArchive,
2223
LanguagePlugin, TmcError,
@@ -115,6 +116,8 @@ impl CSharpPlugin {
115116

116117
impl LanguagePlugin for CSharpPlugin {
117118
const PLUGIN_NAME: &'static str = "csharp";
119+
const LINE_COMMENT: &'static str = "//";
120+
const BLOCK_COMMENT: Option<(&'static str, &'static str)> = Some(("/*", "*/"));
118121
type StudentFilePolicy = CSharpStudentFilePolicy;
119122

120123
/// Checks the directories in src for csproj files, up to 2 subdirectories deep.
@@ -267,6 +270,39 @@ impl LanguagePlugin for CSharpPlugin {
267270
}
268271
Ok(())
269272
}
273+
274+
fn get_default_student_file_paths(&self) -> Vec<PathBuf> {
275+
vec![PathBuf::from("src")]
276+
}
277+
278+
fn get_default_exercise_file_paths(&self) -> Vec<PathBuf> {
279+
vec![PathBuf::from("test")]
280+
}
281+
282+
fn points_parser<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
283+
nom::combinator::map(
284+
nom::sequence::delimited(
285+
nom::sequence::tuple((
286+
nom::bytes::complete::tag("@"),
287+
nom::character::complete::multispace0,
288+
nom::bytes::complete::tag_no_case("points"),
289+
nom::character::complete::multispace0,
290+
nom::character::complete::char('('),
291+
nom::character::complete::multispace0,
292+
)),
293+
nom::sequence::delimited(
294+
nom::character::complete::char('"'),
295+
nom::bytes::complete::is_not("\""),
296+
nom::character::complete::char('"'),
297+
),
298+
nom::sequence::tuple((
299+
nom::character::complete::multispace0,
300+
nom::character::complete::char(')'),
301+
)),
302+
),
303+
str::trim,
304+
)(i)
305+
}
270306
}
271307

272308
#[cfg(test)]
@@ -416,4 +452,16 @@ mod test {
416452
assert!(!bin_path.exists());
417453
assert!(!obj_path_test.exists());
418454
}
455+
456+
#[test]
457+
fn parses_points() {
458+
let res = CSharpPlugin::points_parser("asd");
459+
assert!(res.is_err());
460+
461+
let res = CSharpPlugin::points_parser("@Points(\"1\")").unwrap();
462+
assert_eq!(res.1, "1");
463+
464+
let res = CSharpPlugin::points_parser("@ pOiNtS ( \" 1 \" ) ").unwrap();
465+
assert_eq!(res.1, "1");
466+
}
419467
}

plugins/java/src/ant.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ use j4rs::Jvm;
77
use policy::AntStudentFilePolicy;
88
use std::env;
99
use std::ffi::OsStr;
10-
use std::path::Path;
10+
use std::path::{Path, PathBuf};
1111
use std::process::Stdio;
1212
use std::time::Duration;
1313
use tmc_langs_framework::{
1414
command::TmcCommand,
1515
domain::{ExerciseDesc, RunResult, ValidationResult},
1616
io::file_util,
17+
nom::{self, IResult},
1718
plugin::{Language, LanguagePlugin},
1819
TmcError,
1920
};
@@ -69,6 +70,8 @@ impl AntPlugin {
6970

7071
impl LanguagePlugin for AntPlugin {
7172
const PLUGIN_NAME: &'static str = "apache-ant";
73+
const LINE_COMMENT: &'static str = "//";
74+
const BLOCK_COMMENT: Option<(&'static str, &'static str)> = Some(("/*", "*/"));
7275
type StudentFilePolicy = AntStudentFilePolicy;
7376

7477
fn check_code_style(
@@ -129,6 +132,18 @@ impl LanguagePlugin for AntPlugin {
129132
file_util::remove_file(&stderr_path)?;
130133
Ok(())
131134
}
135+
136+
fn points_parser<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
137+
Self::java_points_parser(i)
138+
}
139+
140+
fn get_default_student_file_paths(&self) -> Vec<PathBuf> {
141+
vec![PathBuf::from("src")]
142+
}
143+
144+
fn get_default_exercise_file_paths(&self) -> Vec<PathBuf> {
145+
vec![PathBuf::from("test")]
146+
}
132147
}
133148

134149
impl JavaPlugin for AntPlugin {

plugins/java/src/maven.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use tmc_langs_framework::{
1616
command::TmcCommand,
1717
domain::{ExerciseDesc, RunResult, ValidationResult},
1818
io::file_util,
19+
nom::{self, IResult},
1920
plugin::{Language, LanguagePlugin},
2021
TmcError,
2122
};
@@ -73,6 +74,8 @@ impl MavenPlugin {
7374

7475
impl LanguagePlugin for MavenPlugin {
7576
const PLUGIN_NAME: &'static str = "apache-maven";
77+
const LINE_COMMENT: &'static str = "//";
78+
const BLOCK_COMMENT: Option<(&'static str, &'static str)> = Some(("/*", "*/"));
7679
type StudentFilePolicy = MavenStudentFilePolicy;
7780

7881
fn check_code_style(
@@ -127,6 +130,10 @@ impl LanguagePlugin for MavenPlugin {
127130
fn get_default_exercise_file_paths(&self) -> Vec<PathBuf> {
128131
vec![PathBuf::from("src/test")]
129132
}
133+
134+
fn points_parser<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
135+
Self::java_points_parser(i)
136+
}
130137
}
131138

132139
impl JavaPlugin for MavenPlugin {

plugins/java/src/plugin.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use tmc_langs_framework::{
1010
command::TmcCommand,
1111
domain::{ExerciseDesc, RunResult, RunStatus, TestDesc, TestResult, ValidationResult},
1212
io::file_util,
13+
nom::{self, IResult},
1314
plugin::{Language, LanguagePlugin},
1415
};
1516
use walkdir::WalkDir;
@@ -244,6 +245,31 @@ pub(crate) trait JavaPlugin: LanguagePlugin {
244245
log::debug!("Validation result: {:?}", result);
245246
Ok(result)
246247
}
248+
249+
fn java_points_parser<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
250+
nom::combinator::map(
251+
nom::sequence::delimited(
252+
nom::sequence::tuple((
253+
nom::bytes::complete::tag("@"),
254+
nom::character::complete::multispace0,
255+
nom::bytes::complete::tag_no_case("points"),
256+
nom::character::complete::multispace0,
257+
nom::character::complete::char('('),
258+
nom::character::complete::multispace0,
259+
)),
260+
nom::sequence::delimited(
261+
nom::character::complete::char('"'),
262+
nom::bytes::complete::is_not("\""),
263+
nom::character::complete::char('"'),
264+
),
265+
nom::sequence::tuple((
266+
nom::character::complete::multispace0,
267+
nom::character::complete::char(')'),
268+
)),
269+
),
270+
str::trim,
271+
)(i)
272+
}
247273
}
248274

249275
#[cfg(test)]

plugins/make/src/plugin.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ use lazy_static::lazy_static;
88
use regex::Regex;
99
use std::collections::HashMap;
1010
use std::io::{self, BufRead, BufReader};
11-
use std::path::Path;
11+
use std::path::{Path, PathBuf};
1212
use std::process::Output;
1313
use std::time::Duration;
1414
use tmc_langs_framework::{
1515
command::TmcCommand,
1616
domain::{ExerciseDesc, RunResult, RunStatus, TestDesc, TmcProjectYml},
1717
error::{CommandError, FileIo},
1818
io::file_util,
19+
nom::{self, IResult},
1920
plugin::LanguagePlugin,
2021
TmcError,
2122
};
@@ -120,6 +121,8 @@ impl MakePlugin {
120121

121122
impl LanguagePlugin for MakePlugin {
122123
const PLUGIN_NAME: &'static str = "make";
124+
const LINE_COMMENT: &'static str = "//";
125+
const BLOCK_COMMENT: Option<(&'static str, &'static str)> = Some(("/*", "*/"));
123126
type StudentFilePolicy = MakeStudentFilePolicy;
124127

125128
fn scan_exercise(&self, path: &Path, exercise_name: String) -> Result<ExerciseDesc, TmcError> {
@@ -299,6 +302,37 @@ impl LanguagePlugin for MakePlugin {
299302

300303
Ok(())
301304
}
305+
306+
fn get_default_student_file_paths(&self) -> Vec<PathBuf> {
307+
vec![PathBuf::from("src")]
308+
}
309+
310+
fn get_default_exercise_file_paths(&self) -> Vec<PathBuf> {
311+
vec![PathBuf::from("test")]
312+
}
313+
314+
fn points_parser<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
315+
nom::combinator::map(
316+
nom::sequence::delimited(
317+
nom::sequence::tuple((
318+
nom::bytes::complete::tag("tmc_register_test"),
319+
nom::character::complete::multispace0,
320+
nom::character::complete::char('('),
321+
nom::bytes::complete::is_not("\""),
322+
)),
323+
nom::sequence::delimited(
324+
nom::character::complete::char('"'),
325+
nom::bytes::complete::is_not("\""),
326+
nom::character::complete::char('"'),
327+
),
328+
nom::sequence::tuple((
329+
nom::character::complete::multispace0,
330+
nom::character::complete::char(')'),
331+
)),
332+
),
333+
str::trim,
334+
)(i)
335+
}
302336
}
303337

304338
#[cfg(test)]
@@ -439,4 +473,21 @@ mod test {
439473
let dir = MakePlugin::find_project_dir_in_zip(&mut zip);
440474
assert!(dir.is_err());
441475
}
476+
477+
#[test]
478+
fn parses_points() {
479+
assert!(MakePlugin::points_parser(
480+
"tmc_register_test(s, test_insertion_empty_list, \"dlink_insert);",
481+
)
482+
.is_err());
483+
484+
assert_eq!(
485+
MakePlugin::points_parser(
486+
"tmc_register_test(s, test_insertion_empty_list, \"dlink_insert\");",
487+
)
488+
.unwrap()
489+
.1,
490+
"dlink_insert"
491+
);
492+
}
442493
}

plugins/notests/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::time::Duration;
77
pub use tmc_langs_framework::policy::EverythingIsStudentFilePolicy as NoTestsStudentFilePolicy;
88
use tmc_langs_framework::{
99
domain::{ExerciseDesc, RunResult, RunStatus, TestDesc, TestResult},
10+
nom::{self, IResult},
1011
zip::ZipArchive,
1112
LanguagePlugin, StudentFilePolicy, TmcError,
1213
};
@@ -30,6 +31,8 @@ impl NoTestsPlugin {
3031

3132
impl LanguagePlugin for NoTestsPlugin {
3233
const PLUGIN_NAME: &'static str = "No-Tests";
34+
const LINE_COMMENT: &'static str = "//";
35+
const BLOCK_COMMENT: Option<(&'static str, &'static str)> = None;
3336
type StudentFilePolicy = NoTestsStudentFilePolicy;
3437

3538
fn scan_exercise(&self, path: &Path, exercise_name: String) -> Result<ExerciseDesc, TmcError> {
@@ -81,6 +84,18 @@ impl LanguagePlugin for NoTestsPlugin {
8184
fn clean(&self, _path: &Path) -> Result<(), TmcError> {
8285
Ok(())
8386
}
87+
88+
fn get_default_student_file_paths(&self) -> Vec<PathBuf> {
89+
vec![PathBuf::from("src")]
90+
}
91+
92+
fn get_default_exercise_file_paths(&self) -> Vec<PathBuf> {
93+
vec![PathBuf::from("test")]
94+
}
95+
96+
fn points_parser<'a>(_: &'a str) -> IResult<&'a str, &'a str> {
97+
Ok(("", ""))
98+
}
8499
}
85100

86101
#[cfg(test)]

plugins/python3/src/plugin.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use tmc_langs_framework::{
1111
command::{OutputWithTimeout, TmcCommand},
1212
domain::{ExerciseDesc, RunResult, RunStatus, TestDesc, TestResult},
1313
io::file_util,
14+
nom::{self, IResult},
1415
plugin::LanguagePlugin,
1516
TmcError,
1617
};
@@ -26,6 +27,8 @@ impl Python3Plugin {
2627

2728
impl LanguagePlugin for Python3Plugin {
2829
const PLUGIN_NAME: &'static str = "python3";
30+
const LINE_COMMENT: &'static str = "#";
31+
const BLOCK_COMMENT: Option<(&'static str, &'static str)> = Some(("\"\"\"", "\"\"\""));
2932
type StudentFilePolicy = Python3StudentFilePolicy;
3033

3134
fn get_student_file_policy(project_path: &Path) -> Self::StudentFilePolicy {
@@ -131,9 +134,45 @@ impl LanguagePlugin for Python3Plugin {
131134
Ok(())
132135
}
133136

137+
fn get_default_student_file_paths(&self) -> Vec<PathBuf> {
138+
vec![PathBuf::from("src")]
139+
}
140+
134141
fn get_default_exercise_file_paths(&self) -> Vec<PathBuf> {
135142
vec![PathBuf::from("test"), PathBuf::from("tmc")]
136143
}
144+
145+
fn points_parser<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
146+
nom::combinator::map(
147+
nom::sequence::delimited(
148+
nom::sequence::tuple((
149+
nom::bytes::complete::tag("@"),
150+
nom::character::complete::multispace0,
151+
nom::bytes::complete::tag_no_case("points"),
152+
nom::character::complete::multispace0,
153+
nom::character::complete::char('('),
154+
nom::character::complete::multispace0,
155+
)),
156+
nom::branch::alt((
157+
nom::sequence::delimited(
158+
nom::character::complete::char('"'),
159+
nom::bytes::complete::is_not("\""),
160+
nom::character::complete::char('"'),
161+
),
162+
nom::sequence::delimited(
163+
nom::character::complete::char('\''),
164+
nom::bytes::complete::is_not("'"),
165+
nom::character::complete::char('\''),
166+
),
167+
)),
168+
nom::sequence::tuple((
169+
nom::character::complete::multispace0,
170+
nom::character::complete::char(')'),
171+
)),
172+
),
173+
str::trim,
174+
)(i)
175+
}
137176
}
138177

139178
fn run_tmc_command(

plugins/r/src/plugin.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use tmc_langs_framework::{
1212
command::TmcCommand,
1313
domain::{ExerciseDesc, RunResult, TestDesc},
1414
io::file_util,
15+
nom::{self, IResult},
1516
zip::ZipArchive,
1617
LanguagePlugin, TmcError,
1718
};
@@ -27,6 +28,8 @@ impl RPlugin {
2728

2829
impl LanguagePlugin for RPlugin {
2930
const PLUGIN_NAME: &'static str = "r";
31+
const LINE_COMMENT: &'static str = "#";
32+
const BLOCK_COMMENT: Option<(&'static str, &'static str)> = None;
3033
type StudentFilePolicy = RStudentFilePolicy;
3134

3235
fn scan_exercise(&self, path: &Path, exercise_name: String) -> Result<ExerciseDesc, TmcError> {
@@ -130,6 +133,11 @@ impl LanguagePlugin for RPlugin {
130133
fn get_default_exercise_file_paths(&self) -> Vec<PathBuf> {
131134
vec![PathBuf::from("tests")]
132135
}
136+
137+
fn points_parser<'a>(_i: &'a str) -> IResult<&'a str, &'a str> {
138+
// no points annotations
139+
Ok(("", ""))
140+
}
133141
}
134142

135143
#[cfg(test)]

0 commit comments

Comments
 (0)