Add a KleeneOp enum for clarity
This commit is contained in:
parent
34dacb80ce
commit
94d6eee335
6 changed files with 42 additions and 30 deletions
|
@ -609,6 +609,14 @@ impl Delimiter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
|
||||||
|
/// for token sequences.
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
|
pub enum KleeneOp {
|
||||||
|
ZeroOrMore,
|
||||||
|
OneOrMore,
|
||||||
|
}
|
||||||
|
|
||||||
/// When the main rust parser encounters a syntax-extension invocation, it
|
/// When the main rust parser encounters a syntax-extension invocation, it
|
||||||
/// parses the arguments to the invocation as a token-tree. This is a very
|
/// parses the arguments to the invocation as a token-tree. This is a very
|
||||||
/// loose structure, such that all sorts of different AST-fragments can
|
/// loose structure, such that all sorts of different AST-fragments can
|
||||||
|
@ -633,12 +641,9 @@ pub enum TokenTree {
|
||||||
|
|
||||||
// These only make sense for right-hand-sides of MBE macros:
|
// These only make sense for right-hand-sides of MBE macros:
|
||||||
|
|
||||||
/// A kleene-style repetition sequence with a span, a `TTForest`,
|
/// A Kleene-style repetition sequence with an optional separator.
|
||||||
/// an optional separator, and a boolean where true indicates
|
|
||||||
/// zero or more (..), and false indicates one or more (+).
|
|
||||||
// FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST.
|
// FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST.
|
||||||
TtSequence(Span, Rc<Vec<TokenTree>>, Option<::parse::token::Token>, bool),
|
TtSequence(Span, Rc<Vec<TokenTree>>, Option<::parse::token::Token>, KleeneOp),
|
||||||
|
|
||||||
/// A syntactic variable that will be filled in by macro expansion.
|
/// A syntactic variable that will be filled in by macro expansion.
|
||||||
TtNonterminal(Span, Ident)
|
TtNonterminal(Span, Ident)
|
||||||
}
|
}
|
||||||
|
@ -711,9 +716,9 @@ pub type Matcher = Spanned<Matcher_>;
|
||||||
pub enum Matcher_ {
|
pub enum Matcher_ {
|
||||||
/// Match one token
|
/// Match one token
|
||||||
MatchTok(::parse::token::Token),
|
MatchTok(::parse::token::Token),
|
||||||
/// Match repetitions of a sequence: body, separator, zero ok?,
|
/// Match repetitions of a sequence: body, separator, Kleene operator,
|
||||||
/// lo, hi position-in-match-array used:
|
/// lo, hi position-in-match-array used:
|
||||||
MatchSeq(Vec<Matcher> , Option<::parse::token::Token>, bool, uint, uint),
|
MatchSeq(Vec<Matcher> , Option<::parse::token::Token>, KleeneOp, uint, uint),
|
||||||
/// Parse a Rust NT: name to bind, name of NT, position in match array:
|
/// Parse a Rust NT: name to bind, name of NT, position in match array:
|
||||||
MatchNonterminal(Ident, Ident, uint)
|
MatchNonterminal(Ident, Ident, uint)
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,9 +323,9 @@ pub fn parse(sess: &ParseSess,
|
||||||
} else {
|
} else {
|
||||||
match ei.elts[idx].node.clone() {
|
match ei.elts[idx].node.clone() {
|
||||||
/* need to descend into sequence */
|
/* need to descend into sequence */
|
||||||
MatchSeq(ref matchers, ref sep, zero_ok,
|
MatchSeq(ref matchers, ref sep, kleene_op,
|
||||||
match_idx_lo, match_idx_hi) => {
|
match_idx_lo, match_idx_hi) => {
|
||||||
if zero_ok {
|
if kleene_op == ast::ZeroOrMore {
|
||||||
let mut new_ei = ei.clone();
|
let mut new_ei = ei.clone();
|
||||||
new_ei.idx += 1u;
|
new_ei.idx += 1u;
|
||||||
//we specifically matched zero repeats.
|
//we specifically matched zero repeats.
|
||||||
|
|
|
@ -232,10 +232,11 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
|
||||||
ms(MatchSeq(vec!(
|
ms(MatchSeq(vec!(
|
||||||
ms(MatchNonterminal(lhs_nm, special_idents::matchers, 0u)),
|
ms(MatchNonterminal(lhs_nm, special_idents::matchers, 0u)),
|
||||||
ms(MatchTok(FAT_ARROW)),
|
ms(MatchTok(FAT_ARROW)),
|
||||||
ms(MatchNonterminal(rhs_nm, special_idents::tt, 1u))), Some(SEMI), false, 0u, 2u)),
|
ms(MatchNonterminal(rhs_nm, special_idents::tt, 1u))), Some(SEMI),
|
||||||
|
ast::OneOrMore, 0u, 2u)),
|
||||||
//to phase into semicolon-termination instead of
|
//to phase into semicolon-termination instead of
|
||||||
//semicolon-separation
|
//semicolon-separation
|
||||||
ms(MatchSeq(vec!(ms(MatchTok(SEMI))), None, true, 2u, 2u)));
|
ms(MatchSeq(vec!(ms(MatchTok(SEMI))), None, ast::ZeroOrMore, 2u, 2u)));
|
||||||
|
|
||||||
|
|
||||||
// Parse the macro_rules! invocation (`none` is for no interpolations):
|
// Parse the macro_rules! invocation (`none` is for no interpolations):
|
||||||
|
|
|
@ -227,9 +227,9 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
|
||||||
r.stack.last_mut().unwrap().idx += 1;
|
r.stack.last_mut().unwrap().idx += 1;
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
TtSequence(sp, tts, sep, zerok) => {
|
TtSequence(sp, tts, sep, kleene_op) => {
|
||||||
// FIXME(pcwalton): Bad copy.
|
// FIXME(pcwalton): Bad copy.
|
||||||
match lockstep_iter_size(&TtSequence(sp, tts.clone(), sep.clone(), zerok), r) {
|
match lockstep_iter_size(&TtSequence(sp, tts.clone(), sep.clone(), kleene_op), r) {
|
||||||
LisUnconstrained => {
|
LisUnconstrained => {
|
||||||
r.sp_diag.span_fatal(
|
r.sp_diag.span_fatal(
|
||||||
sp.clone(), /* blame macro writer */
|
sp.clone(), /* blame macro writer */
|
||||||
|
@ -243,7 +243,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
|
||||||
}
|
}
|
||||||
LisConstraint(len, _) => {
|
LisConstraint(len, _) => {
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
if !zerok {
|
if kleene_op == ast::OneOrMore {
|
||||||
// FIXME #2887 blame invoker
|
// FIXME #2887 blame invoker
|
||||||
r.sp_diag.span_fatal(sp.clone(),
|
r.sp_diag.span_fatal(sp.clone(),
|
||||||
"this must repeat at least once");
|
"this must repeat at least once");
|
||||||
|
|
|
@ -2497,27 +2497,30 @@ impl<'a> Parser<'a> {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an optional separator followed by a kleene-style
|
/// Parse an optional separator followed by a Kleene-style
|
||||||
/// repetition token (+ or *).
|
/// repetition token (+ or *).
|
||||||
pub fn parse_sep_and_zerok(&mut self) -> (Option<token::Token>, bool) {
|
pub fn parse_sep_and_kleene_op(&mut self) -> (Option<token::Token>, ast::KleeneOp) {
|
||||||
fn parse_zerok(parser: &mut Parser) -> Option<bool> {
|
fn parse_kleene_op(parser: &mut Parser) -> Option<ast::KleeneOp> {
|
||||||
match parser.token {
|
match parser.token {
|
||||||
token::BINOP(token::STAR) | token::BINOP(token::PLUS) => {
|
token::BINOP(token::STAR) => {
|
||||||
let zerok = parser.token == token::BINOP(token::STAR);
|
|
||||||
parser.bump();
|
parser.bump();
|
||||||
Some(zerok)
|
Some(ast::ZeroOrMore)
|
||||||
|
},
|
||||||
|
token::BINOP(token::PLUS) => {
|
||||||
|
parser.bump();
|
||||||
|
Some(ast::OneOrMore)
|
||||||
},
|
},
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match parse_zerok(self) {
|
match parse_kleene_op(self) {
|
||||||
Some(zerok) => return (None, zerok),
|
Some(kleene_op) => return (None, kleene_op),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let separator = self.bump_and_get();
|
let separator = self.bump_and_get();
|
||||||
match parse_zerok(self) {
|
match parse_kleene_op(self) {
|
||||||
Some(zerok) => (Some(separator), zerok),
|
Some(zerok) => (Some(separator), zerok),
|
||||||
None => self.fatal("expected `*` or `+`")
|
None => self.fatal("expected `*` or `+`")
|
||||||
}
|
}
|
||||||
|
@ -2564,11 +2567,11 @@ impl<'a> Parser<'a> {
|
||||||
seq_sep_none(),
|
seq_sep_none(),
|
||||||
|p| p.parse_token_tree()
|
|p| p.parse_token_tree()
|
||||||
);
|
);
|
||||||
let (s, z) = p.parse_sep_and_zerok();
|
let (sep, repeat) = p.parse_sep_and_kleene_op();
|
||||||
let seq = match seq {
|
let seq = match seq {
|
||||||
Spanned { node, .. } => node,
|
Spanned { node, .. } => node,
|
||||||
};
|
};
|
||||||
TtSequence(mk_sp(sp.lo, p.span.hi), Rc::new(seq), s, z)
|
TtSequence(mk_sp(sp.lo, p.span.hi), Rc::new(seq), sep, repeat)
|
||||||
} else {
|
} else {
|
||||||
TtNonterminal(sp, p.parse_ident())
|
TtNonterminal(sp, p.parse_ident())
|
||||||
}
|
}
|
||||||
|
@ -2679,8 +2682,8 @@ impl<'a> Parser<'a> {
|
||||||
if ms.len() == 0u {
|
if ms.len() == 0u {
|
||||||
self.fatal("repetition body must be nonempty");
|
self.fatal("repetition body must be nonempty");
|
||||||
}
|
}
|
||||||
let (sep, zerok) = self.parse_sep_and_zerok();
|
let (sep, kleene_op) = self.parse_sep_and_kleene_op();
|
||||||
MatchSeq(ms, sep, zerok, name_idx_lo, *name_idx)
|
MatchSeq(ms, sep, kleene_op, name_idx_lo, *name_idx)
|
||||||
} else {
|
} else {
|
||||||
let bound_to = self.parse_ident();
|
let bound_to = self.parse_ident();
|
||||||
self.expect(&token::COLON);
|
self.expect(&token::COLON);
|
||||||
|
|
|
@ -1037,20 +1037,23 @@ impl<'a> State<'a> {
|
||||||
_ => Ok(())
|
_ => Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::TtSequence(_, ref tts, ref sep, zerok) => {
|
ast::TtSequence(_, ref tts, ref separator, kleene_op) => {
|
||||||
try!(word(&mut self.s, "$("));
|
try!(word(&mut self.s, "$("));
|
||||||
for tt_elt in (*tts).iter() {
|
for tt_elt in (*tts).iter() {
|
||||||
try!(self.print_tt(tt_elt));
|
try!(self.print_tt(tt_elt));
|
||||||
}
|
}
|
||||||
try!(word(&mut self.s, ")"));
|
try!(word(&mut self.s, ")"));
|
||||||
match *sep {
|
match *separator {
|
||||||
Some(ref tk) => {
|
Some(ref tk) => {
|
||||||
try!(word(&mut self.s,
|
try!(word(&mut self.s,
|
||||||
parse::token::to_string(tk).as_slice()));
|
parse::token::to_string(tk).as_slice()));
|
||||||
}
|
}
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
word(&mut self.s, if zerok { "*" } else { "+" })
|
match kleene_op {
|
||||||
|
ast::ZeroOrMore => word(&mut self.s, "*"),
|
||||||
|
ast::OneOrMore => word(&mut self.s, "+"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast::TtNonterminal(_, name) => {
|
ast::TtNonterminal(_, name) => {
|
||||||
try!(word(&mut self.s, "$"));
|
try!(word(&mut self.s, "$"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue