我已阅读有关ABNF 规范的 RFC,并且很难理解如何使用一组 ABNF 规则从与语法匹配的某些输入字符串中可靠地提取标记。似乎该规范从未提及令牌或 AST,因此它可能不关心这一点,但我相信这将是应用任何 BNF 语法的最终目标,除非我弄错了。
在规范中,他们列出了解析邮政地址的示例规则:
postal-address = name-part street zip-part
name-part = *(personal-part SP) last-name [SP suffix] CRLF
name-part =/ personal-part CRLF
personal-part = first-name / (initial ".")
first-name = *ALPHA
initial = ALPHA
last-name = *ALPHA
suffix = ("Jr." / "Sr." / 1*("I" / "V" / "X"))
street = [apt SP] house-num SP street-name CRLF
apt = 1*4DIGIT
house-num = 1*8(DIGIT / ALPHA)
street-name = 1*VCHAR
zip-part = town-name "," SP state 1*2SP zip-code CRLF
town-name = 1*(ALPHA / SP)
state = 2ALPHA
zip-code = 5DIGIT ["-" 4DIGIT]
还有一个核心规则列表,我不会在此处发布描述预期的常用规则。
最终,我想做的是找出接受输入所需的规则
John H. Doe
12345 Fakestreet
Springfield, IL 55555
并生成我认为正确的令牌序列,即:
[ "John"
, " "
, "H"
, "."
, "Doe"
, "\r\n"
,
"12345"
, " "
, "Fakestreet"
, "\r\n"
,
"Springfield"
, ","
, " "
, "IL"
, " "
, "55555"
, "\r\n"
]
(我认为空格和 CRLF 需要作为“令牌”返回,因为它们在某些规则中被指定为要求)
我正在考虑的一些问题:
- “Fakestreet”应该是它自己的标记是有道理的,但根据定义,它是可见字符核心规则的可变重复。理想情况下,我不想将每个字母作为其自己的标记(“F”、“a”、“k”等)读出,因此(假设核心规则可以被视为终端?)任何潜在的标记字符串都会需要对照整个理论上无限的规则定义
1*VCHAR
来检查它是否匹配。有些规则比这更复杂,比如 zip-code's5DIGIT ["-" 4DIGIT]
,但是任何潜在的标记也需要根据这个规则进行检查(“12345”和“12345-6789”都是有效的标记)。所以似乎整个规则元素连接也需要完全检查,除非“12345-6789”"12345"
"-"
,"6789"
] 哪个...可能是正确的? - 我假设我们不想完全检查引用其他规则的规则,否则我们最终可能会将整个邮政地址标记为“邮政地址”类型的单个标记。也许不应该检查引用其他规则的规则?也许有诸如“终端规则”之类的东西,它不包括规则参考(不包括核心规则)?
- 偶尔在规则中,终端值与规则引用结合,例如在“personal-part”的定义中,即文字“.”。被定义为。因此,虽然我们可能不想将任何潜在的标记字符串与整个“个人部分”规则定义进行匹配,但似乎我们确实想尝试将其与文字“.”进行匹配。因为它是解析个人部分所需的令牌。也许在非终端规则中,应该考虑列出的终端值?
我意识到这是一个冗长的问题,但似乎 EBNF 和 ABNF 之类的 BNF 超集正在用于此类事情,但我找不到如何从 ABNF 语法进行标记的标准规范。