go - 如何正确实现 regex/cat[s]?(\b|$)/与 ragel?

标签 go ragel

我想加速我用 Go 编写的程序并将正则表达式转换为有限状态机 ragel .在转换类似于 /cat[s]?(\b|$)/ 的正则表达式时,我无法弄清楚如何正确匹配输入的结尾(它匹配单词边框或输入结尾),所以我做了这个解决方法:

package main

import(
  "strings"
  "fmt"
  "unicode"
)

func Match(data []byte) bool {
  data = []byte(strings.ToLower(string(data)))

  %%{
    machine test;
    write data;
  }%%

  cs, p, pe, eof := 0, 0, len(data), len(data)
  _ = eof

  var matchPos int

  %%{
    main := ('cat' 's'?) @{matchPos = p};

    write init;
    write exec;
  }%%

  return checkMatch(data, matchPos+1)
}

func checkMatch(data []byte, p int) bool {
  if p == len(data) {
    return true
  }
  tail := string(data[p:])
  c := []rune(tail)[0]
  if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
    return true
  }
  return false
}

func main () {
  vs := []string{
    "cat",
    "cats",
    "cat and dog",
    "cats and dogs",
    "caterpillar",
  }
  for _, v := range vs {
    fmt.Printf("'%s': %v\n", v, Match([]byte(v)))
  }
}

Finite State Machine Graph

输出是正确的:
'cat': true
'cats': true
'cat and dog': true
'cats and dogs': true
'caterpillar': false

我确实认为有更好的方法。使用 ragel 处理输入结束的“正确”方式是什么? ?

最佳答案

当然,处理输入结束的正确方法是使用 EOF 操作。并使用一般的 Action ,像这样(减少 Match 函数):

  var matched bool

  %%{
    action setMatched {
      matched = true
    }

    main := ('cat' 's'?) %/setMatched ([ \t] >setMatched);

    write init;
    write exec;
  }%%
  // Variable generated and not used by Ragel.
  _ = _test_trans_actions

  return matched

这会产生以下输出(注意添加了一个重要的测试用例):
'cat': true
'cats': true
'cat and dog': true
'cats and dogs': true
'catspaw': false
'caterpillar': false

像这样工作:
enter image description here

它添加的是setMatched由 EOF 在第一台机器 ( %/setMatched ) 的一个最终状态 ( cats? ) 中触发的 Action ,或者在进入 ( >setMatched ) 第二个机器 (几乎是 \b 时) 触发的 Action ,但可以实际替换为内部 space 机器)。它消除了对 checkMatch 的需求完全地。

关于go - 如何正确实现 regex/cat[s]?(\b|$)/与 ragel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59655001/

相关文章:

image - 在 Go 中的 Goroutine 中运行和使用 SDL

mongodb - 如何更新子文档数组字段以及 Mongodb、Mgo 中的其他一些字段?

json - 将 int 设置为 0 的 Unmarshal/Marshal json 似乎不起作用

c - ragel如何从文件中读取源代码?

d - 解析器生成器和 Ragel……制作我自己的 D 解析器

c - 为什么 Ragel 执行 to-State 和 From-State 操作两次?

java - 滥用 ragel,可能需要新的方法/工具

arrays - Golang graphql 使用子图迭代 map

mongodb - 在 MongoDB 中基于 ID 对两个集合执行连接

xml - 如何编写一个简单的 Ragel 分词器(无回溯)?