summaryrefslogtreecommitdiff
path: root/lib/libproc_macro/src/lib.rs
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-11-15 21:19:22 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-11-15 21:19:22 +0800
commit97839be171f00c9f6ea3d9921ca89db918027800 (patch)
treec60922d8147128d34b8514e1fd30b73b91a750cf /lib/libproc_macro/src/lib.rs
parentd585aa08551aa78b692bab8326509baef02a7b3d (diff)
downloadmrust-97839be171f00c9f6ea3d9921ca89db918027800.tar.gz
proc_macro - Working invocations (some work needed on AST->TT)
Diffstat (limited to 'lib/libproc_macro/src/lib.rs')
-rw-r--r--lib/libproc_macro/src/lib.rs198
1 files changed, 168 insertions, 30 deletions
diff --git a/lib/libproc_macro/src/lib.rs b/lib/libproc_macro/src/lib.rs
index 5db439b2..6d094893 100644
--- a/lib/libproc_macro/src/lib.rs
+++ b/lib/libproc_macro/src/lib.rs
@@ -9,6 +9,7 @@ pub struct TokenStream {
inner: Vec<Token>,
}
+#[derive(Debug)]
enum Token {
Symbol(String),
Ident(String),
@@ -22,7 +23,7 @@ enum Token {
Fragment(FragmentType, u64), // Type and a key
}
#[repr(u8)]
-#[derive(Copy,Clone)] // TODO: Is this just a mrustc thing?
+#[derive(Copy,Clone,Debug)] // TODO: Is this just a mrustc thing?
enum FragmentType {
Ident = 0,
Tt = 1,
@@ -73,21 +74,33 @@ impl<T: Iterator<Item=char>> CharStream<T> {
}
pub struct LexError {
- _inner: (),
+ inner: &'static str,
}
impl ::std::fmt::Debug for LexError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
- f.write_str("LexError")
+ write!(f, "LexError({})", self.inner)
}
}
impl FromStr for TokenStream {
type Err = LexError;
fn from_str(src: &str) -> Result<TokenStream, LexError> {
+ //eprintln!("TokenStream::from_str({:?})\r", src);
let rv = Vec::new();
let mut it = CharStream::new(src.chars());
- fn err() -> Result<TokenStream,LexError> {
- Err(LexError { _inner: () })
+ fn err(s: &'static str) -> Result<TokenStream,LexError> {
+ Err(LexError { inner: s })
+ }
+
+ fn get_ident<T: Iterator<Item=char>>(it: &mut CharStream<T>, mut s: String) -> String
+ {
+ let mut c = it.cur();
+ while c.is_xid_continue() || c.is_digit(10)
+ {
+ s.push(c);
+ c = some_else!(it.consume() => break);
+ }
+ s
}
'outer: while ! it.is_complete()
@@ -95,6 +108,7 @@ impl FromStr for TokenStream {
let c = it.cur();
if c.is_whitespace() {
+ it.consume();
continue ;
}
@@ -132,8 +146,17 @@ impl FromStr for TokenStream {
];
if c == '\''
{
- // Lifetime or char lit
- panic!("TODO: Lifetime / char literal");
+ it.consume();
+ c = it.cur();
+ if c.is_xid_start() && it.next().map(|x| x != '\'').unwrap_or(true) {
+ // Lifetime
+ let ident = get_ident(&mut it, String::new());
+ rv.push(Token::Lifetime(ident))
+ }
+ else {
+ // Char lit
+ panic!("TODO: char literal");
+ }
}
else if c == '/' && it.next() == Some('/')
{
@@ -160,27 +183,39 @@ impl FromStr for TokenStream {
if c == 'r'
{
+ // TODO: If this isn't a string, start parsing an ident instead.
let ident_str = if is_byte { "br" } else { "r" };
c = some_else!(it.consume() => { rv.push(Token::Ident(ident_str.into())); break });
let mut hashes = 0;
while c == '#' {
hashes += 1;
- c = some_else!(it.consume() => return err());
+ c = some_else!(it.consume() => return err("rawstr eof"));
}
if c != '"' {
- return err();
+ if hashes == 0 {
+ let s = get_ident(&mut it, ident_str.to_string());
+ rv.push(Token::Ident(s));
+ }
+ else {
+ rv.push(Token::Ident(ident_str.into()));
+ }
+ while hashes > 0 {
+ rv.push(Token::Symbol("#".into()));
+ hashes -= 1;
+ }
+ continue 'outer;
}
let req_hashes = hashes;
let mut rawstr = String::new();
loop
{
- c = some_else!(it.consume() => return err());
+ c = some_else!(it.consume() => return err("Rawstr eof"));
if c == '"' {
let mut hashes = 0;
while hashes < req_hashes {
- c = some_else!(it.consume() => return err());
+ c = some_else!(it.consume() => return err("rawstr eof"));
if c != '#' { break ; }
hashes += 1;
}
@@ -214,7 +249,26 @@ impl FromStr for TokenStream {
else if c == '\"'
{
// String literal
- panic!("TODO: Escaped string literal");
+ let mut s = String::new();
+ loop
+ {
+ c = some_else!(it.consume() => return err("str eof"));
+ if c == '"' {
+ it.consume();
+ break ;
+ }
+ else if c == '\\' {
+ match some_else!(it.consume() => return err("str eof"))
+ {
+ c @ _ => panic!("Unknown escape in string {}", c),
+ }
+ }
+ else {
+ s.push(c);
+ }
+ }
+ rv.push(Token::String(s));
+ continue 'outer;
}
else
{
@@ -224,23 +278,77 @@ impl FromStr for TokenStream {
}
// Identifier.
- if c.is_xid_start()
+ if c.is_xid_start() || c == '_'
{
- let mut ident = String::new();
- while c.is_xid_continue()
+ let ident = get_ident(&mut it, String::new());
+ if ident == "_" {
+ rv.push(Token::Symbol(ident));
+ }
+ else {
+ rv.push(Token::Ident(ident));
+ }
+ }
+ else if c.is_digit(10)
+ {
+ let base =
+ if c == '0' {
+ match it.consume()
+ {
+ Some('x') => { it.consume(); 16 },
+ Some('o') => { it.consume(); 8 },
+ Some('b') => { it.consume(); 2 },
+ _ => 10,
+ }
+ }
+ else {
+ 10
+ };
+ let mut v = 0;
+ let mut c = it.cur();
+ 'int: loop
{
- ident.push(c);
- c = some_else!(it.consume() => break);
+ while c == '_' {
+ c = some_else!( it.consume() => { break 'int; } );
+ }
+ if c == 'u' || c == 'i' {
+ let s = get_ident(&mut it, String::new());
+ match &*s
+ {
+ "u8" => rv.push(Token::UnsignedInt(v, 8)), "i8" => rv.push(Token::SignedInt(v as i128, 8)),
+ "u16" => rv.push(Token::UnsignedInt(v, 16)), "i16" => rv.push(Token::SignedInt(v as i128, 16)),
+ "u32" => rv.push(Token::UnsignedInt(v, 32)), "i32" => rv.push(Token::SignedInt(v as i128, 32)),
+ "u64" => rv.push(Token::UnsignedInt(v, 64)), "i64" => rv.push(Token::SignedInt(v as i128, 64)),
+ "u128" => rv.push(Token::UnsignedInt(v, 128)), "i128" => rv.push(Token::SignedInt(v as i128, 128)),
+ "usize" => rv.push(Token::UnsignedInt(v, 1)), "isize" => rv.push(Token::SignedInt(v as i128, 1)),
+ _ => return err("Unexpected integer suffix"),
+ }
+ continue 'outer;
+ }
+ else if let Some(d) = c.to_digit(base) {
+ v *= base as u128;
+ v += d as u128;
+ c = some_else!( it.consume() => { break 'int; } );
+ }
+ else if c == '.' {
+ panic!("TODO: Floating point");
+ }
+ else {
+ break;
+ }
}
- rv.push(Token::Ident(ident));
+ rv.push(Token::UnsignedInt(v, 0));
+ continue 'outer;
}
// Punctuation?
else if c as u32 <= 0xFF
{
- let mut start = match syms.binary_search_by(|v| Ord::cmp(&v[0], &(c as u8)))
+ let mut start = match syms.iter().position(|v| v[0] == (c as u8))
{
- Ok(start) => start,
- Err(_) => return err(),
+ Some(start) => start,
+ None => {
+ eprint!("Unknown operator character '{}'\r\n", c);
+ return err("Unknown operator")
+ },
};
let mut end = start+1;
while end < syms.len() && syms[end][0] == c as u8 {
@@ -251,12 +359,12 @@ impl FromStr for TokenStream {
loop
{
let syms = &syms[start..end];
- assert!(ofs == syms[0].len());
+ assert_eq!(ofs, syms[0].len(), "{:?}", syms[0]);
c = some_else!(it.consume() => break);
- let step = match syms[1..].binary_search_by(|v| Ord::cmp(&v[ofs], &(c as u8)))
+ let step = match syms[1..].iter().position(|v| v[ofs] == (c as u8))
{
- Ok(s) => s+1,
- Err(_) => break,
+ Some(s) => s+1,
+ None => break,
};
start += step;
end = start+1;
@@ -265,12 +373,12 @@ impl FromStr for TokenStream {
}
ofs += 1;
}
- assert!(syms[start].len() == ofs);
+ assert_eq!(syms[start].len(), ofs);
rv.push(Token::Symbol(::std::str::from_utf8(syms[start]).unwrap().into()));
}
else
{
- return err();
+ return err("Unexpectec character");
}
}
}
@@ -369,7 +477,7 @@ pub fn recv_token_stream() -> TokenStream
match self.inner.read(&mut b)
{
Ok(1) => Some(b[0]),
- Ok(0) => None,
+ Ok(0) => panic!("Unexpected EOF reading from stdin"),
Ok(_) => panic!("Bad byte count"),
Err(e) => panic!("Error reading from stdin - {}", e),
}
@@ -407,7 +515,7 @@ pub fn recv_token_stream() -> TokenStream
match self.inner.read_exact(&mut buf)
{
Ok(_) => {},
- Err(e) => panic!("Error reading from stdin - {}", e),
+ Err(e) => panic!("Error reading from stdin get_byte_vec({}) - {}", size, e),
}
buf
@@ -436,7 +544,11 @@ pub fn recv_token_stream() -> TokenStream
let hdr_b = some_else!( s.getb() => break );
toks.push(match hdr_b
{
- 0 => Token::Symbol( s.get_string() ),
+ 0 => {
+ let sym = s.get_string();
+ if sym == "" { break ; }
+ Token::Symbol( sym )
+ },
1 => Token::Ident( s.get_string() ),
2 => Token::Lifetime( s.get_string() ),
3 => Token::String( s.get_string() ),
@@ -455,6 +567,7 @@ pub fn recv_token_stream() -> TokenStream
Token::Float(s.get_f64(), ty)
}
});
+ eprintln!("> {:?}\r", toks.last().unwrap());
}
TokenStream {
inner: toks,
@@ -500,6 +613,7 @@ pub fn send_token_stream(ts: TokenStream)
for t in &ts.inner
{
+ //eprintln!("{:?}\r", t);
match t
{
&Token::Symbol(ref v) => { s.putb(0); s.put_bytes(v.as_bytes()); },
@@ -514,6 +628,11 @@ pub fn send_token_stream(ts: TokenStream)
&Token::Fragment(ty, key) => { s.putb(9); s.putb(ty as u8); s.put_u128v(key as u128); },
}
}
+
+ // Empty symbol indicates EOF
+ s.putb(0); s.putb(0);
+ drop(s);
+ ::std::io::Write::flush(&mut ::std::io::stdout());
}
pub struct MacroDesc
@@ -524,5 +643,24 @@ pub struct MacroDesc
pub fn main(macros: &[MacroDesc])
{
+ let mac_name = ::std::env::args().nth(1).expect("Was not passed a macro name");
+ eprintln!("Searching for macro {}\r", mac_name);
+ for m in macros
+ {
+ if m.name == mac_name {
+ use std::io::Write;
+ ::std::io::stdout().write(&[0]);
+ ::std::io::stdout().flush();
+ eprintln!("Waiting for input\r");
+ let input = recv_token_stream();
+ eprintln!("INPUT = `{}`\r", input);
+ let output = (m.handler)( input );
+ eprintln!("OUTPUT = `{}`\r", output);
+ send_token_stream(output);
+ eprintln!("Done");
+ return ;
+ }
+ }
+ panic!("Unknown macro name '{}'", mac_name);
}