parse term rule.
| 1024 | |
| 1025 | // parse term rule. |
| 1026 | bool _context::parse_term(rule& r) { |
| 1027 | // save the state of the rule |
| 1028 | rule::_state old_state = r.m_state; |
| 1029 | // restore the rule's state |
| 1030 | rule::_state_guard quard(old_state, &r.m_state); |
| 1031 | |
| 1032 | // success/failure result |
| 1033 | bool ok = false; |
| 1034 | |
| 1035 | // compute the new position |
| 1036 | size_t new_pos = m_pos.m_it - m_begin; |
| 1037 | |
| 1038 | // check if we have left recursion |
| 1039 | bool lr = new_pos == r.m_state.m_pos; |
| 1040 | |
| 1041 | // update the rule's state |
| 1042 | r.m_state.m_pos = new_pos; |
| 1043 | |
| 1044 | // handle the mode of the rule |
| 1045 | switch (r.m_state.m_mode) { |
| 1046 | // normal parse |
| 1047 | case rule::_PARSE: |
| 1048 | if (lr) { |
| 1049 | // first try to parse the rule by rejecting it, so alternative branches are examined |
| 1050 | r.m_state.m_mode = rule::_REJECT; |
| 1051 | ok = _parse_term(r); |
| 1052 | |
| 1053 | // if the first try is successful, try accepting the rule, |
| 1054 | // so other elements of the sequence are parsed |
| 1055 | if (ok) { |
| 1056 | r.m_state.m_mode = rule::_ACCEPT; |
| 1057 | |
| 1058 | // loop until no more parsing can be done |
| 1059 | for (;;) { |
| 1060 | // store the correct state, in order to backtrack if the call fails |
| 1061 | _state st(*this); |
| 1062 | |
| 1063 | // update the rule position to the current position, |
| 1064 | // because at this state the rule is resolving the left recursion |
| 1065 | r.m_state.m_pos = m_pos.m_it - m_begin; |
| 1066 | |
| 1067 | // if parsing fails, restore the last good state and stop |
| 1068 | if (!_parse_term(r)) { |
| 1069 | restore(st); |
| 1070 | break; |
| 1071 | } |
| 1072 | } |
| 1073 | |
| 1074 | // since the left recursion was resolved successfully, |
| 1075 | // return via a non-local exit |
| 1076 | throw _lr_ok(r.this_ptr()); |
| 1077 | } |
| 1078 | } else { |
| 1079 | try { |
| 1080 | ok = _parse_term(r); |
| 1081 | } catch (const _lr_ok& ex) { |
| 1082 | // since left recursions may be mutual, we must test which rule's left recursion |
| 1083 | // was ended successfully |
no test coverage detected