auto merge of #13879 : huonw/rust/more-re, r=alexcrichton
Commits for details. This shouldn't change the generated code at all (except for switching to `LitBinary` from an explicit ExprVec of individual ExprLit bytes for `prefix_bytes`).
This commit is contained in:
commit
b5d6b07370
11 changed files with 77 additions and 106 deletions
|
|
@ -24,8 +24,11 @@
|
|||
extern crate regex;
|
||||
extern crate syntax;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::base::{
|
||||
SyntaxExtension, ExtCtxt, MacResult, MacExpr, DummyResult,
|
||||
NormalTT, BasicMacroExpander,
|
||||
|
|
@ -112,13 +115,13 @@ impl<'a> NfaGen<'a> {
|
|||
// expression returned.
|
||||
let num_cap_locs = 2 * self.prog.num_captures();
|
||||
let num_insts = self.prog.insts.len();
|
||||
let cap_names = self.vec_expr(self.names.as_slice(),
|
||||
|cx, name| match name {
|
||||
&Some(ref name) => {
|
||||
let cap_names = self.vec_expr(self.names.as_slice().iter(),
|
||||
|cx, name| match *name {
|
||||
Some(ref name) => {
|
||||
let name = name.as_slice();
|
||||
quote_expr!(cx, Some($name.to_owned()))
|
||||
}
|
||||
&None => quote_expr!(cx, None),
|
||||
None => cx.expr_none(self.sp),
|
||||
}
|
||||
);
|
||||
let prefix_anchor =
|
||||
|
|
@ -126,10 +129,12 @@ impl<'a> NfaGen<'a> {
|
|||
EmptyBegin(flags) if flags & FLAG_MULTI == 0 => true,
|
||||
_ => false,
|
||||
};
|
||||
let init_groups = self.vec_from_fn(num_cap_locs,
|
||||
|cx| quote_expr!(cx, None));
|
||||
let prefix_bytes = self.vec_expr(self.prog.prefix.as_slice().as_bytes(),
|
||||
|cx, b| quote_expr!(cx, $b));
|
||||
let init_groups = self.vec_expr(range(0, num_cap_locs),
|
||||
|cx, _| cx.expr_none(self.sp));
|
||||
|
||||
let prefix_lit = Rc::new(Vec::from_slice(self.prog.prefix.as_slice().as_bytes()));
|
||||
let prefix_bytes = self.cx.expr_lit(self.sp, ast::LitBinary(prefix_lit));
|
||||
|
||||
let check_prefix = self.check_prefix();
|
||||
let step_insts = self.step_insts();
|
||||
let add_insts = self.add_insts();
|
||||
|
|
@ -320,12 +325,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
|
|||
let nextpc = pc + 1;
|
||||
let body = match *inst {
|
||||
EmptyBegin(flags) => {
|
||||
let nl = '\n';
|
||||
let cond =
|
||||
if flags & FLAG_MULTI > 0 {
|
||||
quote_expr!(self.cx,
|
||||
self.chars.is_begin()
|
||||
|| self.chars.prev == Some($nl)
|
||||
|| self.chars.prev == Some('\n')
|
||||
)
|
||||
} else {
|
||||
quote_expr!(self.cx, self.chars.is_begin())
|
||||
|
|
@ -336,12 +340,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
|
|||
})
|
||||
}
|
||||
EmptyEnd(flags) => {
|
||||
let nl = '\n';
|
||||
let cond =
|
||||
if flags & FLAG_MULTI > 0 {
|
||||
quote_expr!(self.cx,
|
||||
self.chars.is_end()
|
||||
|| self.chars.cur == Some($nl)
|
||||
|| self.chars.cur == Some('\n')
|
||||
)
|
||||
} else {
|
||||
quote_expr!(self.cx, self.chars.is_end())
|
||||
|
|
@ -489,16 +492,16 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
|
|||
if flags & FLAG_DOTNL > 0 {
|
||||
quote_expr!(self.cx, self.add(nlist, $nextpc, caps))
|
||||
} else {
|
||||
let nl = '\n'; // no char lits allowed? wtf?
|
||||
quote_expr!(self.cx, {
|
||||
if self.chars.prev != Some($nl) {
|
||||
if self.chars.prev != Some('\n') {
|
||||
self.add(nlist, $nextpc, caps)
|
||||
}
|
||||
()
|
||||
})
|
||||
}
|
||||
}
|
||||
// EmptyBegin, EmptyEnd, EmptyWordBoundary, Save, Jump, Split
|
||||
_ => quote_expr!(self.cx, {}),
|
||||
_ => self.empty_block(),
|
||||
};
|
||||
self.arm_inst(pc, body)
|
||||
}).collect::<Vec<ast::Arm>>();
|
||||
|
|
@ -510,28 +513,22 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
|
|||
// This avoids a binary search (and is hopefully replaced by a jump
|
||||
// table).
|
||||
fn match_class(&self, casei: bool, ranges: &[(char, char)]) -> @ast::Expr {
|
||||
let expr_true = quote_expr!(self.cx, true);
|
||||
|
||||
let mut arms = ranges.iter().map(|&(mut start, mut end)| {
|
||||
if casei {
|
||||
start = start.to_uppercase();
|
||||
end = end.to_uppercase();
|
||||
}
|
||||
ast::Arm {
|
||||
attrs: vec!(),
|
||||
pats: vec!(@ast::Pat{
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.sp,
|
||||
node: ast::PatRange(quote_expr!(self.cx, $start),
|
||||
quote_expr!(self.cx, $end)),
|
||||
}),
|
||||
guard: None,
|
||||
body: quote_expr!(self.cx, true),
|
||||
}
|
||||
let pat = self.cx.pat(self.sp, ast::PatRange(quote_expr!(self.cx, $start),
|
||||
quote_expr!(self.cx, $end)));
|
||||
self.cx.arm(self.sp, vec!(pat), expr_true)
|
||||
}).collect::<Vec<ast::Arm>>();
|
||||
|
||||
arms.push(self.wild_arm_expr(quote_expr!(self.cx, false)));
|
||||
|
||||
let match_on = quote_expr!(self.cx, c);
|
||||
self.dummy_expr(ast::ExprMatch(match_on, arms))
|
||||
self.cx.expr_match(self.sp, match_on, arms)
|
||||
}
|
||||
|
||||
// Generates code for checking a literal prefix of the search string.
|
||||
|
|
@ -539,7 +536,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
|
|||
// Otherwise, a no-op is returned.
|
||||
fn check_prefix(&self) -> @ast::Expr {
|
||||
if self.prog.prefix.len() == 0 {
|
||||
quote_expr!(self.cx, {})
|
||||
self.empty_block()
|
||||
} else {
|
||||
quote_expr!(self.cx,
|
||||
if clist.size == 0 {
|
||||
|
|
@ -562,24 +559,20 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
|
|||
// never be used, but is added to satisfy the compiler complaining about
|
||||
// non-exhaustive patterns.
|
||||
fn match_insts(&self, mut arms: Vec<ast::Arm>) -> @ast::Expr {
|
||||
let mat_pc = quote_expr!(self.cx, pc);
|
||||
arms.push(self.wild_arm_expr(quote_expr!(self.cx, {})));
|
||||
self.dummy_expr(ast::ExprMatch(mat_pc, arms))
|
||||
arms.push(self.wild_arm_expr(self.empty_block()));
|
||||
self.cx.expr_match(self.sp, quote_expr!(self.cx, pc), arms)
|
||||
}
|
||||
|
||||
fn empty_block(&self) -> @ast::Expr {
|
||||
quote_expr!(self.cx, {})
|
||||
}
|
||||
|
||||
// Creates a match arm for the instruction at `pc` with the expression
|
||||
// `body`.
|
||||
fn arm_inst(&self, pc: uint, body: @ast::Expr) -> ast::Arm {
|
||||
ast::Arm {
|
||||
attrs: vec!(),
|
||||
pats: vec!(@ast::Pat{
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.sp,
|
||||
node: ast::PatLit(quote_expr!(self.cx, $pc)),
|
||||
}),
|
||||
guard: None,
|
||||
body: body,
|
||||
}
|
||||
let pc_pat = self.cx.pat_lit(self.sp, quote_expr!(self.cx, $pc));
|
||||
|
||||
self.cx.arm(self.sp, vec!(pc_pat), body)
|
||||
}
|
||||
|
||||
// Creates a wild-card match arm with the expression `body`.
|
||||
|
|
@ -596,56 +589,13 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
|
|||
}
|
||||
}
|
||||
|
||||
// Builds a `[a, b, .., len]` expression where each element is the result
|
||||
// of executing `to_expr`.
|
||||
fn vec_from_fn(&self, len: uint, to_expr: |&ExtCtxt| -> @ast::Expr)
|
||||
-> @ast::Expr {
|
||||
self.vec_expr(Vec::from_elem(len, ()).as_slice(),
|
||||
|cx, _| to_expr(cx))
|
||||
}
|
||||
|
||||
// Converts `xs` to a `[x1, x2, .., xN]` expression by calling `to_expr`
|
||||
// on each element in `xs`.
|
||||
fn vec_expr<T>(&self, xs: &[T], to_expr: |&ExtCtxt, &T| -> @ast::Expr)
|
||||
fn vec_expr<T, It: Iterator<T>>(&self, xs: It, to_expr: |&ExtCtxt, T| -> @ast::Expr)
|
||||
-> @ast::Expr {
|
||||
let mut exprs = vec!();
|
||||
for x in xs.iter() {
|
||||
exprs.push(to_expr(self.cx, x))
|
||||
}
|
||||
let vec_exprs = self.dummy_expr(ast::ExprVec(exprs));
|
||||
quote_expr!(self.cx, $vec_exprs)
|
||||
}
|
||||
|
||||
// Creates an expression with a dummy node ID given an underlying
|
||||
// `ast::Expr_`.
|
||||
fn dummy_expr(&self, e: ast::Expr_) -> @ast::Expr {
|
||||
@ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
node: e,
|
||||
span: self.sp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This trait is defined in the quote module in the syntax crate, but I
|
||||
// don't think it's exported.
|
||||
// Interestingly, quote_expr! only requires that a 'to_tokens' method be
|
||||
// defined rather than satisfying a particular trait.
|
||||
#[doc(hidden)]
|
||||
trait ToTokens {
|
||||
fn to_tokens(&self, cx: &ExtCtxt) -> Vec<ast::TokenTree>;
|
||||
}
|
||||
|
||||
impl ToTokens for char {
|
||||
fn to_tokens(&self, _: &ExtCtxt) -> Vec<ast::TokenTree> {
|
||||
vec!(ast::TTTok(codemap::DUMMY_SP, token::LIT_CHAR((*self) as u32)))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for bool {
|
||||
fn to_tokens(&self, _: &ExtCtxt) -> Vec<ast::TokenTree> {
|
||||
let ident = token::IDENT(token::str_to_ident(self.to_str()), false);
|
||||
vec!(ast::TTTok(codemap::DUMMY_SP, ident))
|
||||
let exprs = xs.map(|x| to_expr(self.cx, x)).collect();
|
||||
self.cx.expr_vec(self.sp, exprs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ use rustc::metadata::decoder;
|
|||
|
||||
use std::local_data;
|
||||
use std::strbuf::StrBuf;
|
||||
use std;
|
||||
|
||||
use core;
|
||||
use doctree;
|
||||
|
|
@ -1246,7 +1245,7 @@ fn lit_to_str(lit: &ast::Lit) -> ~str {
|
|||
match lit.node {
|
||||
ast::LitStr(ref st, _) => st.get().to_owned(),
|
||||
ast::LitBinary(ref data) => format!("{:?}", data.as_slice()),
|
||||
ast::LitChar(c) => "'".to_owned() + std::char::from_u32(c).unwrap().to_str() + "'",
|
||||
ast::LitChar(c) => format!("'{}'", c),
|
||||
ast::LitInt(i, _t) => i.to_str(),
|
||||
ast::LitUint(u, _t) => u.to_str(),
|
||||
ast::LitIntUnsuffixed(i) => i.to_str(),
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ pub type Lit = Spanned<Lit_>;
|
|||
pub enum Lit_ {
|
||||
LitStr(InternedString, StrStyle),
|
||||
LitBinary(Rc<Vec<u8> >),
|
||||
LitChar(u32),
|
||||
LitChar(char),
|
||||
LitInt(i64, IntTy),
|
||||
LitUint(u64, UintTy),
|
||||
LitIntUnsuffixed(i64),
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@ use ext::base::*;
|
|||
use ext::base;
|
||||
use ext::build::AstBuilder;
|
||||
|
||||
use std::char;
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
// Gather all argument expressions
|
||||
let exprs = match get_exprs_from_tts(cx, sp, tts) {
|
||||
|
|
@ -59,7 +57,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
|
|||
|
||||
// char literal, push to vector expression
|
||||
ast::LitChar(v) => {
|
||||
if char::from_u32(v).unwrap().is_ascii() {
|
||||
if v.is_ascii() {
|
||||
bytes.push(cx.expr_u8(expr.span, v as u8));
|
||||
} else {
|
||||
cx.span_err(expr.span, "non-ascii char literal in bytes!")
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ use ext::base;
|
|||
use ext::build::AstBuilder;
|
||||
use parse::token;
|
||||
|
||||
use std::char;
|
||||
use std::strbuf::StrBuf;
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
|
||||
|
|
@ -35,7 +34,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
|
|||
accumulator.push_str(s.get());
|
||||
}
|
||||
ast::LitChar(c) => {
|
||||
accumulator.push_char(char::from_u32(c).unwrap());
|
||||
accumulator.push_char(c);
|
||||
}
|
||||
ast::LitInt(i, _) | ast::LitIntUnsuffixed(i) => {
|
||||
accumulator.push_str(format!("{}", i));
|
||||
|
|
|
|||
|
|
@ -561,7 +561,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
|||
|
||||
// Translate the format
|
||||
let fill = match arg.format.fill { Some(c) => c, None => ' ' };
|
||||
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill as u32));
|
||||
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill));
|
||||
let align = match arg.format.align {
|
||||
parse::AlignLeft => {
|
||||
self.ecx.path_global(sp, self.parsepath("AlignLeft"))
|
||||
|
|
|
|||
|
|
@ -125,6 +125,26 @@ pub mod rt {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToSource for () {
|
||||
fn to_source(&self) -> ~str {
|
||||
"()".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSource for bool {
|
||||
fn to_source(&self) -> ~str {
|
||||
let lit = dummy_spanned(ast::LitBool(*self));
|
||||
pprust::lit_to_str(&lit)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSource for char {
|
||||
fn to_source(&self) -> ~str {
|
||||
let lit = dummy_spanned(ast::LitChar(*self));
|
||||
pprust::lit_to_str(&lit)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSource for int {
|
||||
fn to_source(&self) -> ~str {
|
||||
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI));
|
||||
|
|
@ -227,6 +247,9 @@ pub mod rt {
|
|||
impl_to_tokens!(@ast::Expr)
|
||||
impl_to_tokens!(ast::Block)
|
||||
impl_to_tokens_self!(&'a str)
|
||||
impl_to_tokens!(())
|
||||
impl_to_tokens!(char)
|
||||
impl_to_tokens!(bool)
|
||||
impl_to_tokens!(int)
|
||||
impl_to_tokens!(i8)
|
||||
impl_to_tokens!(i16)
|
||||
|
|
|
|||
|
|
@ -874,7 +874,7 @@ fn next_token_inner(rdr: &mut StringReader) -> token::Token {
|
|||
"unterminated character constant".to_owned());
|
||||
}
|
||||
bump(rdr); // advance curr past token
|
||||
return token::LIT_CHAR(c2 as u32);
|
||||
return token::LIT_CHAR(c2);
|
||||
}
|
||||
'"' => {
|
||||
let mut accum_str = StrBuf::new();
|
||||
|
|
@ -1097,17 +1097,17 @@ mod test {
|
|||
|
||||
#[test] fn character_a() {
|
||||
assert_eq!(setup(&mk_sh(), "'a'".to_owned()).next_token().tok,
|
||||
token::LIT_CHAR('a' as u32));
|
||||
token::LIT_CHAR('a'));
|
||||
}
|
||||
|
||||
#[test] fn character_space() {
|
||||
assert_eq!(setup(&mk_sh(), "' '".to_owned()).next_token().tok,
|
||||
token::LIT_CHAR(' ' as u32));
|
||||
token::LIT_CHAR(' '));
|
||||
}
|
||||
|
||||
#[test] fn character_escaped() {
|
||||
assert_eq!(setup(&mk_sh(), "'\\n'".to_owned()).next_token().tok,
|
||||
token::LIT_CHAR('\n' as u32));
|
||||
token::LIT_CHAR('\n'));
|
||||
}
|
||||
|
||||
#[test] fn lifetime_name() {
|
||||
|
|
@ -1128,7 +1128,7 @@ mod test {
|
|||
|
||||
#[test] fn nested_block_comments() {
|
||||
assert_eq!(setup(&mk_sh(), "/* /* */ */'a'".to_owned()).next_token().tok,
|
||||
token::LIT_CHAR('a' as u32));
|
||||
token::LIT_CHAR('a'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use util::interner;
|
|||
|
||||
use serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
use std::cast;
|
||||
use std::char;
|
||||
use std::fmt;
|
||||
use std::local_data;
|
||||
use std::path::BytesContainer;
|
||||
|
|
@ -81,7 +80,7 @@ pub enum Token {
|
|||
DOLLAR,
|
||||
|
||||
/* Literals */
|
||||
LIT_CHAR(u32),
|
||||
LIT_CHAR(char),
|
||||
LIT_INT(i64, ast::IntTy),
|
||||
LIT_UINT(u64, ast::UintTy),
|
||||
LIT_INT_UNSUFFIXED(i64),
|
||||
|
|
@ -195,7 +194,7 @@ pub fn to_str(t: &Token) -> ~str {
|
|||
/* Literals */
|
||||
LIT_CHAR(c) => {
|
||||
let mut res = StrBuf::from_str("'");
|
||||
char::from_u32(c).unwrap().escape_default(|c| {
|
||||
c.escape_default(|c| {
|
||||
res.push_char(c);
|
||||
});
|
||||
res.push_char('\'');
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ use print::pp::{Breaks, Consistent, Inconsistent, eof};
|
|||
use print::pp;
|
||||
|
||||
use std::cast;
|
||||
use std::char;
|
||||
use std::io::{IoResult, MemWriter};
|
||||
use std::io;
|
||||
use std::rc::Rc;
|
||||
|
|
@ -2196,7 +2195,7 @@ impl<'a> State<'a> {
|
|||
ast::LitStr(ref st, style) => self.print_string(st.get(), style),
|
||||
ast::LitChar(ch) => {
|
||||
let mut res = StrBuf::from_str("'");
|
||||
char::from_u32(ch).unwrap().escape_default(|c| res.push_char(c));
|
||||
ch.escape_default(|c| res.push_char(c));
|
||||
res.push_char('\'');
|
||||
word(&mut self.s, res.into_owned())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ fn syntax_extension(cx: &ExtCtxt) {
|
|||
let _c: @syntax::ast::Pat = quote_pat!(cx, (x, 1 .. 4, *) );
|
||||
let _d: @syntax::ast::Stmt = quote_stmt!(cx, let x = $a; );
|
||||
let _e: @syntax::ast::Expr = quote_expr!(cx, match foo { $p_toks => 10 } );
|
||||
|
||||
let _f: @syntax::ast::Expr = quote_expr!(cx, ());
|
||||
let _g: @syntax::ast::Expr = quote_expr!(cx, true);
|
||||
let _h: @syntax::ast::Expr = quote_expr!(cx, 'a');
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue