该|
运算符是左关联的,因此该表中的一行将被解析为:
('Key' | 'Value') | 'Comments'
然后,您可以检测每一行的开始和结束位置是让|
操作符返回一个包含其操作数的列表,然后为每个|
询问左侧操作数(即this
)是否是一个列表。如果是,则表示它是一行的延续;如果它不是一个列表,则意味着它是一个新行。
这是一个 DSL 的完整示例,它使用Category来解析这些数据集,以避免覆盖 Object 元类上的内容:
@Category(Object)
class DatasetCategory {
// A static property for holding the results of the DSL.
static results
def or(other) {
if (this instanceof List) {
// Already in a row. Add the value to the row.
return this << other
} else {
// A new row.
def row = [this, other]
results << row
return row
}
}
}
// This is the method that receives a closure with the DSL and returns the
// parsed result.
def dataset(Closure cl) {
// Initialize results and execute closure using the DatasetCategory.
DatasetCategory.results = []
use (DatasetCategory) { cl() }
// Convert the 2D results array into a list of objects:
def table = DatasetCategory.results
def header = table.head()
def rows = table.tail()
rows.collect { row ->
[header, row].transpose().collectEntries { it }
}
}
// Example usage.
def data = dataset {
'Key' | 'Value' | 'Comments'
1 | 'foo' | 'something'
2 | 'bar' | 'something else'
}
// Correcness test :)
assert data == [
[Key: 1, Value: 'foo', Comments: 'something'],
[Key: 2, Value: 'bar', Comments: 'something else']
]
在此示例中,我将表解析为地图列表,但在 DSL 闭包运行后,您应该能够对 DatasetCategory 的结果执行任何操作。