Skip to content
Snippets Groups Projects
Commit 3db36b8c authored by pln's avatar pln
Browse files

syntax

parent 59664489
No related branches found
No related tags found
No related merge requests found
......@@ -5,7 +5,7 @@ use std::collections::HashMap;
use syn::{Ident, Path};
use error::*;
use {util, Resources, Statics};
use {util, Resources, Statics, Crcs};
/// `$($Ident: { .. },)*`
pub type Tasks = HashMap<Ident, Task>;
......@@ -65,8 +65,9 @@ pub fn app(app: ::App) -> Result<App> {
device: app.device,
idle: ::check::idle(app.idle).chain_err(|| "checking `idle`")?,
init: ::check::init(app.init).chain_err(|| "checking `init`")?,
resources: ::check::statics("resources", app.resources)
.chain_err(|| "checking `resources`")?,
resources: ::check::statics("resources", app.resources).chain_err(
|| "checking `resources`",
)?,
tasks: ::check::tasks(app.tasks).chain_err(|| "checking `tasks`")?,
})
}
......@@ -80,8 +81,9 @@ fn idle(idle: Option<::Idle>) -> Result<Idle> {
Idle {
_extensible: (),
path: ::check::path("idle", idle.path)
.chain_err(|| "checking `path`")?,
path: ::check::path("idle", idle.path).chain_err(
|| "checking `path`",
)?,
resources: ::check::resources("resources", idle.resources)?,
}
} else {
......@@ -98,8 +100,9 @@ fn init(init: Option<::Init>) -> Result<Init> {
if let Some(path) = init.path {
Init {
_extensible: (),
path: ::check::path("init", Some(path))
.chain_err(|| "checking `path`")?,
path: ::check::path("init", Some(path)).chain_err(
|| "checking `path`",
)?,
}
} else {
bail!("empty `init` field. It should be removed.");
......@@ -115,8 +118,7 @@ fn init(init: Option<::Init>) -> Result<Init> {
fn path(default: &str, path: Option<Path>) -> Result<Path> {
Ok(if let Some(path) = path {
ensure!(
path.segments.len() != 1 ||
path.segments[0].ident.as_ref() != default,
path.segments.len() != 1 || path.segments[0].ident.as_ref() != default,
"this is the default value. It should be omitted."
);
......@@ -186,3 +188,15 @@ fn tasks(tasks: Option<::Tasks>) -> Result<Tasks> {
Tasks::new()
})
}
/// `crc! { .. }`
#[derive(Debug)]
pub struct Crc {
/// `crcs: Crcs`
pub crcs: Option<Crcs>,
}
/// Checks the syntax of the parsed `app!` macro
pub fn crc(crc: ::Crc) -> Result<Crc> {
Ok(Crc { crcs: crc.crcs })
}
......@@ -2,7 +2,7 @@
//! framework
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![deny(warnings)]
// #![deny(warnings)]
#[macro_use]
extern crate error_chain;
......@@ -99,3 +99,37 @@ impl App {
parse::app(input)
}
}
/// Crc related
/// `$($Ident: $Path,)*`
pub type Crcs = HashMap<Ident, Path>;
pub enum IpTo {
Crc(Path),
Method(Ident),
}
pub struct Ip {
ty: Ty,
to: IpBind,
}
/// `$($Ident: $Ty,)*`
pub type Ips = HashMap<Ident, Ty>;
/// `crc! { .. }`
#[derive(Debug)]
pub struct Crc {
/// Inner Crcs (can be None)
pub crcs: Option<Crcs>,
/// Input ports (should not be None)
pub ips: Option<Ips>,
}
impl Crc {
/// Parses the contents of the `sys! { .. }` macro
pub fn parse(input: &str) -> Result<Self> {
parse::crc(input)
}
}
......@@ -2,11 +2,11 @@ use std::collections::{HashMap, HashSet};
use std::iter::Peekable;
use std::slice::Iter;
use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, TokenTree};
use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, TokenTree, Ty};
use error::*;
use {App, Idle, Init, Resources, Static, Statics, Task, Tasks};
use {Crc, Crcs, Ips, App, Idle, Init, Resources, Static, Statics, Task, Tasks};
/// Parses the contents of `app! { $App }`
pub fn app(input: &str) -> Result<App> {
......@@ -39,9 +39,9 @@ pub fn app(input: &str) -> Result<App> {
"resources" => {
ensure!(resources.is_none(), "duplicated `resources` field");
resources = Some(
::parse::statics(tts).chain_err(|| "parsing `resources`")?,
);
resources = Some(::parse::statics(tts).chain_err(
|| "parsing `resources`",
)?);
}
"tasks" => {
ensure!(tasks.is_none(), "duplicated `tasks` field");
......@@ -122,7 +122,8 @@ where
let tt = tts.next();
match tt {
None | Some(&TokenTree::Token(Token::Comma)) => {}
None |
Some(&TokenTree::Token(Token::Comma)) => {}
_ => bail!("expected Comma, found {:?}", tt),
}
}
......@@ -149,8 +150,9 @@ fn idle(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Idle> {
"duplicated `resources` field"
);
resources = Some(::parse::resources(tts)
.chain_err(|| "parsing `resources`")?);
resources = Some(::parse::resources(tts).chain_err(
|| "parsing `resources`",
)?);
}
_ => bail!("unknown field: `{}`", key),
}
......@@ -305,8 +307,9 @@ fn statics(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Statics> {
statics.insert(
ident.clone(),
::parse::static_(&mut tts)
.chain_err(|| format!("parsing `{}`", ident))?,
::parse::static_(&mut tts).chain_err(
|| format!("parsing `{}`", ident),
)?,
);
}
......@@ -331,6 +334,7 @@ fn path(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Path> {
tts.next();
}
// bail!("in path fragments, {:? }===== {:?}", fragments, tts);
Ok(syn::parse_path(&format!("{}", quote!(#(#fragments)*)))?)
}
......@@ -348,8 +352,9 @@ fn task(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Task> {
"enabled" => {
ensure!(enabled.is_none(), "duplicated `enabled` field");
enabled = Some(::parse::bool(tts.next())
.chain_err(|| "parsing `enabled`")?);
enabled = Some(::parse::bool(tts.next()).chain_err(
|| "parsing `enabled`",
)?);
}
"path" => {
ensure!(path.is_none(), "duplicated `path` field");
......@@ -361,8 +366,9 @@ fn task(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Task> {
"priority" => {
ensure!(priority.is_none(), "duplicated `priority` field");
priority = Some(::parse::u8(tts.next())
.chain_err(|| "parsing `priority`")?);
priority = Some(::parse::u8(tts.next()).chain_err(
|| "parsing `priority`",
)?);
}
"resources" => {
ensure!(
......@@ -370,8 +376,9 @@ fn task(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Task> {
"duplicated `resources` field"
);
resources = Some(::parse::resources(tts)
.chain_err(|| "parsing `resources`")?);
resources = Some(::parse::resources(tts).chain_err(
|| "parsing `resources`",
)?);
}
_ => bail!("unknown field: `{}`", key),
}
......@@ -403,8 +410,9 @@ fn tasks(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Tasks> {
tasks.insert(
key.clone(),
::parse::task(tts)
.chain_err(|| format!("parsing task `{}`", key))?,
::parse::task(tts).chain_err(
|| format!("parsing task `{}`", key),
)?,
);
Ok(())
......@@ -429,3 +437,121 @@ fn u8(tt: Option<&TokenTree>) -> Result<u8> {
bail!("expected integer, found {:?}", tt);
}
}
/// Parses the contents of `crc! { $Crc }`
pub fn crc(input: &str) -> Result<Crc> {
let tts = syn::parse_token_trees(input)?;
let mut crcs = None;
let mut ips = None;
fields(&tts, |key, tts| {
match key.as_ref() {
"crcs" => {
ensure!(crcs.is_none(), "duplicated `crcs` field");
crcs = Some(::parse::crcs(tts).chain_err(|| "parsing `crcs`")?);
}
"ips" => {
ensure!(ips.is_none(), "duplicated `ips` field");
ips = Some(::parse::ip(tts).chain_err(|| "parsing `ips`")?);
}
_ => bail!("unknown field: `{}`", key),
}
Ok(())
})?;
Ok(Crc { crcs, ips })
}
/// Parses `$($Ident: $Path,)*`
fn crcs(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Crcs> {
::parse::delimited(tts, DelimToken::Brace, |tts| {
let mut crcs = HashMap::new();
let mut tts = tts.iter().peekable();
while let Some(tt) = tts.next() {
let ident = if let &TokenTree::Token(Token::Ident(ref id)) = tt {
id
} else {
bail!("expected Ident, found {:?}", tt);
};
ensure!(
!crcs.contains_key(ident),
"crc {} listed more than once",
ident
);
let tt = tts.next();
if let Some(&TokenTree::Token(Token::Colon)) = tt {
} else {
bail!("expected Colon, found {:?}", tt);
}
let path = ::parse::path(&mut tts).chain_err(|| "parsing `path`")?;
tts.next();
crcs.insert(ident.clone(), path);
}
Ok(crcs)
})
}
/// Parses `$($Ident: $Path,)*`
fn ip(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> {
::parse::delimited(tts, DelimToken::Brace, |tts| {
let mut ips = HashMap::new();
let mut tts = tts.iter();
while let Some(tt) = tts.next() {
let ident = if let &TokenTree::Token(Token::Ident(ref id)) = tt {
id
} else {
bail!("expected Ident, found {:?}", tt);
};
ensure!(
!ips.contains_key(ident),
"ip {} listed more than once",
ident
);
let tt = tts.next();
if let Some(&TokenTree::Token(Token::Colon)) = tt {
} else {
bail!("expected Colon, found {:?}", tt);
}
let ty = ::parse::ty(&mut tts).chain_err(|| {
format!("parsing `type` for {:?}", ident)
})?;
ips.insert(ident.clone(), ty);
}
Ok(ips)
})
}
/// Parses `$Ty `
fn ty(tts: &mut Iter<TokenTree>) -> Result<Ty> {
let mut fragments = vec![];
loop {
if let Some(tt) = tts.next() {
if tt == &TokenTree::Token(Token::Comma) {
break;
} else {
fragments.push(tt);
}
} else {
bail!("expected comma, found end of macro");
}
}
Ok(syn::parse_type(&format!("{}", quote!(#(#fragments)*)))?)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment