自从几天前被 spirit 的精妙所折服后,就萌生了要用它写一个MDX解析器的想法。
由于完整的MDX相当复杂,一次性到位有相当难度。要做大事,先从小事做起,所以就先取MDX的一个小片断来先做尝试。MDX中最常用的莫过于SELECT语句,就单单SELECT语句还是很复杂,于是就做了大大的简略,将with字句,where字句,以及其他许多可选项省去,总之简略的不能再简略了。基本能解析如下的MDX片断:
select
{[Measures].[Amount],[Measures].[Internet Order Count]}
on columns,
{[Date].[Calendar].[Calendar Year].&[2001],
[Date].[Calendar].[Calendar Year].&[2002],
[Date].[Calendar].[Calendar Year].&[2003],
[Date].[Calendar].[Calendar Year].&[2004]
} on rows
from
[Adventure Works]
旨在学习spirit的使用。
Download full source code
以下就是使用 spirit 构造的解析器.spirit 在 character level 工作,所以不需要一个词法分析的阶段,str_p("select") ,str_p("from") 这样的rule就可以解析 select,from 关键词了,十分便捷!
1 struct mdx_select : public grammar<mdx_select>
2 {
3 template <typename ScannerT>
4 struct definition
5 {
6 definition(mdx_select const& /*self*/)
7 {
8
9 select_statement
10 = as_lower_d[str_p("select")]
11 >> axis_specification_list
12 >> as_lower_d[str_p("from")]
13 >> cube_name[&do_cube];
14
15 axis_specification_list
16 = axis_specification
17 >> *(ch_p(',') >> axis_specification);
18
19 // <axis_specification> ::= <set> ON <axis_name>
20 axis_specification
21 = set_expression >> as_lower_d[str_p("on")] >> axis_name;
22
23 set_expression
24 = ch_p('{')
25 >> member_list
26 >> ch_p('}');
27
28 member_list
29 = member_expression [&do_members]
30 >> *(ch_p(",") >> member_expression[&do_members] );
31
32 member_expression
33 = lexeme_d[+(alnum_p|ch_p('_')|ch_p('&')|ch_p('.')|ch_p('[')|ch_p(']')|ch_p('\x20'))];
34
35 axis_name
36 = as_lower_d[str_p("columns")][do_copy_members(col_members)]
37 | as_lower_d[str_p("rows")][do_copy_members(row_members)]
38 | as_lower_d[str_p("axis0")][do_copy_members(col_members)]
39 | as_lower_d[str_p("axis1")][do_copy_members(row_members)];
40
41 cube_name
42 = lexeme_d[+print_p];
43
44 }
45
46 rule<ScannerT> select_statement,axis_specification_list,axis_specification,
47 set_expression,member_list,member_expression,axis_name,cube_name;
48 rule<ScannerT> const&
49
50 start() const { return select_statement; }
51 };
52 };
2 {
3 template <typename ScannerT>
4 struct definition
5 {
6 definition(mdx_select const& /*self*/)
7 {
8
9 select_statement
10 = as_lower_d[str_p("select")]
11 >> axis_specification_list
12 >> as_lower_d[str_p("from")]
13 >> cube_name[&do_cube];
14
15 axis_specification_list
16 = axis_specification
17 >> *(ch_p(',') >> axis_specification);
18
19 // <axis_specification> ::= <set> ON <axis_name>
20 axis_specification
21 = set_expression >> as_lower_d[str_p("on")] >> axis_name;
22
23 set_expression
24 = ch_p('{')
25 >> member_list
26 >> ch_p('}');
27
28 member_list
29 = member_expression [&do_members]
30 >> *(ch_p(",") >> member_expression[&do_members] );
31
32 member_expression
33 = lexeme_d[+(alnum_p|ch_p('_')|ch_p('&')|ch_p('.')|ch_p('[')|ch_p(']')|ch_p('\x20'))];
34
35 axis_name
36 = as_lower_d[str_p("columns")][do_copy_members(col_members)]
37 | as_lower_d[str_p("rows")][do_copy_members(row_members)]
38 | as_lower_d[str_p("axis0")][do_copy_members(col_members)]
39 | as_lower_d[str_p("axis1")][do_copy_members(row_members)];
40
41 cube_name
42 = lexeme_d[+print_p];
43
44 }
45
46 rule<ScannerT> select_statement,axis_specification_list,axis_specification,
47 set_expression,member_list,member_expression,axis_name,cube_name;
48 rule<ScannerT> const&
49
50 start() const { return select_statement; }
51 };
52 };
spirit 的简单介绍和下载安装使用,请参见
http://www.cnblogs.com/nemowang/archive/2007/05/11/743155.html