gpt4 book ai didi

parsing - 如何处理 EBNF 语法中不同标记中的重叠字符组?

转载 作者:行者123 更新时间:2023-12-02 08:58:28 24 4
gpt4 key购买 nike

我正在使用 LL(k) EBNF 语法来解析字符流。我需要三种不同类型的 token :

CHARACTERS

letter = 'A'..'Z' + 'a'..'z' .
digit = "0123456789" .
messageChar = '\u0020'..'\u007e' - ' ' - '(' - ')' .

TOKENS

num = ['-'] digit { digit } [ '.' digit { digit } ] .
ident = letter { letter | digit | '_' } .
message = messageChar { messageChar } .

前两个 token 声明很好,因为它们不共享任何公共(public)字符。

但是,第三个 message 无效,因为某些字符串可能既是 num 又是 message(例如 “123”),其他字符串可以是 identmessage(例如 “Hello”)。因此,分词器无法正确区分。

另一个例子是区分整数和实数。除非您要求所有实数至少有一位小数(意味着 1 需要编码为 1.0,这对我来说不是一个选项),否则我无法在语法中获得这两个数字之间差异的支持类型。我必须将所有值都表示为实数,并在该点之后进行检查。这很好,但不是最优的。我真正的问题是 message token 。我找不到解决方法。

所以问题是,我可以使用 LL(k) EBNF 语法来做到这一点吗?我正在使用 CoCo/R 生成解析器和扫描器。

如果我无法使用 LL(k) EBNF 做到这一点,那么我还可以考虑哪些其他选项?

编辑这是我从 CoCo/R 得到的输出:

Coco/R (Apr 23, 2010)Tokens double and message cannot be distinguishedTokens ident and message cannot be distinguished...9 errors detected

最佳答案

试试这个:

CHARACTERS

letter = 'A'..'Z' + 'a'..'z' .
digit = "0123456789" .
messageChar = '\u0020'..'\u007e' - ' ' - '(' - ')' .

TOKENS

double = ['-'] digit { digit } [ '.' digit { digit } ] .
ident = letter { letter | digit | '_' } .
message = messageChar { messageChar } CONTEXT (")") .

哦,我必须指出 '\u0020' 是 unicode SPACE,您随后将用“- ' '”将其删除。哦,如果您不需要多个字符前瞻,您可以使用 CONTEXT (')')。这在您的情况下不起作用,因为上面的所有标记都可以出现在 ')' 之前。

FWIW:CONTEXT 不会使用所包含的序列,您仍然必须在生产中使用它。

编辑:

好的,这似乎有效。真的,这次我是认真的:)

CHARACTERS
letter = 'A'..'Z' + 'a'..'z' .
digit = "0123456789" .
// messageChar = '\u0020'..'\u007e' - ' ' - '(' - ')' .

TOKENS

double = ['-'] digit { digit } [ '.' digit { digit } ] .
ident = letter { letter | digit | '_' } .
// message = letter { messageChar } CONTEXT (')') .

// MessageText<out string m> = message (. m = t.val; .)
// .

HearExpr<out HeardMessage message> =
(.
TimeSpan time;
Angle direction = Angle.NaN;
string messageText = "";
.)
"(hear"
TimeSpan<out time>
( "self" | AngleInDegrees<out direction> )
// MessageText<out messageText>
{
ANY (. messageText += t.val; .)
}
')'
(.
message = new HeardMessage(time, direction, new Message(messageText));
.)
.

ANY 将读取字符,直到遇到“)”或空格。我将它放在一个连接每个值的循环中,但您可能不想这样做。不过,您可能希望将其放入循环中,这样当它看到“over here”时,它不会返回“over”,而是返回“here”。您可以对 messageText 进行简单的长度检查,或进行其他有效性检查,例如将 t.val 添加到列表并检查计数。真的什么都可以。您还可以使用正则表达式进行测试,以确保它符合您需要检查的任何模式。

编辑(2011 年 4 月 8 日):使用 Coco/R 与整数和实数的示例

COMPILER Calculator
CHARACTERS
digit = "0123456789".

TOKENS
intNumber = ['-'] digit { digit } .
realNumber = ['-'] { digit } "." digit { digit }
[("e" | "E") ["+" | "-"] digit {digit}] .

PRODUCTIONS
Calculator = { Expression "=" } .
Expression = Term { "+" Term | "-" Term }.
Term = Factor { "*" Factor | "/" Factor }.
Factor = intNumber | realNumber .

END Calculator.

编辑(2011 年 4 月 9 日)

Factor<out double value>
(. value = 0.0; .)
=
(
intNumber
(. value = Convert.ToDouble(t.val); .)
|
realNumber
(. value = Convert.ToDouble(t.val); .)
)
| "(" Expression<out value> ")"
.

Factor<out double value>
(. value = 0.0; .)
=
( intNumber | realNumber )
(. value = Convert.ToDouble(t.val); .)
| "(" Expression<out value> ")"
.

关于parsing - 如何处理 EBNF 语法中不同标记中的重叠字符组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3046085/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com