Parsing 识别行尾空白的上下文无关语法
我正在尝试编写一个上下文无关语法来做一些非常简单的事情,将一个字符串解析成一个交替的部分列表,这些部分包括(1)行尾空格和(2)其他所有内容。例如:Parsing 识别行尾空白的上下文无关语法,parsing,context-free-grammar,Parsing,Context Free Grammar,我正在尝试编写一个上下文无关语法来做一些非常简单的事情,将一个字符串解析成一个交替的部分列表,这些部分包括(1)行尾空格和(2)其他所有内容。例如: This.first.line...\n..and.this....second.line\n.\n..and.final.line (将“显示为”,并将换行符显示为“\n”,以确保可读性)解析为 "This.first.line", "...\n..", "and.this....second.line", "\n.\n..", "and.fi
This.first.line...\n..and.this....second.line\n.\n..and.final.line
(将“
显示为”
,并将换行符显示为“\n”
,以确保可读性)解析为
"This.first.line", "...\n..", "and.this....second.line", "\n.\n..", "and.final.line"
我写了以下语法:
string = raw_start | newline_start
raw_start = raw_section [newline_start]
newline_start = newline_section [raw_start]
raw_section = {any_character_except_newline}
newline_section = {whitespace_except_newline} new_line {any_whitespace_character}
但这是不正确的,因为{any_character_,除了新行以外}
将占用新行前面的空格,而我希望这些空格包含在新行部分中
可以说“使用空格,除非它们正好在换行符之前”而不丢失语法的上下文无关属性吗?当然,上下文无关不是问题。“行尾空白”和“其他所有内容”都是常规语言
以下是正则表达式(形式上是正则的,不能“通过某些“regex”包识别”)。我们假设A
是字母表,并定义:
NOTSPACE = { ∀x | x ∈ A ∧ x ≠ NL ∧ x ≠ SPACE }
NOTEOL = { ∀x | x ∈ A ∧ x ≠ NL }
EVERYTHING_ELSE = { xωy | x,y ∈ NOTSPACE ∧ ω ∈ NOTEOL* } ⋃ NOTSPACE
EOL_WHITESPACE = { ωNLγ | ω,γ ∈ {SPACE, NL}* }
如前所述,上述内容不明确,因为它并不坚持Other
和EOL_WS
的最大长度。这很容易解决,但很乏味,因为OP只要求一个CFG,而不是一个明确的或LR(1)CFG,我就不说了。这是将rici的伟大答案翻译成我在问题中使用的EBNF格式:
string = raw_start | newline_start
raw_start = raw_section [newline_start]
newline_start = newline_section [raw_start]
raw_section = any_nonwhite_character [{any_character_except_newline} any_nonwhite_character]
newline_section = {whitespace_except_newline} new_line {any_whitespace_character}
关键是更改raw_部分的定义,要求它以非白色字符结尾。这个简单的语法不会匹配空字符串或以空格结尾的字符串,但这很容易修复。对我来说,理解的关键是行everythings={xωy | x,y∈ 无空间∧ ω ∈ 注意*}
,并且意识到我必须要求原始部分的最后一个字符是非空白字符。@drhagen:Cool。修复了下线空白定义中的错误。事实上,在这个规则中,ω可以是简单的空间*
,但除非你关心歧义,否则它没有什么区别。还修复了Other
中的错误(我没有留下它只是一个非空白字符的可能性)。所有这些都表明了实际测试语法的重要性,在本例中我还没有这样做:(
string = raw_start | newline_start
raw_start = raw_section [newline_start]
newline_start = newline_section [raw_start]
raw_section = any_nonwhite_character [{any_character_except_newline} any_nonwhite_character]
newline_section = {whitespace_except_newline} new_line {any_whitespace_character}