跳转到内容

Raku 编程/语法

来自维基教科书,开放世界中的开放书籍

正则表达式本身很有用,但有限制。重用正则表达式可能很困难,将它们分组到逻辑块中也很困难,并且从一个块继承正则表达式非常困难。这就是语法发挥作用的地方。语法与正则表达式之间的关系,就像类与数据和代码例程之间的关系。语法允许正则表达式像编程语言的普通一等公民一样行事,并利用类系统的强大功能。语法可以像类一样继承和重载。事实上,Raku 语法本身可以被修改,以便在运行时向语言添加新功能。我们将在后面看到这些示例。

规则、标记和原型

[编辑 | 编辑源代码]

语法被分解为称为规则标记原型的组件。标记就像我们已经见过的正则表达式。规则就像子例程,因为它们可以调用其他规则或标记。原型就像默认的多子例程,它们定义了一个可以被覆盖的规则原型。

标记是不回溯的正则表达式,这意味着如果表达式的一部分已匹配,则即使它阻止表达式更大的一部分匹配,这部分也不会被改变。虽然这牺牲了正则表达式的一些灵活性,但它允许以更高效的方式创建更复杂的解析器。

token number {
  \d+ ['.' \d+]?
}

规则是将标记和其他规则组合在一起的方式。所有规则都将被赋予名称,并且可以使用< > 尖括号引用同一语法中的其他规则或标记。与标记一样,它们也不回溯,但它们内部的空格将按字面解释,而不是被忽略。

rule URL {
  <protocol>'://'<address>
}

此规则匹配一个 URL 字符串,其中包含像 "ftp" 或 "https" 这样的协议名称,后面跟着文字符号 "://",然后是一个表示地址的字符串。此规则依赖于两个子规则,<protocol><address>。它们可以定义为标记或规则,只要它们在同一个语法中。

grammar URL {
  rule TOP {
    <protocol>'://'<address>
  }
  token protocol {
    'http'|'https'|'ftp'|'file'
  }
  rule address {
    <subdomain>'.'<domain>'.'<tld>
  }
  ...
}

原型定义了一种规则或标记类型。例如,我们可以定义一个原型标记 <protocol>,然后定义几个表示不同协议的标记。在一个标记中,我们可以将它的名称引用为 <sym>

grammar URL {
  rule TOP {
    <protocol>'://'<address>
  }
  proto token protocol {*}

  token protocol:sym<http> {
    <sym>
  }
  token protocol:sym<https> {
    <sym>
  }
  token protocol:sym<ftp> {
    <sym>
  }
  token protocol:sym<ftps> {
    <sym>
  }
  ...
}

这相当于说

token protocol {
  <http> | <https> | <ftp> | <ftps>
}
token http {
  http
}
...

但是更具可扩展性,允许以后指定协议类型。例如,如果我们想定义一种新的 URL 类型,它也支持 "spdy" 协议,我们可以使用

grammar URL::WithSPDY is URL {
  token protocol:sym<spdy> {
    <sym>
  }
}

匹配语法

[编辑 | 编辑源代码]

一旦我们拥有了上面定义的语法,我们就可以使用 .parse 方法来匹配它

my Str $mystring = "http://www.wikibooks.org";

if URL.parse($mystring) {
  #if it matches a URL, do something
}

匹配对象

[编辑 | 编辑源代码]

匹配对象是一种特殊的 数据类型,它表示语法的解析状态。当前的匹配对象存储在特殊变量 $/ 中。

解析器操作

[编辑 | 编辑源代码]

通过将语法与解析器操作类组合,可以将语法转换为交互式解析器。当语法匹配某些规则时,可以使用当前匹配对象调用相应的操作方法。

华夏公益教科书