grammar.qbk 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. [#grammar]
  2. [section grammar]
  3. [h1 Synopsis]
  4. template <class StartSymbol = BOOST_METAPARSE_STRING("S")>
  5. struct grammar
  6. {
  7. template <class S, class Pos>
  8. struct apply;
  9. template <class Name, class P>
  10. struct import;
  11. template <class S, class Action = /* unspecified */>
  12. struct rule;
  13. };
  14. [h1 Description]
  15. [note
  16. Note that using this adds a significant overhead to your builds. When someone
  17. uses your parser, the compiler will have to build your grammar parser, use it
  18. to parse your grammar and build your parser and then it can parse the input
  19. the user would like to parse with your parser. You might consider using the
  20. parser combinators the library provides.
  21. ]
  22. Parser combinator for constructing parsers based on an embedded DSL similar to
  23. EBNF. It can be used the following way:
  24. grammar<>
  25. // definitions
  26. where a definition can be a rule or an import command.
  27. Rules look like on of the following:
  28. ::rule<BOOST_METAPARSE_STRING("name ::= def")>
  29. ::rule<BOOST_METAPARSE_STRING("name ::= def"), semantic_action>
  30. `name` consists of letters, digits and the `_` character. It is the name of
  31. the symbol being defined. `def` describes the rule. It can be
  32. * the name of a symbol
  33. * a terminal, which is a character between single quotes. `\` can be used for
  34. escaping. The following are accepted: `\n`, `\r`, `\t`, `\\`, `\'`
  35. * a sequence of definitions
  36. * a definition followed by the `*` character, which means repetition accepting
  37. 0 match
  38. * a definition followed by the `+` character, which means repetition expecting
  39. at least one match
  40. * a definition in brackets
  41. Rules take an optional `semantic_action` argument. It is a placeholder
  42. expression taking one argument. When this is given, this is used to transform
  43. the result of the rule.
  44. Imports can be used to turn an arbitrary parser into a symbol available for the
  45. rules. Import definitions look like the following:
  46. ::import<BOOST_METAPARSE_STRING("name"), parser>
  47. `name` is the name of the symbol, `parser` is the parser to bind the name to.
  48. The start symbol of the grammar is specified by the template argument of the
  49. `grammar` template. This is optional, the default value is `S`.
  50. Note that the current implementation "inlines" the referenced symbols while
  51. parsing the grammar and recursion is not supported because of this.
  52. [h1 Header]
  53. #include <boost/metaparse/grammar.hpp>
  54. [h1 Example]
  55. #define BOOST_METAPARSE_LIMIT_STRING_SIZE 64
  56. #include <boost/metaparse/grammar.hpp>
  57. #include <boost/metaparse/token.hpp>
  58. #include <boost/metaparse/int_.hpp>
  59. #include <boost/metaparse/entire_input.hpp>
  60. #include <boost/metaparse/build_parser.hpp>
  61. #include <boost/metaparse/string.hpp>
  62. #include <boost/mpl/front.hpp>
  63. #include <boost/mpl/back.hpp>
  64. #include <boost/mpl/plus.hpp>
  65. #include <boost/mpl/fold.hpp>
  66. #include <boost/mpl/lambda.hpp>
  67. using boost::metaparse::token;
  68. using boost::metaparse::int_;
  69. using boost::metaparse::build_parser;
  70. using boost::metaparse::entire_input;
  71. using boost::metaparse::grammar;
  72. using boost::mpl::front;
  73. using boost::mpl::back;
  74. using boost::mpl::plus;
  75. using boost::mpl::fold;
  76. using boost::mpl::lambda;
  77. using boost::mpl::_1;
  78. using boost::mpl::_2;
  79. template <class A, class B>
  80. struct lazy_plus : boost::mpl::plus<typename A::type, typename B::type> {};
  81. template <class Sequence, class State, class ForwardOp>
  82. struct lazy_fold :
  83. fold<typename Sequence::type, typename State::type, typename ForwardOp::type>
  84. {};
  85. using plus_action =
  86. lazy_fold<back<_1>, front<_1>, lambda<lazy_plus<_1, back<_2>>>::type>;
  87. using plus_grammar =
  88. grammar<BOOST_METAPARSE_STRING("plus_exp")>
  89. ::import<BOOST_METAPARSE_STRING("int_token"), token<int_>>::type
  90. ::rule<BOOST_METAPARSE_STRING("ws ::= (' ' | '\n' | '\r' | '\t')*")>::type
  91. ::rule<BOOST_METAPARSE_STRING("plus_token ::= '+' ws"), front<_1>>::type
  92. ::rule<BOOST_METAPARSE_STRING("plus_exp ::= int_token (plus_token int_token)*"), plus_action>::type
  93. ;
  94. using plus_parser = build_parser<entire_input<plus_grammar>>;
  95. static_assert(
  96. plus_parser::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type::value == 10,
  97. "Arithmetic expression should be evaluated"
  98. );
  99. [endsect]