2017-03-27 32 views
1

我学习做一个编译器,它有一个像一个字符串的一些规则:什么是多字符串的正则表达式?

char ch[] ="abcd"; 

和多串:

printf("This is\ 
a multi\ 
string"); 

我写的正则表达式

STRING \"([^\"\n]|\\{NEWLINE})*\" 

它的工作原理单线字符串很好,但它不适用于多行字符串,其中一行以'\'字符结尾。 我应该改变什么?

+0

为什么使用定义'{NEWLINE}'(其值不显示)而不是更易读的'\ n'?它使你的代码难以阅读,而且你的问题很难回答,因为它很可能与不必要的定义中的错误有关。另外,你不需要在字符类('[[...]')内跳过引号。 – rici

+0

此前,在我的代码中,我编写了NEWLINE \ n规则。所以,无论我需要什么\ n,我都写了NEWLINE,并且是的,我不需要在字符类中逃避引号。 – sphoenix

+0

您如何编写代码当然是您的决定。但是如果你使用一个定义,那么你需要将它包含在你的问题中;否则我们怎么能知道真正的定义是什么?问题代码应该是独立的。如果定义是正确的,那么正则表达式也是如此,并且问题可能与输入中的尾随空格有关。或者你的规则中的其他地方,尽管这会有点奇怪。提供[mcve]总是更好。 – rici

回答

0

一个常见的字符串模式是

\"([^"\\\n]|\\(.|\n))*\" 

这将匹配其中包括转义双引号(\")和反斜杠(\\)字符串。它使用\\(.|\n)来允许反斜杠后的任何字符。尽管一些反斜杠序列长于一个字符(\x40),但它们都不包含第一个字符后面的非字母数字。

您的输入可能包含Windows行尾(CR-LF),在这种情况下,反斜杠不会紧跟换行符;它会跟着一个回车。如果你想接受输入,而不是抛出一个错误(这可能是更合适),你需要明确这样做:

\"([^"\\\n]|\\(.|\r?\n))*\" 

但识别字符串,并了解该字符串代表是两回事。通常情况下,编译器需要将字符串的表示形式转换为字节序列,例如,需要将\n转换为字节10并全部删除反斜杠的换行符。

使用启动条件,可以在(f)lex扫描仪中轻松完成该任务。 (或者,当然,您可以使用不同的词法扫描仪重新扫描字符串。)

此外,您需要考虑错误处理。一旦你禁止带有非转义换行符的字符串(就像C一样),你就可以打开一扇未结束字符串的大门,在结束引号之前遇到一个换行符。如果字符串未正确关闭,则文件末尾可能会发生同样的情况。

如果您有单字符回退规则,它将识别未终止字符串的开始引号。这是不可取的,因为它会将字符串的内容扫描为导致错误级联的程序文本。如果你没有尝试错误恢复,那并不重要,但是如果你是这样的话,通常最好至少用新模式识别未结束的字符串,直到换行符为止。

+0

printf(“abc \ def \ ghi”); 此输入正确的输出将是 令牌词位的printf发现 令牌词位(发现 令牌词位 “ABC \ 高清\ GHI” 发现 但你的表达它产生 TOKEN 词位的printf发现 TOKEN 词位(发现 TOKEN 词位ABC发现 TOKEN 词位DEF发现 TOKEN 词位GHI发现 – sphoenix

+0

为未终止的字符串\ “([^”] | \\)*能正常工作 – sphoenix

+0

@sphoenix:如果这就是你所得到的,那么你的测试工具有问题,因为双引号正在消失。 – rici

相关问题