我對使用RE-FLEX(柔性兼容詞法分析器)的Flex詞法模式匹配句子分離器/標點URL路徑部分
重構文本片段一個空白標記生成器我在詞法文件中的以下的圖案,我只列出那些參與了這個問題:
// ...
WHITESPACE \r\n|[ \r\n\t\f]
DOMAIN "mil"|"info"|"gov"|"edu"|"biz"|"com"|"org"|"net"|"arpa"|"de"|[a-z]{2}
DIGIT [0-9]
LETTER [a-zA-Z]
SYMBOL ({LETTER}|{DIGIT})({LETTER}|{DIGIT}|"_"|"-")*
BARE_URL {SYMBOL}("."{SYMBOL})*"."{DOMAIN}
URL_PATH ([!*'();:@&=+$,/?%#_.~]|"-"|"["|"]"|{LETTER}|{DIGIT})+
%%
("." | "?" | "!" | ";")+ {
return tokenizer_base::TK_PUNCTUATION;
}
/* ... other patterns ... */
{BARE_URL} {
return tokenizer_base::TK_BARE_URL;
}
(("http"|"https"|"ftp")"://")?{BARE_URL}{URL_PATH}? {
return tokenizer_base::TK_FULL_URL;
}
/* ... */
/** Ignore the rest */
.|{WHITESPACE} {
;
}
%%
這基本上是工作的罰款,但考慮到這種情況下,輸入:
Please visit http://www.google.de.
最後.
在上面的字符串中是一個句子分隔符,並且應該返回爲TK_PUNCTUATION
令牌類型。不幸的是,它不是,其解釋爲TK_FULL_URL
令牌的一部分,並返回爲http://www.google.de.
。
思考正常的正則表達式我試圖將[^!;.]
附加到TK_FULL_URL
模式,但這不起作用。
另一種 - 在我看來,hackish - 解決方案是分析返回的令牌的最後 字符和unput
字符返回到輸入流,如果它匹配標點符號。我可以這樣做:
size_t last = YY_SCANNER.ptr_matcher()->size() - 1; // similar to YYleng
std::string last_str = YY_SCANNER.ptr_matcher()->text(); // similar to YYtext
try {
// Check if last character is a '.' and second-last char of type alpha
if (last_str.at(last) == '.' && ::isalpha(last_str.at(last - 1))) {
YY_SCANNER.ptr_matcher()->unput(last_str[last]);
YY_SCANNER.ptr_matcher()->less(last); // similar to YYless
}
} catch(const std::out_of_range& e) {
// we keep silent
}
這是工作到目前爲止,但我認爲這不是很優雅和容易出錯。
所以我的基本問題是,如果我能以某種方式調整urlpath模式,以便最後的.
不被視爲URL路徑的一部分?我知道http://www.domain.tld/foo/bar/.
是有效的,但是http://www.domain.tld/foo/bar.
不是。
也許有一個簡單的解決方案。歡迎任何建議。謝謝你的努力!
我不是100%確定,但是你能否確定'.'出現在行('$')的結尾處?或者至少之後是另一個空格。 –
@πάνταῖεῖ好點,但afaik'''會標記整個詞法分析器輸入流的結束,所以如果該句子片段位於字符串中間的某個位置,將不會有任何效果。也許點/空白組合可能有效,但認爲這是一個相當不穩定的解決方案。 –