Here is a complete rebol script which should help you out :-)
Note that the variables do not have to start with a dot, nor do the parse rules require to be surrounded in = signs. Its a quick way to separate the task of each thing within the rules. This way its much easier to identify which word does what, which is especially important when you start to build larger rules.
rebol [
title: "func spec extractor"
]
code: {adjoin: func [
"Adjoins"
series [series!] "Series to adjoin"
joinee
/local other
][...]
append: func [
{Appends a value to the tail of a series and returns the series head.}
series [series! port!]
value
/only "Appends a block value as a block"
][ ... ]
}
code: load code
;----
; setting to a temp variable, prevents .param-str from being erased
; if the rule doesn't match at the point the rule is used (it may be optional)
;----
=param-str=: [set .tmp string! (.param-str: .tmp)]
=param-types=: [set .tmp into [some [word!]] (.param-types: .tmp)]
=param=: [
(.param-types: .tmp: .param-str: none )
set .param-name word!
opt =param-str=
opt =param-types=
opt =param-str=
(
append/only .param-blk .tmp: reduce [ .param-name .param-str .param-types ]
)
]
=refinements=: [
(.ref-str: none)
set .refinement refinement!
opt [ set .ref-str string! ]
(
append .param-blk .refinement
append .param-blk .ref-str
)
any =param=
]
=func-rule=: [
; set/reset variables
(
func-def: context [name: none doc-str: none args: [] refinements: [] code: none]
.tmp: .func-name: .doc-str: .param-str: none
)
set .func-name set-word!
'func into [
opt [ set .doc-str string! ]
( func-def/args: .param-blk: copy [] )
any =param=
( func-def/refinements: .param-blk: copy [] )
any =refinements=
here:
]
set .func-body block!
(
func-def/name: .func-name
func-def/doc-str: .doc-str
func-def/code: .func-body
)
]
funcs: []
parse code [ some [ =func-rule= ( append funcs func-def) | skip ]]
probe funcs
here is what it prints out:
[make object! [
name: adjoin:
doc-str: "Adjoins"
args: [[
series "Series to adjoin" [series!]
] [
joinee none none
]]
refinements: [
/local none [other none none]
]
code: [...]
] make object! [
name: append:
doc-str: {Appends a value to the tail of a series and returns the series head.}
args: [[
series none [series! port!]
] [
value none none
]]
refinements: [
/only "Appends a block value as a block"
]
code: [...]
]]