如何在Kotlin中正确编写此正则表达式以在Pascal中测试代码

如何在Kotlin中正确编写此正则表达式以在Pascal中测试代码,kotlin,Kotlin,我试着这样做,但不是很正确的解决方案,因为如果删除分号,它仍然是true,但应该是false 这是作业: 检查for语句的正确性,其中 非整数值​​可以是整数或符号,循环体是write(ln)运算符,其参数是整数和符号 实数和变量 要检查的Pascal代码示例: for i:=1 to n do write(0); 我尝试在Kotlin上实现此正则表达式: fun main(){ val regex = Regex(pattern = """

我试着这样做,但不是很正确的解决方案,因为如果删除分号,它仍然是true,但应该是false

这是作业: 检查for语句的正确性,其中 非整数值​​可以是整数或符号,循环体是write(ln)运算符,其参数是整数和符号 实数和变量

要检查的Pascal代码示例:

for i:=1 to n do
  write(0);

我尝试在Kotlin上实现此正则表达式:

fun main(){
        val regex = Regex(pattern = """for\s\w:=\d|\w\sto\s\w|\d\sdo\nwrite(\w|\d);|writeln(\w|\d);""")
        val matched = regex.containsMatchIn(input = "for i:=1 to n do\n write(n);")
        if(matched) println("True")
        else println("False")}
    

首先:Regex通常不足以检查上下文无关语言。因此,不能使用正则表达式检查任意pascal源代码的语法。对于您的简短示例,这可能是可能的,但是您的正则表达式存在许多问题

  • 是正则表达式语法(分组)的一部分。因此,如果您想让字符串字面上包含
    ,您必须像
    \(
    \)那样对它们进行转义

  • 你的选择没有明确说明。因此,例如,
    for\s\w:=\d |\w\s…
    将匹配
    之前或之后的任何内容。使用分组来精确指定备选方案<代码>对于\s\w:=(\d |\w)\sto

  • 变量名称或数字的所有匹配项仅匹配一个字符。所以像i:=1到10的
    这样的东西将不匹配。使用
    \d+
    \w+
    也可以匹配多位数/更长的变量名

  • 同样适用于空格
    \s
    您的正则表达式始终只需要一个空格。原始示例中的缩进将不匹配

  • \d
    (所有数字)是
    \w
    (所有单词字符,a-zA-Z0-9)的子集,因此
    \d\w
    可以是
    \w
    。但在pascal中,变量名不能以数字开头,因此必须执行
    (\d+|[a-z]\w*)
    ,即数字或以字符开头的变量名

  • 你根本不考虑实数(1.23)。因此,您没有使用
    \d+
    而是使用类似
    \d+(\.\d+?
    (仍然完全忽略了这一点。3或2.3e4也是有效的实数)

  • 您可以通过
    write(ln)?

所以把这些放在一起,你的正则表达式可能看起来像这样

val regex = Regex(pattern = """for\s+[a-z]\w*\s*:=\s*(\d+|[a-z]\w*)\s+to\s+(\d+|[a-z]\w*)\s+do\s*(\n|\s)\s*write(ln)?\((\d+(\.\d+)?|[a-z]\w*)\);""")

该行输出false,尽管它应该输出true“i=‘1’到‘n’do\n写(n,7.54,-6,7e7);”@ RoxasHekka,为什么你会考虑<代码>为i:=‘1’到‘n’…< /代码>有效的Pascal语法?这些引语来自哪里?如上所述,此正则表达式不包括
7e7
为有效双倍数的情况。为什么在write语句中有多个参数?这一点在最初的问题中也没有具体说明…@derpirsher事实上我并不完全了解被检查代码的准确性,那天我被展示了被检查代码的外观like@derpirsher任务本身听起来是这样的:使用实现正则表达式的函数,根据您的选择(本工作中的选项编号与之前的不同),开发一个程序,用于检查用Pascal(古典方言)编写的片段的语法正确性。检查for语句的正确性,其中初始值和非整数值​​可以是整数或符号,循环的主体是write(ln)操作符,其参数是整数、实数和变量。