Skip to content
This repository has been archived by the owner on Jul 6, 2019. It is now read-only.

Commit

Permalink
Merge pull request #129 from bgamari/ioreg-k20
Browse files Browse the repository at this point in the history
Refactor K20 to use ioreg!

Reviewed-by:
  • Loading branch information
hacknbot committed Aug 18, 2014
2 parents 2af9fe6 + 7c10b28 commit c9c1c07
Show file tree
Hide file tree
Showing 6 changed files with 538 additions and 198 deletions.
4 changes: 2 additions & 2 deletions ioreg/builder/setter.rs
Expand Up @@ -64,8 +64,8 @@ fn build_type<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
let reg_ty = cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));

let reg_doc = match reg.docstring {
Some(d) => d.node,
None => cx.ident_of("no documentation"),
Some(d) => token::get_ident(d.node).get().into_string(),
None => "no documentation".into_string(),
};
let docstring = format!("Update value of `{}` register: {}",
reg.name.node,
Expand Down
34 changes: 20 additions & 14 deletions ioreg/ioreg.rs
Expand Up @@ -110,25 +110,31 @@ and bitfields are free of overlap).
It is highly recommended that register definitions include
docstrings. Registers, fields, and `enum` values can all be annotated
with docstrings with the typical Rust `/// comment` syntax
although, in contrast to Rust, a comment will be assumed to describe
the item preceding it. This makes it convenient to place a definition
and its documentation on the same line.
with docstrings with the typical Rust doc comment syntax. Both outer
(`/// comment`) and inner (`//! comment`) comments are accepted. Inner
comments apply to the item to which the current block belongs whereas
outer comments apply to the item that follows. In addition,
trailing comments are supported with the `//=` syntax. These apply
to the preceding item, allowing definitions and associated comments
to inhabit the same line. Multiple successive comments of the same
type will be concatenated together into a single doc comment.
For instance, we might document the above example as follows,
```
ioregs!(UART = {
0x0 => reg32 cr { ///! Control register
0 => rxe, /// Receive enable
1 => txe, /// Transmit enable
2 => rxie, /// Receive interrupt enable
3 => txie, /// Transmit interrupt enable
4..12 => br, /// Baud rate
14..16 => parity { /// Parity selection
0x0 => NoParity, /// No parity
0x2 => EvenParity, /// Even parity
0x3 => OddParity, /// Odd parity
/// Control register
/// Here is some discussion of the function of the `cr` register.
0x0 => reg32 cr {
0 => rxe, //= Receive enable
1 => txe, //= Transmit enable
2 => rxie, //= Receive interrupt enable
3 => txie, //= Transmit interrupt enable
4..12 => br, //= Baud rate
14..16 => parity { //! Parity selection
0x0 => NoParity, //= No parity
0x2 => EvenParity, //= Even parity
0x3 => OddParity, //= Odd parity
}
}
Expand Down
78 changes: 53 additions & 25 deletions ioreg/parser.rs
Expand Up @@ -23,6 +23,16 @@ use syntax::parse::{token, ParseSess, lexer};

use node;

/// The scope of a doc comment
enum Scope {
/// Applies to the next item in the block
Inner,
/// Applies to the previous item in the block
Trailing,
/// Applies to the owner of the current block
Outer,
}

pub struct Parser<'a,'b> {
cx: &'a ExtCtxt<'b>,
sess: &'a ParseSess,
Expand Down Expand Up @@ -73,7 +83,7 @@ impl<'a, 'b> Parser<'a, 'b> {
return None;
}

let docstring = self.parse_docstring();
let docstring = self.parse_docstring(Inner);

let regs = match self.parse_regs() {
Some(regs) => regs,
Expand Down Expand Up @@ -148,6 +158,9 @@ impl<'a, 'b> Parser<'a, 'b> {

/// Parse the introduction of a register
fn parse_reg(&mut self) -> Option<node::Reg> {
// We might have an outer docstring
let docstring = self.parse_docstring(Outer);

// we are still sitting at the offset
let offset = match self.expect_uint() {
Some(offset) => offset,
Expand Down Expand Up @@ -181,13 +194,17 @@ impl<'a, 'b> Parser<'a, 'b> {
Some(count) => count,
};

let docstring = self.parse_docstring();
// Potentially a trailing docstring before the block
let docstring = docstring.or_else(|| self.parse_docstring(Trailing));

// Catch beginning of block and potentially an inner docstring
if !self.expect(&token::LBRACE) {
return None;
}
let docstring = docstring.or_else(|| self.parse_docstring(Inner));

let ty = match ty {
node::RegPrim(width, _) => {
if !self.expect(&token::LBRACE) {
return None;
}
match self.parse_fields() {
None => return None,
Some(mut fields) => {
Expand Down Expand Up @@ -221,9 +238,6 @@ impl<'a, 'b> Parser<'a, 'b> {
}
},
node::RegUnion(_) => {
if !self.expect(&token::LBRACE) {
return None;
}
match self.parse_regs() {
Some(regs) => node::RegUnion(box(GC) regs),
None => return None,
Expand Down Expand Up @@ -355,9 +369,8 @@ impl<'a, 'b> Parser<'a, 'b> {
require_comma = false;
}

let docstring = self.parse_docstring();

let ty = match self.token {
let (docstring, ty) = match self.token {
// A list of enumeration variants
token::LBRACE if !require_comma => {
self.error(String::from_str("Unexpected enumeration list after comma"));
Expand All @@ -366,17 +379,26 @@ impl<'a, 'b> Parser<'a, 'b> {
token::LBRACE => {
// we don't require a delimiting comma after a block
require_comma = false;

if !self.expect(&token::LBRACE) {
return None;
}
let docstring = self.parse_docstring(Inner);
match self.parse_enum_variants() {
Some(variants) => node::EnumField {opt_name: None, variants: variants},
Some(variants) => {
let ty = node::EnumField {opt_name: None, variants: variants};
(docstring, ty)
},
None => return None,
}
},
_ => {
if width == 1 {
node::BoolField
} else {
node::UIntField
}
let docstring = self.parse_docstring(Trailing);
let ty = match width {
1 => node::BoolField,
_ => node::UIntField,
};
(docstring, ty)
},
};

Expand Down Expand Up @@ -408,12 +430,9 @@ impl<'a, 'b> Parser<'a, 'b> {
}

fn parse_enum_variants(&mut self) -> Option<Vec<node::Variant>> {
// sitting on LBRACE
// sitting at beginning of block after LBRACE
let mut variants: Vec<node::Variant> = Vec::new();

if !self.expect(&token::LBRACE) {
return None;
}

let mut require_comma: bool = false;
loop {
Expand Down Expand Up @@ -455,23 +474,32 @@ impl<'a, 'b> Parser<'a, 'b> {
_ => {}
}

let docstring = self.parse_docstring();
let docstring = self.parse_docstring(Trailing);

let value: node::Variant = node::Variant { name: name, value: value, docstring: docstring };
variants.push(value);
}
Some(variants)
}

fn parse_docstring(&mut self) -> Option<Spanned<Ident>> {
fn parse_docstring(&mut self, scope: Scope) -> Option<Spanned<Ident>> {
let mut docs: Vec<String> = Vec::new();
let prefix = match scope {
Inner => "//!",
Trailing => "//=",
Outer => "///",
};
loop {
match self.token {
token::DOC_COMMENT(docstring) => {
self.bump();
// for some reason ident begins with '/// '
let s = token::get_ident(docstring.ident());
let stripped = s.get().trim_left_chars(&['/',' ']);
if !s.get().starts_with(prefix) {
break
}

self.bump();
let stripped = s.get().slice_from(prefix.len())
.trim_left_chars(&[' ']);
docs.push(String::from_str(stripped));
},
_ => break,
Expand Down

0 comments on commit c9c1c07

Please sign in to comment.