Check-in [2c725f9968]

Not logged in

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
Changes
hide diffs unified diffs patch

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