diff options
| author | Luqman Aden <me@luqman.ca> | 2013-03-12 00:01:09 -0700 |
|---|---|---|
| committer | Luqman Aden <me@luqman.ca> | 2013-03-12 01:03:34 -0700 |
| commit | 5aa734d6a1946e526832bb602e1bb271bf26c0b1 (patch) | |
| tree | f9c2332f54666a31c4bb7ffa5a2cb1e85e2c895a /src/libsyntax/ext | |
| parent | 885d0d3d3369bef72590a4d5671c0de83e968dda (diff) | |
| download | rust-5aa734d6a1946e526832bb602e1bb271bf26c0b1.tar.gz rust-5aa734d6a1946e526832bb602e1bb271bf26c0b1.zip | |
Parse operands properly and add a way to indicate volatile asm.
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/asm.rs | 140 |
1 files changed, 129 insertions, 11 deletions
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index bbf42389907..229d1d2a95e 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -20,29 +20,147 @@ use ast; use codemap::span; use ext::base; use ext::base::*; +use parse; +use parse::token; + +enum State { + Asm, + Outputs, + Inputs, + Clobbers, + Options +} + +fn next_state(s: State) -> Option<State> { + match s { + Asm => Some(Outputs), + Outputs => Some(Inputs), + Inputs => Some(Clobbers), + Clobbers => Some(Options), + Options => None + } +} pub fn expand_asm(cx: ext_ctxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { - let args = get_exprs_from_tts(cx, tts); - if args.len() == 0 { - cx.span_fatal(sp, "ast! takes at least 1 argument."); + + let p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), + vec::from_slice(tts)); + + let mut asm = ~""; + let mut outputs = ~[]; + let mut inputs = ~[]; + let mut cons = ~""; + let mut volatile = false; + + let mut state = Asm; + loop outer: { + + match state { + Asm => { + asm = expr_to_str(cx, p.parse_expr(), + ~"inline assembly must be a string literal."); + } + Outputs => { + while *p.token != token::EOF && + *p.token != token::COLON && + *p.token != token::MOD_SEP { + + if outputs.len() != 0 { + p.eat(&token::COMMA); + } + + let constraint = p.parse_str(); + p.expect(&token::LPAREN); + let out = p.parse_expr(); + p.expect(&token::RPAREN); + + outputs.push((constraint, out)); + } + } + Inputs => { + while *p.token != token::EOF && + *p.token != token::COLON && + *p.token != token::MOD_SEP { + + if inputs.len() != 0 { + p.eat(&token::COMMA); + } + + let constraint = p.parse_str(); + p.expect(&token::LPAREN); + let in = p.parse_expr(); + p.expect(&token::RPAREN); + + inputs.push((constraint, in)); + } + } + Clobbers => { + let mut clobs = ~[]; + while *p.token != token::EOF && + *p.token != token::COLON && + *p.token != token::MOD_SEP { + + if clobs.len() != 0 { + p.eat(&token::COMMA); + } + + let clob = ~"~{" + *p.parse_str() + ~"}"; + clobs.push(clob); + } + + cons = str::connect(clobs, ","); + } + Options => { + let option = *p.parse_str(); + + if option == ~"volatile" { + volatile = true; + } + + if *p.token == token::COMMA { + p.eat(&token::COMMA); + } + } + } + + while *p.token == token::COLON || + *p.token == token::MOD_SEP || + *p.token == token::EOF { + state = if *p.token == token::COLON { + p.bump(); + match next_state(state) { + Some(x) => x, + None => break outer + } + } else if *p.token == token::MOD_SEP { + p.bump(); + let s = match next_state(state) { + Some(x) => x, + None => break outer + }; + match next_state(s) { + Some(x) => x, + None => break outer + } + } else if *p.token == token::EOF { + break outer; + } else { + state + }; + } } - let asm = - expr_to_str(cx, args[0], - ~"inline assembly must be a string literal."); - let cons = if args.len() > 1 { - expr_to_str(cx, args[1], - ~"constraints must be a string literal.") - } else { ~"" }; MRExpr(@ast::expr { id: cx.next_id(), callee_id: cx.next_id(), - node: ast::expr_inline_asm(@asm, @cons), + node: ast::expr_inline_asm(@asm, @cons, volatile), span: sp }) } + + // // Local Variables: // mode: rust |
