From 7b31c3eed6c7c979af6e8f6e9d3e346c6b434061 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 16 Jul 2015 06:09:31 -0400 Subject: [PATCH] fix unit tests --- lalrpop/src/grammar/parse_tree.rs | 2 +- lalrpop/src/grammar/repr.rs | 9 ++++-- lalrpop/src/lr1/ascent.rs | 19 ++++++----- lalrpop/src/lr1/first/test.rs | 3 +- lalrpop/src/lr1/test.rs | 35 ++++++++++---------- lalrpop/src/normalize/lower/mod.rs | 4 +-- lalrpop/src/normalize/lower/test.rs | 29 ++++++++--------- lalrpop/src/normalize/macro_expand/test.rs | 16 ++++------ lalrpop/src/normalize/tyinfer/test.rs | 37 ++++++++-------------- lalrpop/src/normalize/validate/mod.rs | 4 +-- lalrpop/src/normalize/validate/test.rs | 29 ++++++++++------- lalrpop/src/parser/mod.rs | 6 ++-- lalrpop/src/parser/test.rs | 2 +- 13 files changed, 96 insertions(+), 99 deletions(-) diff --git a/lalrpop/src/grammar/parse_tree.rs b/lalrpop/src/grammar/parse_tree.rs index e92edc5..db4cd08 100644 --- a/lalrpop/src/grammar/parse_tree.rs +++ b/lalrpop/src/grammar/parse_tree.rs @@ -39,7 +39,7 @@ pub struct ExternToken { #[derive(Clone, Debug, PartialEq, Eq)] pub struct AssociatedType { - pub span: Span, + pub type_span: Span, pub type_name: InternedString, pub type_ref: TypeRef, } diff --git a/lalrpop/src/grammar/repr.rs b/lalrpop/src/grammar/repr.rs index 6985682..fd4e6ec 100644 --- a/lalrpop/src/grammar/repr.rs +++ b/lalrpop/src/grammar/repr.rs @@ -60,7 +60,7 @@ pub struct Production { // handy to have it pub nonterminal: NonterminalString, pub symbols: Vec, - pub action_fn: ActionFn, + pub action: ProductionAction, pub span: Span, } @@ -70,6 +70,11 @@ pub enum Symbol { Terminal(TerminalString), } +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub enum ProductionAction { + Call(ActionFn) +} + #[derive(Clone, PartialEq, Eq)] pub struct ActionFnDefn { pub arg_patterns: Vec, @@ -231,7 +236,7 @@ impl Debug for Production { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { write!(fmt, "{} = {} => {:?};", - self.nonterminal, Sep(", ", &self.symbols), self.action_fn) + self.nonterminal, Sep(", ", &self.symbols), self.action) } } diff --git a/lalrpop/src/lr1/ascent.rs b/lalrpop/src/lr1/ascent.rs index 5006143..a179db9 100644 --- a/lalrpop/src/lr1/ascent.rs +++ b/lalrpop/src/lr1/ascent.rs @@ -2,7 +2,7 @@ //! //! [recursive ascent]: https://en.wikipedia.org/wiki/Recursive_ascent_parser -use grammar::repr::{Grammar, NonterminalString, Symbol, TerminalString, Types}; +use grammar::repr::{Grammar, NonterminalString, ProductionAction, Symbol, TerminalString, Types}; use lr1::{Lookahead, State, StateIndex}; use rust::RustWrite; use std::io::{self, Write}; @@ -229,13 +229,16 @@ impl<'ascent,'grammar,W:Write> RecursiveAscent<'ascent,'grammar,W> { } // invoke the action code - rust!(self.out, "let {}nt = super::{}actions::{}action{}({}{});", - self.prefix, - self.prefix, - self.prefix, - production.action_fn.index(), - self.grammar.user_parameter_refs(), - Sep(", ", &transfer_syms)); + match production.action { + ProductionAction::Call(action_fn) => + rust!(self.out, "let {}nt = super::{}actions::{}action{}({}{});", + self.prefix, + self.prefix, + self.prefix, + action_fn.index(), + self.grammar.user_parameter_refs(), + Sep(", ", &transfer_syms)), + } // wrap up the result along with the (unused) lookahead if !transfer_syms.is_empty() { diff --git a/lalrpop/src/lr1/first/test.rs b/lalrpop/src/lr1/first/test.rs index 8d8dc3b..b3d5fc2 100644 --- a/lalrpop/src/lr1/first/test.rs +++ b/lalrpop/src/lr1/first/test.rs @@ -26,14 +26,13 @@ fn first(first: &FirstSets, symbols: &[Symbol], lookahead: Lookahead) -> Vec = { "D" => Some(1); => None; }; -} "#); let first_sets = FirstSets::new(&grammar); diff --git a/lalrpop/src/lr1/test.rs b/lalrpop/src/lr1/test.rs index e243969..28799b9 100644 --- a/lalrpop/src/lr1/test.rs +++ b/lalrpop/src/lr1/test.rs @@ -44,17 +44,16 @@ fn items<'g>(grammar: &'g Grammar, nonterminal: &str, index: usize, la: Lookahea #[test] fn start_state() { let grammar = normalized_grammar(r#" -grammar { +grammar; extern token { enum Tok { } } A = B "C"; B: Option = { "D" => Some(1); => None; }; -} "#); let items = items(&grammar, "A", 0, EOF); - expect_debug(items, r#"[ + expect_debug(items.vec, r#"[ A = (*) B "C" [EOF], B = (*) ["C"], B = (*) "D" ["C"] @@ -64,21 +63,20 @@ grammar { #[test] fn start_state_1() { let grammar = normalized_grammar(r#" -grammar { - extern token { enum Tok { } } - A = B C; - B: Option = { - "B1" => Some(1); - => None; - }; - C: Option = { - "C1" => Some(1); - => None; - }; -} +grammar; +extern token { enum Tok { } } +A = B C; +B: Option = { + "B1" => Some(1); + => None; +}; +C: Option = { + "C1" => Some(1); + => None; +}; "#); - expect_debug(items(&grammar, "A", 0, EOF), r#"[ + expect_debug(items(&grammar, "A", 0, EOF).vec, r#"[ A = (*) B C [EOF], B = (*) [EOF], B = (*) ["C1"], @@ -86,7 +84,7 @@ grammar { B = (*) "B1" ["C1"] ]"#); - expect_debug(items(&grammar, "A", 1, EOF), r#"[ + expect_debug(items(&grammar, "A", 1, EOF).vec, r#"[ A = B (*) C [EOF], C = (*) [EOF], C = (*) "C1" [EOF] @@ -96,7 +94,7 @@ grammar { #[test] fn expr_grammar1() { let grammar = normalized_grammar(r#" -grammar { +grammar; extern token { enum Tok { } } S: () = @@ -111,7 +109,6 @@ grammar { "N" => (); "(" E ")" => (); }; -} "#); // for now, just test that process does not result in an error diff --git a/lalrpop/src/normalize/lower/mod.rs b/lalrpop/src/normalize/lower/mod.rs index 5dfad5b..c16638b 100644 --- a/lalrpop/src/normalize/lower/mod.rs +++ b/lalrpop/src/normalize/lower/mod.rs @@ -69,7 +69,7 @@ impl LowerState { nonterminal: nt.name, span: alt.span, symbols: symbols, - action_fn: action_fn, + action: r::ProductionAction::Call(action_fn), }; self.productions.push(production); } @@ -129,7 +129,7 @@ impl LowerState { self.productions.push(r::Production { nonterminal: fake_name, symbols: symbols, - action_fn: action_fn, + action: r::ProductionAction::Call(action_fn), span: nt.span }); (nt.name, fake_name) diff --git a/lalrpop/src/normalize/lower/test.rs b/lalrpop/src/normalize/lower/test.rs index ece0d25..df73b13 100644 --- a/lalrpop/src/normalize/lower/test.rs +++ b/lalrpop/src/normalize/lower/test.rs @@ -11,7 +11,7 @@ fn flat_productions(grammar: &Grammar) -> Vec { // sort by the action fn index just to get a consistent ordering productions.sort_by(|k1, k2| { - Ord::cmp(&k1.action_fn.index(), &k2.action_fn.index()) + Ord::cmp(&k1.action, &k2.action) }); productions @@ -20,7 +20,7 @@ fn flat_productions(grammar: &Grammar) -> Vec { #[test] fn test_comma() { let grammar = parser::parse_grammar(" -grammar { +grammar; extern token { enum Tok { } } Comma: Vec = @@ -28,29 +28,28 @@ grammar { v.into_iter().chain(e.into_iter()).collect(); Ids = Comma<\"Id\">; -} ").unwrap(); let actual = normalize_without_validating(grammar).unwrap(); expect_debug(flat_productions(&actual), r#"[ - Ids = Comma<"Id"> => ActionFn(0);, - Comma<"Id"> = (<"Id"> ",")*, "Id"? => ActionFn(1);, - "Id"? = "Id" => ActionFn(2);, - "Id"? = => ActionFn(3);, - (<"Id"> ",")* = => ActionFn(4);, - (<"Id"> ",")* = (<"Id"> ",")*, (<"Id"> ",") => ActionFn(5);, - (<"Id"> ",") = "Id", "," => ActionFn(6); + Ids = Comma<"Id"> => Call(ActionFn(0));, + Comma<"Id"> = (<"Id"> ",")*, "Id"? => Call(ActionFn(1));, + "Id"? = "Id" => Call(ActionFn(2));, + "Id"? = => Call(ActionFn(3));, + (<"Id"> ",")* = => Call(ActionFn(4));, + (<"Id"> ",")* = (<"Id"> ",")*, (<"Id"> ",") => Call(ActionFn(5));, + (<"Id"> ",") = "Id", "," => Call(ActionFn(6)); ]"#); expect_debug(&actual.action_fn_defns, r#"[ fn _(__0: Vec) -> Vec { (__0) }, - fn _(v: std::vec::Vec, e: std::option::Option) -> Vec { v.into_iter().chain(e.into_iter()).collect() }, - fn _(__0: Tok) -> std::option::Option { Some(__0) }, - fn _() -> std::option::Option { None }, - fn _() -> std::vec::Vec { vec![] }, - fn _(v: std::vec::Vec, e: Tok) -> std::vec::Vec { { let mut v = v; v.push(e); v } }, + fn _(v: ::std::vec::Vec, e: ::std::option::Option) -> Vec { v.into_iter().chain(e.into_iter()).collect() }, + fn _(__0: Tok) -> ::std::option::Option { Some(__0) }, + fn _() -> ::std::option::Option { None }, + fn _() -> ::std::vec::Vec { vec![] }, + fn _(v: ::std::vec::Vec, e: Tok) -> ::std::vec::Vec { { let mut v = v; v.push(e); v } }, fn _(__0: Tok, _: Tok) -> Tok { (__0) } ]"#); } diff --git a/lalrpop/src/normalize/macro_expand/test.rs b/lalrpop/src/normalize/macro_expand/test.rs index fa4956f..547c7c4 100644 --- a/lalrpop/src/normalize/macro_expand/test.rs +++ b/lalrpop/src/normalize/macro_expand/test.rs @@ -6,37 +6,35 @@ use super::expand_macros; #[test] fn test_comma() { let grammar = parser::parse_grammar(r#" -grammar { +grammar; Comma: Vec = ",")*> => v.into_iter().chain(e.into_iter()).collect(); Ids = Comma<"Id">; -} "#).unwrap(); let actual = expand_macros(grammar).unwrap(); let expected = parser::parse_grammar(r#" -grammar { +grammar; Ids = `Comma<"Id">`; `Comma<"Id">`: Vec<`"Id"`> = ",")*`> => v.into_iter().chain(e.into_iter()).collect(); - `"Id"?`: std::option::Option<`"Id"`> = { + `"Id"?`: ::std::option::Option<`"Id"`> = { "Id" => Some(<>); => None; }; - `(<"Id"> ",")*`: std::vec::Vec<``(<"Id"> ",")``> = { + `(<"Id"> ",")*`: ::std::vec::Vec<``(<"Id"> ",")``> = { => vec![]; ",")*`> ",")`> => { let mut v = v; v.push(e); v }; }; `(<"Id"> ",")`: `"Id"` = <"Id"> "," => (<>); -} "#).unwrap(); compare(actual, expected); @@ -45,7 +43,7 @@ grammar { #[test] fn test_if_match() { let grammar = parser::parse_grammar(r#" -grammar { +grammar; Expr = { A if E == "A*C"; B if E ~~ "^A*C$"; @@ -56,13 +54,12 @@ grammar { Expr1 = Expr<"A*C">; Expr2 = Expr<"AAC">; Expr3 = Expr<"ABC">; -} "#).unwrap(); let actual = expand_macros(grammar).unwrap(); let expected = parser::parse_grammar(r#" -grammar { +grammar; Expr1 = `Expr<"A*C">`; Expr2 = `Expr<"AAC">`; Expr3 = `Expr<"ABC">`; @@ -70,7 +67,6 @@ grammar { `Expr<"ABC">` = { C; D; }; `Expr<"AAC">` = { B; C; }; `Expr<"A*C">` = { A; D; }; -} "#).unwrap(); compare(actual, expected); diff --git a/lalrpop/src/normalize/tyinfer/test.rs b/lalrpop/src/normalize/tyinfer/test.rs index 23f37d5..249d698 100644 --- a/lalrpop/src/normalize/tyinfer/test.rs +++ b/lalrpop/src/normalize/tyinfer/test.rs @@ -28,12 +28,11 @@ fn compare(g1: &str, expected: Vec<(&'static str, &'static str)>) { #[test] fn test_pairs_and_tokens() { compare(" -grammar { +grammar; extern token { enum Tok { } } X = Y Z; Y: Foo = \"Hi\"; Z = \"Ho\"; -} ", vec![ ("X", "(Foo, Tok)"), ("Y", "Foo"), @@ -44,14 +43,13 @@ grammar { #[test] fn test_cycle_direct() { let grammar = parser::parse_grammar(" -grammar { +grammar; extern token { enum Tok { } } X = { X Y; => vec![<>]; }; Y = \"Hi\"; -} ").unwrap(); let actual = expand_macros(grammar).unwrap(); @@ -61,13 +59,12 @@ grammar { #[test] fn test_cycle_indirect() { let grammar = parser::parse_grammar(" -grammar { +grammar; extern token { enum Tok { } } A = B; B = C; C = D; D = A; -} ").unwrap(); let actual = expand_macros(grammar).unwrap(); @@ -77,11 +74,10 @@ grammar { #[test] fn test_macro_expansion() { compare(" -grammar { +grammar; extern token { enum Tok { } } Two: (X, X) = X X; Ids = Two<\"Id\">; -} ", vec![ ("Ids", "(Tok, Tok)"), (r#"Two<"Id">"#, "(Tok, Tok)"), @@ -91,11 +87,10 @@ grammar { #[test] fn test_macro_expansion_infer() { compare(" -grammar { +grammar; extern token { enum Tok { } } Two = X X; Ids = Two<\"Id\">; -} ", vec![ ("Ids", "(Tok, Tok)"), (r#"Two<"Id">"#, "(Tok, Tok)"), @@ -105,13 +100,12 @@ grammar { #[test] fn test_type_question() { compare(" -grammar { +grammar; extern token { enum Tok { } } X = Y?; Y = \"Hi\"; -} ",vec![ - ("X", "std::option::Option"), + ("X", "::std::option::Option"), ("Y", "Tok") ]) } @@ -119,25 +113,24 @@ grammar { #[test] fn test_star_plus_question() { compare(" -grammar { +grammar; extern token { enum Tok { } } A = Z*; X = \"Hi\"*; Y = \"Hi\"+; Z = \"Hi\"?; -} ", vec![ - ("A", "std::vec::Vec>"), - ("X", "std::vec::Vec"), - ("Y", "std::vec::Vec"), - ("Z", "std::option::Option") + ("A", "::std::vec::Vec<::std::option::Option>"), + ("X", "::std::vec::Vec"), + ("Y", "::std::vec::Vec"), + ("Z", "::std::option::Option") ]) } #[test] fn test_action() { compare(r#" -grammar { +grammar; extern token { enum Tok { } } X = { @@ -146,7 +139,6 @@ grammar { }; Y: i32 = "foo" => 22; -} "#,vec![ ("X", "i32"), ("Y", "i32"), @@ -156,7 +148,7 @@ grammar { #[test] fn test_inconsistent_action() { let grammar = parser::parse_grammar(" -grammar { +grammar; extern token { enum Tok { } } X = { @@ -168,7 +160,6 @@ grammar { Y: i32 = \"foo\" => 22; Z: u32 = \"bar\" => 22; -} ").unwrap(); let actual = expand_macros(grammar).unwrap(); diff --git a/lalrpop/src/normalize/validate/mod.rs b/lalrpop/src/normalize/validate/mod.rs index 87b3c64..ac90f5a 100644 --- a/lalrpop/src/normalize/validate/mod.rs +++ b/lalrpop/src/normalize/validate/mod.rs @@ -70,14 +70,14 @@ impl<'grammar> Validator<'grammar> { for associated_type in &data.associated_types { if !allowed_names.contains(&associated_type.type_name) { return_err!( - associated_type.span, + associated_type.type_span, "associated type `{}` not recognized, \ try one of the following: {}", associated_type.type_name, Sep(", ", &allowed_names)); } else if !new_names.insert(associated_type.type_name) { return_err!( - associated_type.span, + associated_type.type_span, "associated type `{}` already specified", associated_type.type_name); } diff --git a/lalrpop/src/normalize/validate/test.rs b/lalrpop/src/normalize/validate/test.rs index e28833f..6d809b5 100644 --- a/lalrpop/src/normalize/validate/test.rs +++ b/lalrpop/src/normalize/validate/test.rs @@ -1,9 +1,5 @@ -use intern::intern; use parser; -use normalize::macro_expand::expand_macros; -use normalize::tyinfer::infer_types; -use grammar::parse_tree::{NonterminalString, Span}; -use grammar::repr::TypeRepr; +use grammar::parse_tree::{Span}; use regex::Regex; fn check_err(expected_err: &str, grammar: &str) { @@ -36,33 +32,42 @@ fn check_err(expected_err: &str, grammar: &str) { fn unknown_nonterminal() { check_err( "no definition found for nonterminal `Y`", - r#"grammar { X = X >>>Y<<<; }"#); + r#"grammar; X = X >>>Y<<<;"#); } #[test] fn repeated_macro_arg() { check_err( "multiple macro arguments declared with the name `Y`", - r#"grammar { >>>X <<<= "foo"; }"#); + r#"grammar; >>>X <<<= "foo";"#); } #[test] fn unknown_nonterminal_two() { check_err( "no definition found for nonterminal `Expr`", - r#"grammar { Term = { => n.as_num(); "A" <>>>Expr<<<> "B"; }; }"#); + r#"grammar; Term = { => n.as_num(); "A" <>>>Expr<<<> "B"; };"#); } #[test] fn named_symbols() { check_err( - r#"named symbols (like `"Num"`) require a custom action"#, - r#"grammar { Term = { >>"Num"<<<>; }; }"#); + r#"named symbols \(like `"Num"`\) require a custom action"#, + r#"grammar; Term = { >>"Num"<<<>; };"#); } #[test] fn bad_assoc_type() { check_err( - r#"named symbols (like `"Num"`) require a custom action"#, - r#"grammar { extern token { type Foo = i32; } }"#); + r#"associated type `Foo` not recognized"#, + r#"grammar; extern token { type >>>Foo <<<= i32; enum Tok { } }"#); +} + +#[test] +fn dup_assoc_type() { + check_err( + r#"associated type `Location` already specified"#, + r#"grammar; extern token { type Location = i32; + type >>>Location <<<= u32; + enum Tok { } }"#); } diff --git a/lalrpop/src/parser/mod.rs b/lalrpop/src/parser/mod.rs index a8a5d83..ab69339 100644 --- a/lalrpop/src/parser/mod.rs +++ b/lalrpop/src/parser/mod.rs @@ -265,8 +265,10 @@ rusty_peg! { }; ASSOCIATED_TYPE: AssociatedType = - ( "type" "=" ";" ) => { - AssociatedType { span: Span(lo, hi), type_name: n, type_ref: t } + ("type" "=" ";") => { + AssociatedType { type_span: Span(lo1, hi1), + type_name: n, + type_ref: t } }; CONVERSION: Conversion = diff --git a/lalrpop/src/parser/test.rs b/lalrpop/src/parser/test.rs index 5850e92..080bcdd 100644 --- a/lalrpop/src/parser/test.rs +++ b/lalrpop/src/parser/test.rs @@ -1,4 +1,4 @@ -use grammar::parse_tree::{Symbol, SymbolKind, TypeRef}; +use grammar::parse_tree::{SymbolKind, TypeRef}; #[test] fn type_ref() {