== false) {
      break
    }
    results.push(result)
  }
  return results.length ? results : false
}

/**
 * zero or one
 *
 * @param {Walker} walker 表达式字符串读取工具
 * @param {Rule} rule 解析规则
 * @return {ASTNode|undefined} 解析得到的 AST
 */
export const opt = (walker, rule) => {
  return seq(walker, rule) || undefined
}

/**
 * 当匹配到该规则时，则判定为解析失败，反之则解析成功
 *
 * @param {Walker} walker 表达式字符串读取工具
 * @param {Rule} rule 解析规则
 * @return {undefined|false} 成功时返回 undefined，反之则返回 false
 */
export const not = restorable((walker, rule) => {
  let result = seq(walker, rule)
  return result === false ? undefined : false
})

/**
 * 规则定义描述对象
 *
 * @typedef {Object} RuleDescriptor
 * @property {string} type 规则名称
 * @property {Rule|() => Rule} rule 匹配规则
 * @property {Function} match 规则匹配成功后的回调函数
 * @property {Rule|() => Rule} fallback 规则匹配失败时的降级规则
 */

/**
 * 定义规则
 *
 * @param {Walker} walker 表达式字符串读取工具
 * @param {RuleDescriptor} descriptor 规则描述对象
 * @return {ASTNode|undefined|false} 解析得到的 AST
 */
export const def = memoize(singleton(
  (walker, descriptor) => {
    let index = walker.index
    const {rule, match, type, fallback} = descriptor
    let result = seq(walker, rule)

    if (result !== false && match) {
      result = match(result, walker)
    }

    if (result === false && fallback) {
      walker.index = index
      return seq(walker, fallback)
    }

    if (result && !result.type) {
      result.type = type
    }

    return result
  },
  ['rule', 'fallback']
))

/**
 * 文本匹配
 *
 * @param {Walker} walker 表达式字符串读取工具
 * @param {string} pattern 要匹配的字符串
 * @return {ASTNode|false} 解析得到的 AST，匹配失败时返回 false
 */
export const text = memoize(
  (walker, pattern) => {
    let match = walker.matchText(patte