summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml10
-rw-r--r--build.rs34
-rw-r--r--src/syntax/tokens.rs2
-rw-r--r--tests/layout.rs (renamed from tests/layouting.rs)5
-rw-r--r--tests/layouting/align.typ (renamed from tests/layouts/align.typ)0
-rw-r--r--tests/layouting/coma.typ (renamed from tests/layouts/coma.typ)0
-rw-r--r--tests/layouting/lines.typ (renamed from tests/layouts/lines.typ)0
-rw-r--r--tests/parse.rs59
-rw-r--r--tests/parsing/base.rs78
9 files changed, 184 insertions, 4 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0ce0d396..76db3d18 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,7 @@ name = "typstc"
version = "0.1.0"
authors = ["Laurenz Mรคdje <laurmaedje@gmail.com>"]
edition = "2018"
+build = "build.rs"
[dependencies]
tide = { path = "../tide" }
@@ -16,6 +17,11 @@ name = "typst-bin"
path = "src/bin/main.rs"
[[test]]
-name = "layouting"
-path = "tests/layouting.rs"
+name = "layout"
+path = "tests/layout.rs"
+harness = false
+
+[[test]]
+name = "parse"
+path = "tests/parse.rs"
harness = false
diff --git a/build.rs b/build.rs
new file mode 100644
index 00000000..c91db8e0
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,34 @@
+use std::fs;
+use std::ffi::OsStr;
+
+fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+ println!("cargo:rerun-if-changed=tests/parsing");
+
+ fs::create_dir_all("tests/cache").unwrap();
+
+ let paths = fs::read_dir("tests/parsing").unwrap()
+ .map(|entry| entry.unwrap().path())
+ .filter(|path| path.extension() == Some(OsStr::new("rs")));
+
+ let mut code = "vec![".to_string();
+ for path in paths {
+ let name = path.file_stem().unwrap().to_str().unwrap();
+ let file = fs::read_to_string(&path).unwrap();
+
+ println!("cargo:rerun-if-changed=tests/parsing/{}.rs", name);
+
+ code.push_str(&format!("(\"{}\", tokens!{{", name));
+
+ for (index, line) in file.lines().enumerate() {
+ let mut line = line.replace("=>", &format!("=>({})=>", index + 1));
+ line.push('\n');
+ code.push_str(&line);
+ }
+
+ code.push_str("}),");
+ }
+ code.push(']');
+
+ fs::write("tests/cache/parsing.rs", code).unwrap();
+}
diff --git a/src/syntax/tokens.rs b/src/syntax/tokens.rs
index 4fdee371..95b2ea3e 100644
--- a/src/syntax/tokens.rs
+++ b/src/syntax/tokens.rs
@@ -204,7 +204,7 @@ impl<'s> Iterator for Tokens<'s> {
'\\' => {
if let Some((index, c)) = self.chars.peek() {
let escapable = match c {
- '[' | ']' | '\\' | '*' | '_' | '`' | ':' | '=' | '/' => true,
+ '[' | ']' | '\\' | '*' | '_' | '`' | ':' | '=' | ',' | '/' => true,
_ => false,
};
diff --git a/tests/layouting.rs b/tests/layout.rs
index 001ff45a..46835a2a 100644
--- a/tests/layouting.rs
+++ b/tests/layout.rs
@@ -31,7 +31,7 @@ fn main() {
let mut failed = 0;
- for entry in fs::read_dir("tests/layouts/").unwrap() {
+ for entry in fs::read_dir("tests/layouting/").unwrap() {
let path = entry.unwrap().path();
if path.extension() != Some(std::ffi::OsStr::new("typ")) {
@@ -60,8 +60,11 @@ fn main() {
if failed > 0 {
println!("{} tests failed.", failed);
+ println!();
std::process::exit(-1);
}
+
+ println!();
}
/// Create a _PDF_ with a name from the source code.
diff --git a/tests/layouts/align.typ b/tests/layouting/align.typ
index a7101932..a7101932 100644
--- a/tests/layouts/align.typ
+++ b/tests/layouting/align.typ
diff --git a/tests/layouts/coma.typ b/tests/layouting/coma.typ
index d0a02b74..d0a02b74 100644
--- a/tests/layouts/coma.typ
+++ b/tests/layouting/coma.typ
diff --git a/tests/layouts/lines.typ b/tests/layouting/lines.typ
index 705de638..705de638 100644
--- a/tests/layouts/lines.typ
+++ b/tests/layouting/lines.typ
diff --git a/tests/parse.rs b/tests/parse.rs
new file mode 100644
index 00000000..a56059d7
--- /dev/null
+++ b/tests/parse.rs
@@ -0,0 +1,59 @@
+use typstc::syntax::*;
+
+use Token::{
+ Space as S, Newline as N, LeftBracket as LB,
+ RightBracket as RB, Text as T, *
+};
+
+macro_rules! tokens {
+ ($($src:expr =>($line:expr)=> $tokens:expr)*) => ({
+ #[allow(unused_mut)]
+ let mut cases = Vec::new();
+ $(cases.push(($line, $src, $tokens.to_vec()));)*
+ cases
+ });
+}
+
+fn main() {
+ let tests = include!("cache/parsing.rs");
+
+ let mut errors = false;
+ for (file, cases) in tests.into_iter() {
+ print!("Testing: {}. ", file);
+
+ let mut okay = 0;
+ let mut failed = 0;
+
+ for (line, src, expected) in cases.into_iter() {
+ let found: Vec<_> = tokenize(src).map(Spanned::value).collect();
+
+ if found == expected {
+ okay += 1;
+ } else {
+ if failed == 0 {
+ println!();
+ }
+
+ println!(" - Case failed in file {}.rs in line {}.", file, line);
+ println!(" - Source: {:?}", src);
+ println!(" - Expected: {:?}", expected);
+ println!(" - Found: {:?}", found);
+
+ failed += 1;
+ errors = true;
+ }
+ }
+
+ print!("{} okay, {} failed.", okay, failed);
+ if failed == 0 {
+ print!(" โœ”")
+ }
+ println!();
+ }
+
+ println!();
+
+ if errors {
+ std::process::exit(-1);
+ }
+}
diff --git a/tests/parsing/base.rs b/tests/parsing/base.rs
new file mode 100644
index 00000000..ad7d87c0
--- /dev/null
+++ b/tests/parsing/base.rs
@@ -0,0 +1,78 @@
+// Spaces, Newlines, Brackets.
+"" => []
+" " => [S]
+" " => [S]
+"\t" => [S]
+" \t" => [S]
+"\n" => [N]
+"\n " => [N, S]
+" \n" => [S, N]
+" \n " => [S, N, S]
+"[" => [LB]
+"]" => [RB]
+
+// Header only tokens.
+"[:]" => [LB, Colon, RB]
+"[=]" => [LB, Equals, RB]
+"[,]" => [LB, Comma, RB]
+":" => [T(":")]
+"=" => [T("=")]
+"," => [T(",")]
+r#"["hi"]"# => [LB, Quoted("hi"), RB]
+r#""hi""# => [T(r#""hi""#)]
+
+// Body only tokens.
+"_" => [Underscore]
+"*" => [Star]
+"`" => [Backtick]
+"[_]" => [LB, T("_"), RB]
+"[*]" => [LB, T("*"), RB]
+"[`]" => [LB, T("`"), RB]
+
+// Comments.
+"//line" => [LineComment("line")]
+"/*block*/" => [BlockComment("block")]
+"*/" => [StarSlash]
+
+// Plain text.
+"A" => [T("A")]
+"Hello" => [T("Hello")]
+"Hello-World" => [T("Hello-World")]
+r#"A"B"# => [T(r#"A"B"#)]
+"๐ŸŒ" => [T("๐ŸŒ")]
+
+// Escapes.
+r"\[" => [T("[")]
+r"\]" => [T("]")]
+r"\\" => [T(r"\")]
+r"[\[]" => [LB, T("["), RB]
+r"[\]]" => [LB, T("]"), RB]
+r"[\\]" => [LB, T(r"\"), RB]
+r"\:" => [T(":")]
+r"\=" => [T("=")]
+r"\/" => [T("/")]
+r"[\:]" => [LB, T(":"), RB]
+r"[\=]" => [LB, T("="), RB]
+r"[\,]" => [LB, T(","), RB]
+r"\*" => [T("*")]
+r"\_" => [T("_")]
+r"\`" => [T("`")]
+r"[\*]" => [LB, T("*"), RB]
+r"[\_]" => [LB, T("_"), RB]
+r"[\`]" => [LB, T("`"), RB]
+
+// Whitespace.
+"Hello World" => [T("Hello"), S, T("World")]
+"Hello World" => [T("Hello"), S, T("World")]
+"Hello \t World" => [T("Hello"), S, T("World")]
+
+// Newline.
+"First\n" => [T("First"), N]
+"First \n" => [T("First"), S, N]
+"First\n " => [T("First"), N, S]
+"First \n " => [T("First"), S, N, S]
+"First\nSecond" => [T("First"), N, T("Second")]
+"First\r\nSecond" => [T("First"), N, T("Second")]
+"First \nSecond" => [T("First"), S, N, T("Second")]
+"First\n Second" => [T("First"), N, S, T("Second")]
+"First \n Second" => [T("First"), S, N, S, T("Second")]