Simplify parser a bit
This commit is contained in:
parent
6a8ce2cf34
commit
b826788be4
1 changed files with 50 additions and 72 deletions
|
@ -1,4 +1,5 @@
|
||||||
use syntax::ast::{Expr, Lit, TokenTree, TtDelimited, TtToken};
|
use syntax::ast::{Expr, Lit, TokenTree, TtDelimited, TtToken};
|
||||||
|
use syntax::codemap::Span;
|
||||||
use syntax::ext::base::ExtCtxt;
|
use syntax::ext::base::ExtCtxt;
|
||||||
use syntax::parse;
|
use syntax::parse;
|
||||||
use syntax::parse::parser::Parser as RustParser;
|
use syntax::parse::parser::Parser as RustParser;
|
||||||
|
@ -11,25 +12,6 @@ macro_rules! guard {
|
||||||
($e:expr) => (if !$e { return false; })
|
($e:expr) => (if !$e { return false; })
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! branch {
|
|
||||||
($self_:expr;) => (return false);
|
|
||||||
($self_:expr; $e:expr) => (branch!($self_; $e,));
|
|
||||||
($self_:expr; $e:expr, $($es:expr),*) => ({
|
|
||||||
let start_ptr = $self_.input.as_ptr();
|
|
||||||
if $e {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
if $self_.input.as_ptr() == start_ptr {
|
|
||||||
// Parsing failed, but did not consume input.
|
|
||||||
// Keep going.
|
|
||||||
branch!($self_; $($es),*)
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! dollar {
|
macro_rules! dollar {
|
||||||
() => (TtToken(_, token::Dollar))
|
() => (TtToken(_, token::Dollar))
|
||||||
}
|
}
|
||||||
|
@ -46,7 +28,8 @@ macro_rules! literal {
|
||||||
() => (TtToken(_, token::Literal(..)))
|
() => (TtToken(_, token::Literal(..)))
|
||||||
}
|
}
|
||||||
macro_rules! ident {
|
macro_rules! ident {
|
||||||
($x:pat) => (TtToken(_, token::Ident($x, token::IdentStyle::Plain)))
|
($x:pat) => (ident!(_, $x));
|
||||||
|
($sp:pat, $x:pat) => (TtToken($sp, token::Ident($x, token::IdentStyle::Plain)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(cx: &mut ExtCtxt, input: &[TokenTree]) -> Option<P<Expr>> {
|
pub fn parse(cx: &mut ExtCtxt, input: &[TokenTree]) -> Option<P<Expr>> {
|
||||||
|
@ -88,36 +71,52 @@ impl<'cx: 'r, 's: 'cx, 'i, 'r, 'o: 'r> Parser<'cx, 's, 'i, 'r, 'o> {
|
||||||
match self.input {
|
match self.input {
|
||||||
[] => return true,
|
[] => return true,
|
||||||
[semi!(), ..] => self.shift(1),
|
[semi!(), ..] => self.shift(1),
|
||||||
[ref tt, ..] => {
|
[_, ..] => guard!(self.markup()),
|
||||||
if !self.markup() {
|
|
||||||
self.render.cx.span_err(tt.get_span(), "invalid syntax");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn markup(&mut self) -> bool {
|
fn markup(&mut self) -> bool {
|
||||||
branch!(self;
|
match self.input {
|
||||||
self.literal(),
|
// Literal
|
||||||
self.splice(),
|
|
||||||
self.block(),
|
|
||||||
!self.in_attr && self.element())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn literal(&mut self) -> bool {
|
|
||||||
let (tt, minus) = match self.input {
|
|
||||||
[minus!(), ref tt @ literal!(), ..] => {
|
[minus!(), ref tt @ literal!(), ..] => {
|
||||||
self.shift(2);
|
self.shift(2);
|
||||||
(tt, true)
|
self.literal(tt, true)
|
||||||
},
|
},
|
||||||
[ref tt @ literal!(), ..] => {
|
[ref tt @ literal!(), ..] => {
|
||||||
self.shift(1);
|
self.shift(1);
|
||||||
(tt, false)
|
self.literal(tt, false)
|
||||||
},
|
},
|
||||||
_ => return false,
|
// Splice
|
||||||
};
|
[ref tt @ dollar!(), dollar!(), ..] => {
|
||||||
|
self.shift(2);
|
||||||
|
self.splice(Escape::PassThru, tt.get_span())
|
||||||
|
},
|
||||||
|
[ref tt @ dollar!(), ..] => {
|
||||||
|
self.shift(1);
|
||||||
|
self.splice(Escape::Escape, tt.get_span())
|
||||||
|
},
|
||||||
|
// Element
|
||||||
|
[ident!(sp, name), ..] => {
|
||||||
|
self.shift(1);
|
||||||
|
self.element(name.as_str(), sp)
|
||||||
|
},
|
||||||
|
// Block
|
||||||
|
[TtDelimited(_, ref d), ..] if d.delim == token::DelimToken::Brace => {
|
||||||
|
self.shift(1);
|
||||||
|
self.block(d.tts.as_slice())
|
||||||
|
},
|
||||||
|
// ???
|
||||||
|
_ => {
|
||||||
|
if let [ref tt, ..] = self.input {
|
||||||
|
self.render.cx.span_err(tt.get_span(), "invalid syntax");
|
||||||
|
}
|
||||||
|
false
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn literal(&mut self, tt: &TokenTree, minus: bool) -> bool {
|
||||||
let lit = self.new_rust_parser(vec![tt.clone()]).parse_lit();
|
let lit = self.new_rust_parser(vec![tt.clone()]).parse_lit();
|
||||||
match lit_to_string(self.render.cx, lit, minus) {
|
match lit_to_string(self.render.cx, lit, minus) {
|
||||||
Some(s) => self.render.string(s.as_slice(), Escape::Escape),
|
Some(s) => self.render.string(s.as_slice(), Escape::Escape),
|
||||||
|
@ -126,18 +125,7 @@ impl<'cx: 'r, 's: 'cx, 'i, 'r, 'o: 'r> Parser<'cx, 's, 'i, 'r, 'o> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn splice(&mut self) -> bool {
|
fn splice(&mut self, escape: Escape, sp: Span) -> bool {
|
||||||
let (escape, sp) = match self.input {
|
|
||||||
[ref tt @ dollar!(), dollar!(), ..] => {
|
|
||||||
self.shift(2);
|
|
||||||
(Escape::PassThru, tt.get_span())
|
|
||||||
},
|
|
||||||
[ref tt @ dollar!(), ..] => {
|
|
||||||
self.shift(1);
|
|
||||||
(Escape::Escape, tt.get_span())
|
|
||||||
},
|
|
||||||
_ => return false,
|
|
||||||
};
|
|
||||||
let tt = match self.input {
|
let tt = match self.input {
|
||||||
[ref tt, ..] => {
|
[ref tt, ..] => {
|
||||||
self.shift(1);
|
self.shift(1);
|
||||||
|
@ -152,15 +140,11 @@ impl<'cx: 'r, 's: 'cx, 'i, 'r, 'o: 'r> Parser<'cx, 's, 'i, 'r, 'o> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element(&mut self) -> bool {
|
fn element(&mut self, name: &str, sp: Span) -> bool {
|
||||||
let name = match self.input {
|
if self.in_attr {
|
||||||
[ident!(name), ..] => {
|
self.render.cx.span_err(sp, "unexpected element, you silly bumpkin");
|
||||||
self.shift(1);
|
return false;
|
||||||
name.as_str().to_string()
|
}
|
||||||
},
|
|
||||||
_ => return false,
|
|
||||||
};
|
|
||||||
let name = name.as_slice();
|
|
||||||
self.render.element_open_start(name);
|
self.render.element_open_start(name);
|
||||||
guard!(self.attrs());
|
guard!(self.attrs());
|
||||||
self.render.element_open_end();
|
self.render.element_open_end();
|
||||||
|
@ -184,18 +168,12 @@ impl<'cx: 'r, 's: 'cx, 'i, 'r, 'o: 'r> Parser<'cx, 's, 'i, 'r, 'o> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(&mut self) -> bool {
|
fn block(&mut self, tts: &[TokenTree]) -> bool {
|
||||||
match self.input {
|
Parser {
|
||||||
[TtDelimited(_, ref d), ..] if d.delim == token::DelimToken::Brace => {
|
in_attr: self.in_attr,
|
||||||
self.shift(1);
|
input: tts,
|
||||||
Parser {
|
render: self.render,
|
||||||
in_attr: self.in_attr,
|
}.markups()
|
||||||
input: d.tts.as_slice(),
|
|
||||||
render: self.render,
|
|
||||||
}.markups()
|
|
||||||
},
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue