rust/src/libsyntax/ext/bytes.rs
Benjamin Herr 9d7b130041 add new enum ast::StrStyle as field to ast::lit_str
For the benefit of the pretty printer we want to keep track of how
string literals in the ast were originally represented in the source
code.

This commit changes parser functions so they don't extract strings from
the token stream without at least also returning what style of string
literal it was. This is stored in the resulting ast node for string
literals, obviously, for the package id in `extern mod = r"package id"`
view items, for the inline asm in `asm!()` invocations.

For `asm!()`'s other arguments or for `extern "Rust" fn()` items, I just
the style of string, because it seemed disproportionally cumbersome to
thread that information through the string processing that happens with
those string literals, given the limited advantage raw string literals
would provide in these positions.

The other syntax extensions don't seem to store passed string literals
in the ast, so they also discard the style of strings they parse.
2013-10-08 03:43:28 +02:00

76 lines
2.7 KiB
Rust

// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/* The compiler code necessary to support the bytes! extension. */
use ast;
use codemap::Span;
use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use std::char;
pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) -> base::MacResult {
// Gather all argument expressions
let exprs = get_exprs_from_tts(cx, sp, tts);
let mut bytes = ~[];
for expr in exprs.iter() {
match expr.node {
// expression is a literal
ast::ExprLit(lit) => match lit.node {
// string literal, push each byte to vector expression
ast::lit_str(s, _) => {
for byte in s.byte_iter() {
bytes.push(cx.expr_u8(expr.span, byte));
}
}
// u8 literal, push to vector expression
ast::lit_uint(v, ast::ty_u8) => {
if v > 0xFF {
cx.span_err(expr.span, "Too large u8 literal in bytes!")
} else {
bytes.push(cx.expr_u8(expr.span, v as u8));
}
}
// integer literal, push to vector expression
ast::lit_int_unsuffixed(v) => {
if v > 0xFF {
cx.span_err(expr.span, "Too large integer literal in bytes!")
} else if v < 0 {
cx.span_err(expr.span, "Negative integer literal in bytes!")
} else {
bytes.push(cx.expr_u8(expr.span, v as u8));
}
}
// char literal, push to vector expression
ast::lit_char(v) => {
if char::from_u32(v).unwrap().is_ascii() {
bytes.push(cx.expr_u8(expr.span, v as u8));
} else {
cx.span_err(expr.span, "Non-ascii char literal in bytes!")
}
}
_ => cx.span_err(expr.span, "Unsupported literal in bytes!")
},
_ => cx.span_err(expr.span, "Non-literal in bytes!")
}
}
let e = cx.expr_vec_slice(sp, bytes);
MRExpr(e)
}