Function parsing
diff --git a/src/expr.rs b/src/expr.rs
index 1824922..c3c90ea 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -624,16 +624,22 @@
))
));
- named!(expr_block -> Expr, map!(block, |b| Expr::Block(Box::new(b))));
-
- named!(block -> Block, do_parse!(
+ named!(expr_block -> Expr, do_parse!(
rules: block_check_mode >>
+ b: block >>
+ (Expr::Block(Box::new(Block {
+ stmts: b.stmts,
+ rules: rules,
+ })))
+ ));
+
+ named!(pub block -> Block, do_parse!(
punct!("{") >>
stmts: within_block >>
punct!("}") >>
(Block {
stmts: stmts,
- rules: rules,
+ rules: BlockCheckMode::Default,
})
));
@@ -669,7 +675,7 @@
(Stmt::Semi(Box::new(e)))
));
- named!(pat -> Pat, alt!(
+ named!(pub pat -> Pat, alt!(
pat_wild
|
pat_ident
@@ -757,7 +763,10 @@
Expr::AddrOf(_mutability, ref _expr) => unimplemented!(),
Expr::Break(ref _label) => unimplemented!(),
Expr::Continue(ref _label) => unimplemented!(),
- Expr::Ret(ref _expr) => unimplemented!(),
+ Expr::Ret(ref opt_expr) => {
+ tokens.append("return");
+ opt_expr.to_tokens(tokens);
+ }
Expr::Mac(ref _mac) => unimplemented!(),
Expr::Struct(ref _path, ref _fields, ref _base) => unimplemented!(),
Expr::Repeat(ref _expr, ref _times) => unimplemented!(),
@@ -829,4 +838,39 @@
}
}
}
+
+ impl ToTokens for Block {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ self.rules.to_tokens(tokens);
+ tokens.append("{");
+ for stmt in &self.stmts {
+ stmt.to_tokens(tokens);
+ }
+ tokens.append("}");
+ }
+ }
+
+ impl ToTokens for BlockCheckMode {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ BlockCheckMode::Default => { /* nothing */ },
+ BlockCheckMode::Unsafe => tokens.append("unsafe"),
+ }
+ }
+ }
+
+ impl ToTokens for Stmt {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ Stmt::Local(ref _local) => unimplemented!(),
+ Stmt::Item(ref item) => item.to_tokens(tokens),
+ Stmt::Expr(ref expr) => expr.to_tokens(tokens),
+ Stmt::Semi(ref expr) => {
+ expr.to_tokens(tokens);
+ tokens.append(";");
+ }
+ Stmt::Mac(ref _mac) => unimplemented!(),
+ }
+ }
+ }
}
diff --git a/src/item.rs b/src/item.rs
index 4d646fe..8592485 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -32,7 +32,7 @@
/// A function declaration (`fn` or `pub fn`).
///
/// E.g. `fn foo(bar: usize) -> usize { .. }`
- Fn(Box<FnDecl>, Unsafety, Constness, Abi, Generics, Box<Block>),
+ Fn(Box<FnDecl>, Unsafety, Constness, Option<Abi>, Generics, Box<Block>),
/// A module declaration (`mod` or `pub mod`).
///
/// E.g. `mod foo;` or `mod foo { .. }`
@@ -209,14 +209,16 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
+ use {FnDecl, FunctionRetTy, Generics};
use attr::parsing::outer_attr;
use data::parsing::visibility;
- use expr::parsing::expr;
- use generics::parsing::generics;
+ use expr::parsing::{block, expr};
+ use generics::parsing::{generics, where_clause};
use ident::parsing::ident;
+ use lit::parsing::quoted_string;
use macro_input::{Body, MacroInput};
use macro_input::parsing::macro_input;
- use ty::parsing::{mutability, ty};
+ use ty::parsing::{fn_arg, mutability, ty};
named!(pub item -> Item, alt!(
item_extern_crate
@@ -225,7 +227,8 @@
item_static
|
item_const
- // TODO: Fn
+ |
+ item_fn
// TODO: Mod
// TODO: ForeignMod
|
@@ -301,6 +304,42 @@
})
));
+ named!(item_fn -> Item, do_parse!(
+ attrs: many0!(outer_attr) >>
+ vis: visibility >>
+ constness: constness >>
+ unsafety: unsafety >>
+ abi: option!(preceded!(keyword!("extern"), quoted_string)) >>
+ keyword!("fn") >>
+ name: ident >>
+ generics: generics >>
+ punct!("(") >>
+ inputs: separated_list!(punct!(","), fn_arg) >>
+ punct!(")") >>
+ ret: option!(preceded!(punct!("->"), ty)) >>
+ where_clause: where_clause >>
+ body: block >>
+ (Item {
+ ident: name,
+ vis: vis,
+ attrs: attrs,
+ node: ItemKind::Fn(
+ Box::new(FnDecl {
+ inputs: inputs,
+ output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+ }),
+ unsafety,
+ constness,
+ abi.map(Abi),
+ Generics {
+ where_clause: where_clause,
+ .. generics
+ },
+ Box::new(body),
+ ),
+ })
+ ));
+
named!(item_ty -> Item, do_parse!(
attrs: many0!(outer_attr) >>
vis: visibility >>
@@ -334,6 +373,24 @@
}
}
));
+
+ named!(constness -> Constness, alt!(
+ do_parse!(
+ keyword!("const") >>
+ (Constness::Const)
+ )
+ |
+ epsilon!() => { |_| Constness::NotConst }
+ ));
+
+ named!(unsafety -> Unsafety, alt!(
+ do_parse!(
+ keyword!("unsafe") >>
+ (Unsafety::Unsafe)
+ )
+ |
+ epsilon!() => { |_| Unsafety::Normal }
+ ));
}
#[cfg(feature = "printing")]
@@ -381,7 +438,18 @@
expr.to_tokens(tokens);
tokens.append(";");
}
- ItemKind::Fn(ref _decl, _unsafety, _constness, ref _abi, ref _generics, ref _block) => unimplemented!(),
+ ItemKind::Fn(ref decl, unsafety, constness, ref abi, ref generics, ref block) => {
+ self.vis.to_tokens(tokens);
+ constness.to_tokens(tokens);
+ unsafety.to_tokens(tokens);
+ abi.to_tokens(tokens);
+ tokens.append("fn");
+ self.ident.to_tokens(tokens);
+ generics.to_tokens(tokens);
+ decl.to_tokens(tokens);
+ generics.where_clause.to_tokens(tokens);
+ block.to_tokens(tokens);
+ }
ItemKind::Mod(ref _items) => unimplemented!(),
ItemKind::ForeignMod(ref _foreign_mod) => unimplemented!(),
ItemKind::Ty(ref ty, ref generics) => {
@@ -427,4 +495,29 @@
}
}
}
+
+ impl ToTokens for Unsafety {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ Unsafety::Unsafe => tokens.append("unsafe"),
+ Unsafety::Normal => { /* nothing */ },
+ }
+ }
+ }
+
+ impl ToTokens for Constness {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ Constness::Const => tokens.append("const"),
+ Constness::NotConst => { /* nothing */ },
+ }
+ }
+ }
+
+ impl ToTokens for Abi {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ tokens.append("extern");
+ self.0.to_tokens(tokens);
+ }
+ }
}
diff --git a/src/lit.rs b/src/lit.rs
index b3d2954..2e67d82 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -74,11 +74,7 @@
));
named!(string -> Lit, alt!(
- delimited!(
- punct!("\""),
- cooked_string,
- tag!("\"")
- ) => { |s| Lit::Str(s, StrStyle::Cooked) }
+ quoted_string => { |s| Lit::Str(s, StrStyle::Cooked) }
|
preceded!(
punct!("r"),
@@ -86,6 +82,12 @@
) => { |(s, n)| Lit::Str(s, StrStyle::Raw(n)) }
));
+ named!(pub quoted_string -> String, delimited!(
+ punct!("\""),
+ cooked_string,
+ tag!("\"")
+ ));
+
named!(byte_string -> Lit, alt!(
delimited!(
punct!("b\""),
diff --git a/src/ty.rs b/src/ty.rs
index 3ee68e5..aa9c9df 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -154,7 +154,7 @@
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct BareFnTy {
pub lifetimes: Vec<LifetimeDef>,
- pub decl: FnDecl
+ pub decl: FnDecl,
}
/// Header (not the body) of a function declaration.
@@ -406,7 +406,7 @@
})
));
- named!(fn_arg -> FnArg, do_parse!(
+ named!(pub fn_arg -> FnArg, do_parse!(
pat: option!(terminated!(ident, punct!(":"))) >>
ty: ty >>
(FnArg {
@@ -620,16 +620,32 @@
tokens.append("fn");
if !self.lifetimes.is_empty() {
tokens.append("<");
- for (i, lifetime) in self.lifetimes.iter().enumerate() {
- if i > 0 {
- tokens.append(",");
- }
- lifetime.to_tokens(tokens);
- }
+ tokens.append_separated(&self.lifetimes, ",");
tokens.append(">");
}
+ self.decl.to_tokens(tokens);
+ }
+ }
+
+ impl ToTokens for FnDecl {
+ fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append("(");
+ tokens.append_separated(&self.inputs, ",");
tokens.append(")");
+ if let FunctionRetTy::Ty(ref ty) = self.output {
+ tokens.append("->");
+ ty.to_tokens(tokens);
+ }
+ }
+ }
+
+ impl ToTokens for FnArg {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ if let Some(ref pat) = self.pat {
+ pat.to_tokens(tokens);
+ tokens.append(":");
+ }
+ self.ty.to_tokens(tokens);
}
}
}