【转】C++轻量级可配置语法分析器
Combinator_Parser这个分析器包含了四个文件:
VL_Data_Basic.h(使用了其中的智能指针VL_AutoPtr和一些类型重命名)
VL_CpData.h(数据结构)
VL_CpKernel.h/cpp(词法分析器和语法分析器)
以下是将一个四则运算式子的字符串进行词法分析,分割成记号之后求值的代码:
1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
2 #include "..\..\..\..\VL++\Library\Data\Grammar2\VL_CpKernel.h"
3
4 using namespace vl;
5 using namespace vl::platform;
6 using namespace vl::grammar;
7
8 enum Operator
9 {
10 opAdd,
11 opSub,
12 opMul,
13 opDiv
14 };
15
16 enum TokenID
17 {
18 tiNumber,
19 tiLeft,
20 tiRight,
21 tiAdd,
22 tiSub,
23 tiMul,
24 tiDiv
25 };
26
27 VDouble Number(const VL_CpToken& Input)
28 {
29 return VUnicodeString(Input.Start,Input.Length).ToDouble();
30 }
31
32 Operator Op(const VL_CpToken& Input)
33 {
34 switch(Input.ID)
35 {
36 case tiAdd:return opAdd;
37 case tiSub:return opSub;
38 case tiMul:return opMul;
39 case tiDiv:return opDiv;
40 default:return (Operator)-1;
41 }
42 }
43
44 VDouble RemoveBracket(const VL_CpPair<VL_CpPair<VL_CpToken , VDouble> , VL_CpToken>& Input)
45 {
46 return Input.First.Second;
47 }
48
49 VDouble Calculate(const VL_CpPair<VDouble,VL_CpList<VL_CpPair<Operator,VDouble>>>& Numbers)
50 {
51 VDouble Result=Numbers.First;
52 VL_CpList<VL_CpPair<Operator,VDouble>>::Node::Ptr Current=Numbers.Second.Head;
53 while(Current)
54 {
55 switch(Current->Data.First)
56 {
57 case opAdd:
58 Result+=Current->Data.Second;
59 break;
60 case opSub:
61 Result-=Current->Data.Second;
62 break;
63 case opMul:
64 Result*=Current->Data.Second;
65 break;
66 case opDiv:
67 Result/=Current->Data.Second;
68 break;
69 }
70 Current=Current->Next;
71 }
72 return Result;
73 }
74
75 void Parse()
76 {
77 VL_CpLexer Lexer;
78 Lexer
79 <<Token(false,L"(",tiLeft)
80 <<Token(false,L")",tiRight)
81 <<Token(false,L"+",tiAdd)
82 <<Token(false,L"-",tiSub)
83 <<Token(false,L"*",tiMul)
84 <<Token(false,L"/",tiDiv)
85 <<Token(false,_Float,tiNumber)
86 ;
87
88 _Wrapper<VL_CpTokenNodePtr , VDouble> Factor,Term,Expr;
89 Factor = (Number<<=Token(tiNumber)) | (RemoveBracket <<= Token(tiLeft) + Expr + Token(tiRight));
90 Term = Calculate <<= Factor + *((Op<<=Token(tiMul)|Token(tiDiv)) + Factor);
91 Expr = Calculate <<= Term + *((Op<<=Token(tiAdd)|Token(tiSub)) + Term);
92
93 VL_CpParser<VL_CpTokenNodePtr , VDouble> p=Expr;
94 VL_CpParser<VL_CpTokenNodePtr , VDouble>::_FullResult Value=p.Parse(Lexer.Parse(L"(1+2)*(3+4)").First.Head);
95 GetConsole()->Write(L"结果:\t"+VUnicodeString(Value.Head->Data.First)+L"\r\n");
96 }
97
98 void vlmain()
99 {
100 GetConsole()->SetTitle(L"Vczh Combinator Parser");
101 GetConsole()->SetTestMemoryLeaks(true);
102 GetConsole()->SetPauseOnExit(true);
103
104 Parse();
105 }
2 #include "..\..\..\..\VL++\Library\Data\Grammar2\VL_CpKernel.h"
3
4 using namespace vl;
5 using namespace vl::platform;
6 using namespace vl::grammar;
7
8 enum Operator
9 {
10 opAdd,
11 opSub,
12 opMul,
13 opDiv
14 };
15
16 enum TokenID
17 {
18 tiNumber,
19 tiLeft,
20 tiRight,
21 tiAdd,
22 tiSub,
23 tiMul,
24 tiDiv
25 };
26
27 VDouble Number(const VL_CpToken& Input)
28 {
29 return VUnicodeString(Input.Start,Input.Length).ToDouble();
30 }
31
32 Operator Op(const VL_CpToken& Input)
33 {
34 switch(Input.ID)
35 {
36 case tiAdd:return opAdd;
37 case tiSub:return opSub;
38 case tiMul:return opMul;
39 case tiDiv:return opDiv;
40 default:return (Operator)-1;
41 }
42 }
43
44 VDouble RemoveBracket(const VL_CpPair<VL_CpPair<VL_CpToken , VDouble> , VL_CpToken>& Input)
45 {
46 return Input.First.Second;
47 }
48
49 VDouble Calculate(const VL_CpPair<VDouble,VL_CpList<VL_CpPair<Operator,VDouble>>>& Numbers)
50 {
51 VDouble Result=Numbers.First;
52 VL_CpList<VL_CpPair<Operator,VDouble>>::Node::Ptr Current=Numbers.Second.Head;
53 while(Current)
54 {
55 switch(Current->Data.First)
56 {
57 case opAdd:
58 Result+=Current->Data.Second;
59 break;
60 case opSub:
61 Result-=Current->Data.Second;
62 break;
63 case opMul:
64 Result*=Current->Data.Second;
65 break;
66 case opDiv:
67 Result/=Current->Data.Second;
68 break;
69 }
70 Current=Current->Next;
71 }
72 return Result;
73 }
74
75 void Parse()
76 {
77 VL_CpLexer Lexer;
78 Lexer
79 <<Token(false,L"(",tiLeft)
80 <<Token(false,L")",tiRight)
81 <<Token(false,L"+",tiAdd)
82 <<Token(false,L"-",tiSub)
83 <<Token(false,L"*",tiMul)
84 <<Token(false,L"/",tiDiv)
85 <<Token(false,_Float,tiNumber)
86 ;
87
88 _Wrapper<VL_CpTokenNodePtr , VDouble> Factor,Term,Expr;
89 Factor = (Number<<=Token(tiNumber)) | (RemoveBracket <<= Token(tiLeft) + Expr + Token(tiRight));
90 Term = Calculate <<= Factor + *((Op<<=Token(tiMul)|Token(tiDiv)) + Factor);
91 Expr = Calculate <<= Term + *((Op<<=Token(tiAdd)|Token(tiSub)) + Term);
92
93 VL_CpParser<VL_CpTokenNodePtr , VDouble> p=Expr;
94 VL_CpParser<VL_CpTokenNodePtr , VDouble>::_FullResult Value=p.Parse(Lexer.Parse(L"(1+2)*(3+4)").First.Head);
95 GetConsole()->Write(L"结果:\t"+VUnicodeString(Value.Head->Data.First)+L"\r\n");
96 }
97
98 void vlmain()
99 {
100 GetConsole()->SetTitle(L"Vczh Combinator Parser");
101 GetConsole()->SetTestMemoryLeaks(true);
102 GetConsole()->SetPauseOnExit(true);
103
104 Parse();
105 }