Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| SHA1 Hash: | 2c725f9968df10377d5b542aabfca99cfe3adb20 |
|---|---|
| Date: | 2008-06-21 10:57:05 |
| User: | stephan |
| Comment: | added some code from the qboard tree |
Tags And Properties
- branch=trunk inherited from [d45e7467f2]
- sym-trunk inherited from [d45e7467f2]
Changes
Changes to parsepp.hpp
| Old (76a78a44f7ca441b) | New (4a4cc623aaa9b4b9) | |||
|---|---|---|---|---|
| 1 | #ifndef s11n_net_PARSEPP_HPP_INCLUDED | 1 | #ifndef s11n_net_PARSEPP_HPP_INCLUDED | |
| 2 | #define s11n_net_PARSEPP_HPP_INCLUDED | 2 | #define s11n_net_PARSEPP_HPP_INCLUDED | |
| 3 | 3 | |||
| 4 | #include <map> | 4 | #include <map> | |
| 5 | #include <string> | 5 | #include <string> | |
| 246 hidden lines | ||||
| 252 | Returns a copy of this object's underlying start point | 252 | Returns a copy of this object's underlying start point | |
| 253 | iterator. | 253 | iterator. | |
| 254 | */ | 254 | */ | |
| 255 | iterator begin() const | 255 | iterator begin() const | |
| 256 | { | 256 | { | |
| 257 | return this->m_pos; | | | 257 | return this->m_beg; |
| 258 | } | 258 | } | |
| 259 | /** | 259 | /** | |
| 260 | Returns a copy of this object's underlying end point | 260 | Returns a copy of this object's underlying end point | |
| 261 | iterator. | 261 | iterator. | |
| 262 | */ | 262 | */ | |
| 263 | iterator end() const | 263 | iterator end() const | |
| 264 | { | 264 | { | |
| 265 | return this->m_pos; | | | 265 | return this->m_end; |
| 266 | } | 266 | } | |
| 267 | 267 | |||
| 268 | /** | 268 | /** | |
| 269 | Prefix increment. Avances this object one char then returns | 269 | Prefix increment. Avances this object one char then returns | |
| 270 | this object. | 270 | this object. | |
| 311 hidden lines | ||||
| 582 | if( m_max < m_it ) m_max = m_it; | 582 | if( m_max < m_it ) m_max = m_it; | |
| 583 | } | 583 | } | |
| 584 | }; | 584 | }; | |
| 585 | 585 | |||
| 586 | 586 | |||
| > | 587 | void calc_line_col( parse_iterator pos, | ||
| > | 588 | int & line, int & col ); | ||
| > | 589 | |||
| 587 | /** | 590 | /** | |
| 588 | Base exception class used by this framework. | 591 | Base exception class used by this framework. | |
| > | 592 | |||
| > | 593 | Note that if the parser_state to which a parse_error applies | ||
| > | 594 | goes out of scope during throw/catch unwinding, the pos() and | ||
| > | 595 | state() members have undefined resuls. | ||
| 589 | */ | 596 | */ | |
| 590 | class parse_error : public std::exception | 597 | class parse_error : public std::exception | |
| 591 | { | 598 | { | |
| > | 599 | private: | ||
| > | 600 | void calcWhere() | ||
| > | 601 | { | ||
| > | 602 | int line = 1, col = 0; | ||
| > | 603 | calc_line_col( m_pos, line, col ); | ||
| > | 604 | std::ostringstream os; | ||
| > | 605 | os << "[line "<<line<<" col "<<col<<']'; | ||
| > | 606 | m_where = (os.str()); | ||
| > | 607 | } | ||
| > | 608 | |||
| 592 | public: | 609 | public: | |
| 593 | 610 | |||
| 594 | parse_error(parser_state const & st ) : | 611 | parse_error(parser_state const & st ) : | |
| 595 | m_st(&st), | 612 | m_st(&st), | |
| 596 | m_pos(st.pos()), | 613 | m_pos(st.pos()), | |
| 597 | m_what() {} | | | 614 | m_what(), |
| | | 615 | m_where() | ||
| | | 616 | { | ||
| | | 617 | calcWhere(); | ||
| | | 618 | } | ||
| 598 | parse_error(parser_state const & st, std::string const & w ) : | 619 | parse_error(parser_state const & st, std::string const & w ) : | |
| 599 | m_st(&st), | 620 | m_st(&st), | |
| 600 | m_pos(st.pos()), | 621 | m_pos(st.pos()), | |
| 601 | m_what(w) {} | | | 622 | m_what(w), |
| | | 623 | m_where() | ||
| | | 624 | { | ||
| | | 625 | calcWhere(); | ||
| | | 626 | } | ||
| 602 | virtual ~parse_error() throw() {} | 627 | virtual ~parse_error() throw() {} | |
| 603 | virtual char const * what() const throw() | 628 | virtual char const * what() const throw() | |
| 604 | { | 629 | { | |
| 605 | return m_what.c_str(); | 630 | return m_what.c_str(); | |
| 606 | } | 631 | } | |
| 607 | parser_state const * state() const | 632 | parser_state const * state() const | |
| 608 | { return this->m_st; } | 633 | { return this->m_st; } | |
| 609 | 634 | |||
| 610 | parse_iterator pos() const { return this->m_pos; } | 635 | parse_iterator pos() const { return this->m_pos; } | |
| > | 636 | |||
| > | 637 | /** | ||
| > | 638 | Returns a best guess as to the position of the | ||
| > | 639 | error. | ||
| > | 640 | */ | ||
| > | 641 | std::string where() const throw() | ||
| > | 642 | { | ||
| > | 643 | return m_where; | ||
| > | 644 | } | ||
| > | 645 | |||
| 611 | protected: | 646 | protected: | |
| 612 | parse_error(std::string const & w ) : m_st(0), m_what(w) {} | 647 | parse_error(std::string const & w ) : m_st(0), m_what(w) {} | |
| 613 | void pos( parse_iterator const & p ) { this->m_pos = p; } | 648 | void pos( parse_iterator const & p ) { this->m_pos = p; } | |
| 614 | 649 | |||
| 615 | private: | 650 | private: | |
| 616 | parser_state const * m_st; | 651 | parser_state const * m_st; | |
| 617 | parse_iterator m_pos; | 652 | parse_iterator m_pos; | |
| 618 | std::string m_what; | 653 | std::string m_what; | |
| > | 654 | std::string m_where; | ||
| 619 | }; | 655 | }; | |
| 620 | 656 | |||
| 621 | 657 | |||
| 622 | /** | 658 | /** | |
| 623 | This type is used to mark an iterator's position at | 659 | This type is used to mark an iterator's position at | |
| 158 hidden lines | ||||
| 782 | detail regarding the input string's lifespan and immutability. | 818 | detail regarding the input string's lifespan and immutability. | |
| 783 | */ | 819 | */ | |
| 784 | template <typename Rule, typename ClientState> | 820 | template <typename Rule, typename ClientState> | |
| 785 | bool parse( parse_iterator const & in, ClientState & st) | 821 | bool parse( parse_iterator const & in, ClientState & st) | |
| 786 | { | 822 | { | |
| 787 | parser_state ps(in); | | | 823 | try |
| 788 | return parse<Rule>( ps, st ); | | | 824 | { |
| | | 825 | parser_state ps(in); | ||
| | | 826 | return parse<Rule>( ps, st ); | ||
| | | 827 | } | ||
| | | 828 | catch( parse_error const & ex ) | ||
| | | 829 | { | ||
| | | 830 | // recreate exception without the state, | ||
| | | 831 | // which won't be valid once this function returns. | ||
| | | 832 | std::string msg( ex.what() ); | ||
| | | 833 | msg += "\n Near "+ex.where(); | ||
| | | 834 | throw std::runtime_error( msg ); | ||
| | | 835 | } | ||
| | | 836 | return false; | ||
| 789 | } | 837 | } | |
| 790 | 838 | |||
| 791 | /** | 839 | /** | |
| 792 | Convenience overload. See the parse_iterator(string) ctor for | 840 | Convenience overload. See the parse_iterator(string) ctor for | |
| 793 | important detail regarding the input string's lifespan and | 841 | important detail regarding the input string's lifespan and | |
| 794 | immutability. | 842 | immutability. | |
| 795 | */ | 843 | */ | |
| 796 | template <typename Rule, typename ClientState> | 844 | template <typename Rule, typename ClientState> | |
| 797 | bool parse( std::string const & in, ClientState & st) | 845 | bool parse( std::string const & in, ClientState & st) | |
| 798 | { | 846 | { | |
| 799 | parser_state it(in); | | | 847 | parse_iterator it(in); |
| 800 | return parse<Rule>( it, st ); | 848 | return parse<Rule>( it, st ); | |
| 801 | } | 849 | } | |
| 802 | 850 | |||
| 803 | /** | 851 | /** | |
| 804 | A non-consuming parser which returns Val. | 852 | A non-consuming parser which returns Val. | |
| 372 hidden lines | ||||
| 1177 | template <typename Rule, typename RuleLeft, typename RuleRight = RuleLeft> | 1225 | template <typename Rule, typename RuleLeft, typename RuleRight = RuleLeft> | |
| 1178 | struct r_pad : r_and< rule_list< r_star<RuleLeft>, Rule, r_star<RuleRight> > > | 1226 | struct r_pad : r_and< rule_list< r_star<RuleLeft>, Rule, r_star<RuleRight> > > | |
| 1179 | {}; | 1227 | {}; | |
| 1180 | 1228 | |||
| 1181 | /** | 1229 | /** | |
| > | 1230 | A Rule which advances the input iterator by Count steps. It | ||
| > | 1231 | fails only if it reaches eof before advancing the full | ||
| > | 1232 | amount. Note that it is possible for the input to be advanced | ||
| > | 1233 | exactly to eof and this Rule still return true. That would | ||
| > | 1234 | happen if, e.g., r_advance<3> is used when the input has | ||
| > | 1235 | exactly 3 chars left. | ||
| > | 1236 | |||
| > | 1237 | This type uses an iterator sentry, so it is not as efficient as | ||
| > | 1238 | using r_any for short sequences. | ||
| > | 1239 | */ | ||
| > | 1240 | template <int Count> | ||
| > | 1241 | struct r_advance | ||
| > | 1242 | { | ||
| > | 1243 | typedef r_advance type; | ||
| > | 1244 | template <typename State> | ||
| > | 1245 | static bool matches( parser_state & in, State & ) | ||
| > | 1246 | { | ||
| > | 1247 | placemarker sentry(in); | ||
| > | 1248 | int i = 0; | ||
| > | 1249 | for( ; i < Count; ++i ) | ||
| > | 1250 | { | ||
| > | 1251 | if(in.eof()) break; | ||
| > | 1252 | ++in; | ||
| > | 1253 | } | ||
| > | 1254 | return sentry( i == Count ); | ||
| > | 1255 | } | ||
| > | 1256 | }; | ||
| > | 1257 | |||
| > | 1258 | /** | ||
| > | 1259 | Consumes no input and throws an ExceptionType. | ||
| > | 1260 | */ | ||
| > | 1261 | template <typename ExceptionType> | ||
| > | 1262 | struct r_throw_base | ||
| > | 1263 | { | ||
| > | 1264 | typedef r_throw_base base; | ||
| > | 1265 | template <typename State> | ||
| > | 1266 | static bool matches( parser_state &, State & ) | ||
| > | 1267 | { | ||
| > | 1268 | throw ExceptionType(); | ||
| > | 1269 | } | ||
| > | 1270 | }; | ||
| > | 1271 | |||
| > | 1272 | /** | ||
| > | 1273 | Specialized to ensure the error point is marked. | ||
| > | 1274 | */ | ||
| > | 1275 | template <> | ||
| > | 1276 | struct r_throw_base<parse_error> | ||
| > | 1277 | { | ||
| > | 1278 | typedef r_throw_base type; | ||
| > | 1279 | template <typename State> | ||
| > | 1280 | static bool matches( parser_state & in, State & ) | ||
| > | 1281 | { | ||
| > | 1282 | throw parse_error(in, "parse error triggered by r_throw" ); | ||
| > | 1283 | return false; | ||
| > | 1284 | } | ||
| > | 1285 | }; | ||
| > | 1286 | |||
| > | 1287 | typedef r_throw_base<parse_error> r_throw; | ||
| > | 1288 | |||
| > | 1289 | |||
| > | 1290 | |||
| > | 1291 | /** | ||
| 1182 | Matches any characters in the range [Min..Max] | 1292 | Matches any characters in the range [Min..Max] | |
| 1183 | */ | 1293 | */ | |
| 1184 | template< int Min, int Max > | 1294 | template< int Min, int Max > | |
| 1185 | struct r_range | 1295 | struct r_range | |
| 1186 | { | 1296 | { | |
| 268 hidden lines | ||||
| 1455 | */ | 1565 | */ | |
| 1456 | template <typename Rule> | 1566 | template <typename Rule> | |
| 1457 | struct r_skipws : r_pad<Rule,r_space,r_space> {}; | 1567 | struct r_skipws : r_pad<Rule,r_space,r_space> {}; | |
| 1458 | 1568 | |||
| 1459 | /** | 1569 | /** | |
| > | 1570 | Matches until the first space character. If it is not at | ||
| > | 1571 | a space character, it does not consume but still succeeds. | ||
| > | 1572 | */ | ||
| > | 1573 | struct r_tospace : r_star< | ||
| > | 1574 | r_and< rule_list< r_notat< r_space >, r_advance<1> > > | ||
| > | 1575 | > | ||
| > | 1576 | {}; | ||
| > | 1577 | |||
| > | 1578 | /** | ||
| 1460 | Matches if Rule matches, skipping any amount of leading or | 1579 | Matches if Rule matches, skipping any amount of leading or | |
| 1461 | trailing blanks (space or tab). | 1580 | trailing blanks (space or tab). | |
| 1462 | */ | 1581 | */ | |
| 1463 | template <typename Rule> | 1582 | template <typename Rule> | |
| 1464 | struct r_skipblanks : r_pad<Rule,r_blank,r_blank> {}; | 1583 | struct r_skipblanks : r_pad<Rule,r_blank,r_blank> {}; | |
| > | 1584 | |||
| > | 1585 | /** | ||
| > | 1586 | Matches until the first blank character. | ||
| > | 1587 | */ | ||
| > | 1588 | struct r_toblank : r_star< | ||
| > | 1589 | r_and< rule_list< r_notat< r_blank >, r_advance<1> > > | ||
| > | 1590 | > | ||
| > | 1591 | {}; | ||
| 1465 | 1592 | |||
| 1466 | /** | 1593 | /** | |
| 1467 | Matches the combination \r\n or a single \n. | 1594 | Matches the combination \r\n or a single \n. | |
| 1468 | */ | 1595 | */ | |
| 1469 | struct r_eol : | 1596 | struct r_eol : | |
| 1470 | r_or< rule_list< r_chseq< char_list<'\r','\n'> >, r_ch<'\n'> > > | 1597 | r_or< rule_list< r_chseq< char_list<'\r','\n'> >, r_ch<'\n'> > > | |
| 1471 | {}; | 1598 | {}; | |
| 1472 | 1599 | |||
| > | 1600 | |||
| > | 1601 | /** Parser for C++-style comments. */ | ||
| > | 1602 | struct r_comment_cpp : | ||
| > | 1603 | r_and< rule_list< | ||
| > | 1604 | r_chseq< char_list<'/','/'> >, | ||
| > | 1605 | r_star< r_notch<'\n'> >, | ||
| > | 1606 | r_eol | ||
| > | 1607 | > > | ||
| > | 1608 | {}; | ||
| > | 1609 | |||
| > | 1610 | template <typename R> | ||
| > | 1611 | struct r_throw_if : r_and< rule_list< | ||
| > | 1612 | r_and< rule_list<R,r_throw> >, | ||
| > | 1613 | r_success > > | ||
| > | 1614 | {}; | ||
| > | 1615 | |||
| > | 1616 | namespace Detail | ||
| > | 1617 | { | ||
| > | 1618 | /** Inner part of a C++ comment. Consumes until '*' followed by '/'. */ | ||
| > | 1619 | struct r_comment_c_inner : r_and< rule_list< | ||
| > | 1620 | r_star< r_and< rule_list< | ||
| > | 1621 | r_notat< r_chseq< char_list<'*','/'> > >, | ||
| > | 1622 | r_advance<1> | ||
| > | 1623 | > > >, | ||
| > | 1624 | r_throw_if< r_eof > | ||
| > | 1625 | > > | ||
| > | 1626 | {}; | ||
| > | 1627 | } | ||
| > | 1628 | /** Parser for C-style comments. */ | ||
| > | 1629 | struct r_comment_c : | ||
| > | 1630 | r_and< rule_list< | ||
| > | 1631 | r_chseq< char_list<'/','*'> >, | ||
| > | 1632 | Detail::r_comment_c_inner, | ||
| > | 1633 | r_chseq< char_list<'*','/'> > | ||
| > | 1634 | > > | ||
| > | 1635 | {}; | ||
| > | 1636 | |||
| > | 1637 | |||
| > | 1638 | |||
| > | 1639 | namespace Detail { | ||
| > | 1640 | using namespace Ps; | ||
| > | 1641 | struct line_col_state | ||
| > | 1642 | { | ||
| > | 1643 | int line; | ||
| > | 1644 | int col; | ||
| > | 1645 | line_col_state() : line(1),col(0){} | ||
| > | 1646 | }; | ||
| > | 1647 | struct calc_inc_line | ||
| > | 1648 | { | ||
| > | 1649 | static void matched( parser_state &, | ||
| > | 1650 | const std::string &, | ||
| > | 1651 | line_col_state & state ) | ||
| > | 1652 | { | ||
| > | 1653 | ++state.line; | ||
| > | 1654 | state.col = 0; | ||
| > | 1655 | } | ||
| > | 1656 | }; | ||
| > | 1657 | struct calc_inc_col | ||
| > | 1658 | { | ||
| > | 1659 | static void matched( parser_state &, | ||
| > | 1660 | const std::string &, | ||
| > | 1661 | line_col_state & state ) | ||
| > | 1662 | { | ||
| > | 1663 | ++state.col; | ||
| > | 1664 | } | ||
| > | 1665 | }; | ||
| > | 1666 | struct r_linecol : | ||
| > | 1667 | r_star< r_or< rule_list< | ||
| > | 1668 | r_action< r_eol, calc_inc_line >, | ||
| > | 1669 | r_action< r_any, calc_inc_col > | ||
| > | 1670 | > > > | ||
| > | 1671 | {}; | ||
| > | 1672 | } | ||
| > | 1673 | |||
| > | 1674 | |||
| > | 1675 | /** | ||
| > | 1676 | Walks parse_iterator until its end end. For each newline it | ||
| > | 1677 | finds, line is incremented by one and col is set to 1, | ||
| > | 1678 | otherwise col is incremented by 1. line and col are initialized | ||
| > | 1679 | by this function. | ||
| > | 1680 | |||
| > | 1681 | Column numbers start at 0 and line numbers start at 1 (because | ||
| > | 1682 | emacs does it that way). | ||
| > | 1683 | */ | ||
| > | 1684 | inline void calc_line_col( parse_iterator pos, | ||
| > | 1685 | int & line, int & col ) | ||
| > | 1686 | { | ||
| > | 1687 | line = 1; col = 0; | ||
| > | 1688 | parse_iterator inp( pos.begin(), pos.iter() ); | ||
| > | 1689 | Detail::line_col_state st; | ||
| > | 1690 | parse<Detail::r_linecol>( inp, st ); | ||
| > | 1691 | line = st.line; | ||
| > | 1692 | col = st.col; | ||
| > | 1693 | } | ||
| 1473 | } // namespace | 1694 | } // namespace | |
| 1474 | 1695 | |||
| 1475 | #endif // s11n_net_PARSEPP_HPP_INCLUDED | 1696 | #endif // s11n_net_PARSEPP_HPP_INCLUDED | |