Learning Spirit 1
Spirit is a syntax analysis framework in Boost. Using Spirit can be used to write a syntax analysis program.
Spirit has the following features:
l Use the recursive drop analysis program (the efficiency of the analysis is not high)
l Template element programming technology (slow compilation, but increased the running speed of the program)
l EBNF syntax representation (easy to use)
Hello, Spirit!
Let's take a simple example to see what spirit is going.
What we have to do is analyzing a piece of text similar to:
1, 12, 11, 200, 111
Use a comma-divided integer sequence and then find them. Of course, this program does not use Spirit to be more simple, and we are just simple examples here, Spirit is not just this.
Parsing
First we analyze the grammar of this text, use EBNF as follows: (EBNF-EXTEND Backus Naur Form, is used to represent the literary law)
S :: = integer (',' integer) *
If you have not studied the principle of compilation, then you may not understand the above style. Simply put, meaning is an integer, and then repeat any number of commas integers. It is a bit similar to the syntax of the regular expression.
In Spirit's EBNF grammar, it is a bit different from this. First, the asterisk * This operator must be prejudice because there is only a pre-measured asterisk in C to indicate the pointer operation (of course, the spirit reloaded pointer operator makes it repeated). Then, different parts of the formula use >> operators, indicate the order. A >> B represents the syntax of AB. The final style is like this:
S = integer >> * (',' >> integer)
Of course, the above formula is not final.
Parser
In Spirit, similar to INTEGER and ',' is called Parser, Parser is used to match the text.
For example: INT_P is used to match a decimal integer. That is, if it is analyzed by int_P, ""
10 "
"
123 "
Such strings are syntax, and "12Ab" "// 11" is not conforming to grammar.
CH_P (c) is used to match characters C, c may be char or WCHAR_T, for example: ch_p (',') is used to match a comma.
The result of the connection between the Parser is also a PARSER.
E.g:
CH_P ('a') >> CH_P ('b') matches "ab"
CH_P ('a') >> * ch_ ('b') matches "A", "AB", "ABB", "ABBB", ...
Then, the syntax of the comma-divided integer sequence can be expressed as:
S = INT_P >> * (CH_P (',') >> INT_P);
It is possible that you will have questions, what INT_P and CH_P here?
INT_P is a pre-defined object similar to COUT, which is int_Parser
CH_P is a function that returns a chlit
These will be said later.
Finally, what is the type of s, how do we define its type?
The type of S is usually rule <>, Rule <> is a container of a Parser, which can save any type of Parser. Of course, Rule <> itself can be used as a PARSER. E.g:
Rule <> s, t;
T = CH _ (',') >> INT_P;
S = INT_P >> * T;
This is equivalent to:
Rule <> s = int_p >> * (ch_p (',') >> INT_P);
PARSE function
At this point, we have used Spirit to expressed syntax, then use this syntax to analyze strings?
The answer is the PARSE function. The syntax is as follows:
PARSE (STR, S, Space_P);
Here Str is a 0th tail string of a C language, and s is the above Rule <>.
Space_p is a Parser, here as Skip Parser, used to filter out blank characters (comma and integer signs).
Parse also accepts the input of the iterator, PARSE (First, Last, S, Space_P), First, Last is the iterator that starts ending.
PARSE returns a PARSE_INFO <> object to return the results of the analysis (success or failure).
PARSE_INFO <> has 4 members:
STOP analysis
His a successful match, that is, the syntax.
Does Full match all the inputs, that is, the syntax is not a match without the remaining characters.
LENGTH matches the number of characters
At this point, we can write the program.
code show as below:
#include
#include
#include
Using namespace std;
USING NAMESPACE boost :: spirit;
int main ()
{
Rule
// So you can't use the default template parameters
/ / Don't care about this problem now.
= INT_P >> * (CH_P (',') >> INT_P);
String Str;
While (GetLine (CIN, STR))
{
PARSE_INFO <> info = parse (str.c_str (), s, space_p);
IF (Info.full)
{
Cout << "Parse Successful." << endl;
}
Else
{
Cout << "Parse Fail." << Endl;
}
}
Return 0;
}
(To be commitUed)