REBOL [ Title: "Match" Author: "Christopher Ross-Gill" Purpose: { Matches a block to a given specification, returning an object with the specified values. } ] match: use [get-one get-some datatype][ datatype: [ 'binary! | 'char! | 'date! | 'decimal! | 'email! | 'file! | 'get-word! | 'integer! | 'issue! | 'lit-path! | 'lit-word! | 'logic! | 'money! | 'none! | 'number! | 'pair! | 'paren! | 'path! | 'range! | 'refinement! | 'set-path! | 'set-word! | 'string! | 'tag! | 'time! | 'tuple! | 'url! | 'word! ] get-one: func [data type /local res][ parse data [some [res: type to end break | skip]] unless tail? res [take res] ] get-some: func [data type /local pos res][ res: make block! length? data parse data [some [pos: type (append res take pos) :pos | skip]] unless empty? res [res] ] func [[catch] data spec /local out val word freq types][ data: copy data out: context append remove-each item copy spec [not set-word? item] none unless parse spec [ some [ set word set-word! (word: to-word word) set freq ['opt | 'any | 'some | ] copy types [datatype any ['| datatype]] ( switch/default freq [ any [val: get-some data types] opt [val: get-one data types] some [ unless val: get-some data types [ throw make error! rejoin ["Required: " form word] ] ] ][ unless val: get-one data types [ throw make error! rejoin ["Required: " form word] ] ] out/(word): val ) ] ][throw make error! "Invalid MATCH Spec"] either empty? data [out][throw make error! rejoin ["Too Many Options: " mold data]] ] ]