refactor grammar to prevent undesirable nesting of symbols and

so forth
This commit is contained in:
Niko Matsakis 2015-06-25 22:39:11 -07:00
parent 388fbcb495
commit 6192b0b2a1
4 changed files with 42 additions and 18 deletions

View File

@ -174,7 +174,7 @@ pub enum Symbol {
// ~X
Choose(Box<Symbol>),
// ~x:X
// x:X
Name(InternedString, Box<Symbol>),
}

View File

@ -142,7 +142,7 @@ grammar {
X = {
Y;
~l:X "+" ~r:Y => l + r;
l:X "+" r:Y => l + r;
};
Y: i32 = "foo" => 22;
@ -162,7 +162,7 @@ grammar {
X = {
Y;
Z;
~l:X \"+\" ~r:Y => l + r;
l:X \"+\" r:Y => l + r;
};
Y: i32 = \"foo\" => 22;

View File

@ -102,7 +102,16 @@ rusty_peg! {
// Symbols
SYMBOL: Symbol =
fold(<lhs:SYMBOL0>,
(NAMED_SYMBOL / CHOSEN_SYMBOL / SYMBOL0);
NAMED_SYMBOL: Symbol =
(<l:ID> ":" <s:SYMBOL0>) => Symbol::Name(l, Box::new(s));
CHOSEN_SYMBOL: Symbol =
("~" <s:SYMBOL0>) => Symbol::Choose(Box::new(s));
SYMBOL0: Symbol =
fold(<lhs:SYMBOL1>,
(<lo:POSL> <op:REPEAT_OP> <hi:POSR>) => {
Symbol::Repeat(Box::new(RepeatSymbol { span: Span(lo, hi),
symbol: lhs,
@ -114,9 +123,8 @@ rusty_peg! {
REPEAT_OP_STAR: RepeatOp = "*" => RepeatOp::Star;
REPEAT_OP_QUESTION: RepeatOp = "?" => RepeatOp::Question;
SYMBOL0: Symbol =
(NAMED_SYMBOL / CHOSEN_SYMBOL / MACRO_SYMBOL / TERMINAL_SYMBOL /
NT_SYMBOL / ESCAPE_SYMBOL / PAREN_SYMBOL);
SYMBOL1: Symbol =
(MACRO_SYMBOL / TERMINAL_SYMBOL / NT_SYMBOL / ESCAPE_SYMBOL / PAREN_SYMBOL);
MACRO_SYMBOL: Symbol =
(<lo:POSL> <l:NONTERMINAL_ID> "<" <m:{MACRO_ARG_START}> <n:[SYMBOL]> ">" <hi:POSR>) => {
@ -145,12 +153,6 @@ rusty_peg! {
(<lo:POSL> <s:{SYMBOL}> <hi:POSR>) => ExprSymbol { span: Span(lo, hi),
symbols: s };
NAMED_SYMBOL: Symbol =
(<l:ID> ":" <s:SYMBOL>) => Symbol::Name(l, Box::new(s));
CHOSEN_SYMBOL: Symbol =
("~" <s:SYMBOL>) => Symbol::Choose(Box::new(s));
// TypeRef
TYPE_REF: TypeRef =

View File

@ -1,4 +1,4 @@
use grammar::parse_tree::TypeRef;
use grammar::parse_tree::{Symbol, TypeRef};
#[test]
fn type_ref() {
@ -66,7 +66,7 @@ fn paren_with_plus_and_anon() {
#[test]
fn named_choice() {
super::parse_grammar(r#"grammar { Expr = ~n:Alt; }"#).unwrap();
super::parse_grammar(r#"grammar { Expr = n:Alt; }"#).unwrap();
}
#[test]
@ -82,14 +82,14 @@ fn token_expr() {
#[test]
fn map1() {
super::parse_grammar(
r#"grammar { Expr = ~n:Alt+ => { { foo } }; }"#).unwrap();
r#"grammar { Expr = n:Alt+ => { { foo } }; }"#).unwrap();
}
#[test]
#[allow(non_snake_case)]
fn mapN() {
super::parse_grammar(
r#"grammar { Expr = { Bar => { Baz }; X ~n:Bar => { Y }; }; }"#).unwrap();
r#"grammar { Expr = { Bar => { Baz }; X n:Bar => { Y }; }; }"#).unwrap();
}
#[test]
@ -101,10 +101,32 @@ fn macro_symbols() {
super::parse_symbol(r#"Foo<"Baz"+, ("Balooga" Potato),>"#).unwrap();
}
#[test]
fn symbol_precedence() {
// check that we parse this as choosing a X+
let sym = super::parse_symbol(r#"~X+"#).unwrap();
assert!(match sym {
Symbol::Choose(..) => true,
_ => false
});
let sym = super::parse_symbol(r#"n:X+"#).unwrap();
assert!(match sym {
Symbol::Name(..) => true,
_ => false
});
}
#[test]
fn symbol_choose_name() {
// check that we can parse ~S and x:S but not both
assert!(super::parse_symbol(r#"~x:X+"#).is_err());
}
#[test]
fn macro_nt() {
super::parse_nonterminal(
r#"Comma<E>: Vec<E> = ~v:(~E ",")* ~e:E? => v.into_iter().chain(e.into_iter()).collect();"#)
r#"Comma<E>: Vec<E> = v:(~E ",")* e:E? => v.into_iter().chain(e.into_iter()).collect();"#)
.unwrap();
}