簡體   English   中英

如何使用 ragel correclty 實現正則表達式 /cat[s]?(\\b|$)/?

[英]How to implement regex /cat[s]?(\b|$)/ with ragel correclty?

我想加速我用 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)))
  }
}

有限狀態機圖

輸出是正確的:

'cat': true
'cats': true
'cat and dog': true
'cats and dogs': true
'caterpillar': false

我確實認為有更好的方法。 ragel處理輸入結束的“正確”方法是什么?

當然,處理輸入結束的正確方法是使用 EOF 操作。 並使用一般的動作,像這樣(減少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

並像這樣工作: 在此處輸入圖片說明

它添加的是setMatched操作,該操作由 EOF 在第一台機器( cats? )的最終狀態之一( %/setMatched )中觸發,或者在進入( >setMatched )第二個狀態(幾乎是\\b ,但實際上可以用內部space機代替)。 它完全消除了checkMatch的需要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM