Skip to content
Merged
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ rust:
- nightly
- beta
- stable
- 1.30.0

script:
- cargo build --verbose
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cssparser"
version = "0.25.4"
version = "0.25.5"
authors = [ "Simon Sapin <simon.sapin@exyr.org>" ]

description = "Rust implementation of CSS Syntax Level 3"
Expand Down
9 changes: 6 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ mod codegen {
println!("cargo:rerun-if-changed={}", input.display());

// We have stack overflows on Servo's CI.
let handle = Builder::new().stack_size(128 * 1024 * 1024).spawn(move || {
match_byte::expand(&input, &output);
}).unwrap();
let handle = Builder::new()
.stack_size(128 * 1024 * 1024)
.spawn(move || {
match_byte::expand(&input, &output);
})
.unwrap();

handle.join().unwrap();
}
Expand Down
52 changes: 31 additions & 21 deletions build/match_byte.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,27 @@ use syn::parse::{Parse, ParseStream, Result};

use proc_macro2::{Span, TokenStream};

struct MatchByteParser {
}
struct MatchByteParser {}

pub fn expand(from: &Path, to: &Path) {
let mut source = String::new();
File::open(from).unwrap().read_to_string(&mut source).unwrap();
File::open(from)
.unwrap()
.read_to_string(&mut source)
.unwrap();
let ast = syn::parse_file(&source).expect("Parsing rules.rs module");
let mut m = MatchByteParser {};
let ast = m.fold_file(ast);

let code = ast.into_token_stream().to_string().replace("{ ", "{\n").replace(" }", "\n}");
File::create(to).unwrap().write_all(code.as_bytes()).unwrap();
let code = ast
.into_token_stream()
.to_string()
.replace("{ ", "{\n")
.replace(" }", "\n}");
File::create(to)
.unwrap()
.write_all(code.as_bytes())
.unwrap();
}

struct MatchByte {
Expand All @@ -45,7 +54,7 @@ impl Parse for MatchByte {
arms.push(input.call(syn::Arm::parse)?);
}
arms
}
},
})
}
}
Expand All @@ -55,16 +64,14 @@ fn get_byte_from_expr_lit(expr: &Box<syn::Expr>) -> u8 {
syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => {
if let syn::Lit::Byte(ref byte) = *lit {
byte.value()
}
else {
} else {
panic!("Found a pattern that wasn't a byte")
}
},
}
_ => unreachable!(),
}
}


/// Expand a TokenStream corresponding to the `match_byte` macro.
///
/// ## Example
Expand Down Expand Up @@ -93,12 +100,12 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {

for pat in &arm.pats {
match pat {
&syn::Pat::Lit(syn::PatLit{ref expr}) => {
&syn::Pat::Lit(syn::PatLit { ref expr }) => {
let value = get_byte_from_expr_lit(expr);
if table[value as usize] == 0 {
table[value as usize] = case_id as u8;
}
},
}
&syn::Pat::Range(syn::PatRange { ref lo, ref hi, .. }) => {
let lo = get_byte_from_expr_lit(lo);
let hi = get_byte_from_expr_lit(hi);
Expand All @@ -110,14 +117,14 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {
if table[hi as usize] == 0 {
table[hi as usize] = case_id as u8;
}
},
}
&syn::Pat::Wild(_) => {
for byte in table.iter_mut() {
if *byte == 0 {
*byte = case_id as u8;
}
}
},
}
&syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => {
assert_eq!(wildcard, None);
wildcard = Some(ident);
Expand All @@ -126,7 +133,7 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {
*byte = case_id as u8;
}
}
},
}
_ => {
panic!("Unexpected pattern: {:?}. Buggy code ?", pat);
}
Expand Down Expand Up @@ -159,11 +166,14 @@ fn expand_match_byte(body: &TokenStream) -> syn::Expr {
impl Fold for MatchByteParser {
fn fold_stmt(&mut self, stmt: syn::Stmt) -> syn::Stmt {
match stmt {
syn::Stmt::Item(syn::Item::Macro(syn::ItemMacro{ ref mac, .. })) => {
syn::Stmt::Item(syn::Item::Macro(syn::ItemMacro { ref mac, .. })) => {
if mac.path == parse_quote!(match_byte) {
return syn::fold::fold_stmt(self, syn::Stmt::Expr(expand_match_byte(&mac.tts)))
return syn::fold::fold_stmt(
self,
syn::Stmt::Expr(expand_match_byte(&mac.tts)),
);
}
},
}
_ => {}
}

Expand All @@ -172,11 +182,11 @@ impl Fold for MatchByteParser {

fn fold_expr(&mut self, expr: syn::Expr) -> syn::Expr {
match expr {
syn::Expr::Macro(syn::ExprMacro{ ref mac, .. }) => {
syn::Expr::Macro(syn::ExprMacro { ref mac, .. }) => {
if mac.path == parse_quote!(match_byte) {
return syn::fold::fold_expr(self, expand_match_byte(&mac.tts))
return syn::fold::fold_expr(self, expand_match_byte(&mac.tts));
}
},
}
_ => {}
}

Expand Down
14 changes: 8 additions & 6 deletions macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#[macro_use] extern crate procedural_masquerade;
#[macro_use]
extern crate procedural_masquerade;
extern crate phf_codegen;
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use] extern crate quote;
#[macro_use]
extern crate quote;
extern crate syn;

#[allow(unused_imports)] use std::ascii::AsciiExt;
use proc_macro2::{TokenStream, TokenTree};
use quote::TokenStreamExt;
use std::iter;
use proc_macro2::{TokenStream, TokenTree};

define_proc_macros! {
/// Input: the arms of a `match` expression.
Expand Down Expand Up @@ -88,12 +89,13 @@ define_proc_macros! {
}
}

fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
fn max_len<I: Iterator<Item = usize>>(lengths: I) -> String {
let max_length = lengths.max().expect("expected at least one string");
quote!( const MAX_LENGTH: usize = #max_length; ).to_string()
}

fn string_literal(token: &TokenTree) -> String {
let lit: syn::LitStr = syn::parse2(iter::once(token.clone()).collect()).expect(&format!("expected string literal, got {:?}", token));
let lit: syn::LitStr = syn::parse2(iter::once(token.clone()).collect())
.expect(&format!("expected string literal, got {:?}", token));
lit.value()
}
87 changes: 52 additions & 35 deletions procedural-masquerade/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,35 @@ macro_rules! define_proc_macros {
pub fn _extract_input(derive_input: &str) -> &str {
let mut input = derive_input;

for expected in &["#[allow(unused)]", "enum", "ProceduralMasqueradeDummyType", "{",
"Input", "=", "(0,", "stringify!", "("] {
for expected in &[
"#[allow(unused)]",
"enum",
"ProceduralMasqueradeDummyType",
"{",
"Input",
"=",
"(0,",
"stringify!",
"(",
] {
input = input.trim_start();
assert!(input.starts_with(expected),
"expected prefix {:?} not found in {:?}", expected, derive_input);
assert!(
input.starts_with(expected),
"expected prefix {:?} not found in {:?}",
expected,
derive_input
);
input = &input[expected.len()..];
}

for expected in [")", ").0,", "}"].iter().rev() {
input = input.trim_end();
assert!(input.ends_with(expected),
"expected suffix {:?} not found in {:?}", expected, derive_input);
assert!(
input.ends_with(expected),
"expected suffix {:?} not found in {:?}",
expected,
derive_input
);
let end = input.len() - expected.len();
input = &input[..end];
}
Expand All @@ -227,33 +244,33 @@ macro_rules! define_invoke_proc_macro {
#[doc(hidden)]
#[macro_export]
macro_rules! $macro_name {
($proc_macro_name: ident ! $paren: tt) => {
#[derive($proc_macro_name)]
#[allow(unused)]
enum ProceduralMasqueradeDummyType {
// The magic happens here.
//
// We use an `enum` with an explicit discriminant
// because that is the only case where a type definition
// can contain a (const) expression.
//
// `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored.
//
// By the time the `#[proc_macro_derive]` function
// implementing `#[derive($proc_macro_name)]` is called,
// `$paren` has already been replaced with the input of this inner macro,
// but `stringify!` has not been expanded yet.
//
// This how arbitrary tokens can be inserted
// in the input to the `#[proc_macro_derive]` function.
//
// Later, `stringify!(...)` is expanded into a string literal
// which is then ignored.
// Using `stringify!` enables passing arbitrary tokens
// rather than only what can be parsed as a const expression.
Input = (0, stringify! $paren ).0
}
}
}
}
($proc_macro_name: ident ! $paren: tt) => {
#[derive($proc_macro_name)]
#[allow(unused)]
enum ProceduralMasqueradeDummyType {
// The magic happens here.
//
// We use an `enum` with an explicit discriminant
// because that is the only case where a type definition
// can contain a (const) expression.
//
// `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored.
//
// By the time the `#[proc_macro_derive]` function
// implementing `#[derive($proc_macro_name)]` is called,
// `$paren` has already been replaced with the input of this inner macro,
// but `stringify!` has not been expanded yet.
//
// This how arbitrary tokens can be inserted
// in the input to the `#[proc_macro_derive]` function.
//
// Later, `stringify!(...)` is expanded into a string literal
// which is then ignored.
// Using `stringify!` enables passing arbitrary tokens
// rather than only what can be parsed as a const expression.
Input = (0, stringify! $paren ).0
}
}
}
};
}
Loading