https://lalrpop.github.io/lalrpop/tutorial/003_type_inference.html
OK, now that we understand the calculator1 example, let's look at some of the shorthands that LALRPOP offers to make it more concise. This code is found in the calculator2 demo.
GPT --- 好的,现在我们理解了
calculator1
示例,让我们看看 LALRPOP 提供的一些简写方式,以使代码更加简洁。这些代码可以在calculator2
示例中找到。
MST --- 好了,现在我们已经理解了 calculator1 示例,让我们看看 LALRPOP 提供的一些简写,以使其更简洁。此代码位于 calculator2 演示中。
To start, let's look at the definition of Term we saw before:
pub Term: i32 = {
<n:Num> => n,
"(" <t:Term> ")" => t,
};
The action code here is somewhat interesting. In both cases, it's not doing any new work, it's just selecting a value that was produced by another nonterminal. This turns out to be pretty common. So common, in fact, that LALRPOP offers some shorthand notation for it. Here is the definition of Term from the calculator2 demo:
GPT --- 这里的动作代码有些有趣。在这两种情况下,它并没有做任何新的工作,只是选择了由另一个非终结符生成的值。这实际上是非常常见的。所以,LALRPOP 提供了一些简写方式来处理这种情况。以下是
calculator2
示例中Term
的定义:
MST --- 这里的操作代码有点有趣。在这两种情况下,它都没有做任何新工作,它只是选择由另一个非终端生成的值。事实证明这很常见。事实上,LALRPOP 为它提供了一些速记符号。以下是 calculator2 演示中 Term 的定义:
pub Term = { Num, "(" <Term> ")" };
Here, we have no action code at all. If there is no action code, LALRPOP synthesizes action code which just takes the value of the things being matched. In the case of the first alternative, Num, there is only one thing being matched, so that means that Term will produce the same value as the Num we parsed, whatever that was.
GPT --- 在这里,我们没有任何动作代码。如果没有动作代码,LALRPOP 会自动生成动作代码,默认情况下它会直接使用匹配到的值。在第一个替代定义
Num
的情况下,只有一个匹配项,这意味着Term
将生成与我们解析的Num
相同的值,无论那个值是什么。
MST --- 在这里,我们根本没有操作代码。如果没有操作代码,LALRPOP 会合成操作代码,该代码只接受被匹配内容的值。在第一个选项的情况下,Num 只有一个东西被匹配,所以这意味着 Term 将产生与我们解析的 Num 相同的值,无论它是什么。
In the case of the second alternative, "("
GPT --- 在第二个替代定义
("(" <Term> ")")
的情况下,匹配了三个项。在这里,我们使用尖括号来选择我们想要取值的项——我们只选择了一个,所以结果就是我们解析的Term
的值。如果我们选择了多个项,结果将是一个包含所有选中项的元组。如果我们没有选择任何项(即("(" Term ")")
),结果将是所有项的元组,因此结果的类型将是(&'input str, i32, &'input str)
。
MST --- 在第二个选项“(”
“)”的情况下,有三个东西被匹配。在这里,我们使用尖括号来选择要获取值---我们只选择一个项目的值,因此结果是我们获取我们解析的 Term 的值。如果我们选择了多个,结果将是所有选定项目的元组。如果我们没有选择任何(即“(” Term “)”),结果将是所有项目的元组,因此结果将是 (&'input str, i32, &'input str) 类型。
Speaking of types, you may have noticed that Term has no type annotation. Since we didn't write out own action code, we can omit the type annotation and let LALRPOP infer it for us. In this case, LALRPOP can see that Term must have the same type as Num, and hence that the type must be i32.
GPT --- 说到类型,你可能已经注意到
Term
没有类型注解。由于我们没有编写自己的动作代码,我们可以省略类型注解,让 LALRPOP 为我们推断类型。在这种情况下,LALRPOP 可以看出Term
必须与Num
具有相同的类型,因此类型必须是i32
。
MST --- 说到类型,你可能已经注意到 Term 没有类型注释。由于我们没有写出自己的 action 代码,我们可以省略类型注释,让 LALRPOP 为我们推断它。在这种情况下,LALRPOP 可以看到 Term 必须与 Num 具有相同的类型,因此类型必须为 i32。
OK, let's look at the definition of Num we saw before from calculator1:
Num: i32 = <s:r"[0-9]+"> => i32::from_str(s).unwrap();
This definition too can be made somewhat shorter. In calculator2, you will find:
Num: i32 = r"[0-9]+" => i32::from_str(<>).unwrap();
Here, instead of giving the regular expression a name s, we modified the action code to use the funky expression <>. This is a shorthand that says "synthesize names for the matched values and insert a comma-separated list here". In this case, there is only one matched value, r"[0-9]+", and it produces a &'input str, so LALRPOP will insert a synthetic variable for that value. Note that we still have custom action code, so we still need a type annotation.
GPT --- 在这里,我们没有给正则表达式命名为
s
,而是修改了动作代码,使用了特殊的表达式<>
。这是一个简写方式,表示“为匹配到的值生成名称,并在这里插入一个以逗号分隔的列表”。在这种情况下,只有一个匹配值r"[0-9]+"
,它会生成一个&'input str
,因此 LALRPOP 会为该值插入一个合成变量。注意,我们仍然有自定义的动作代码,所以我们仍然需要类型注解。
MST --- 在这里,我们没有给正则表达式命名 s,而是修改了操作代码以使用 funky 表达式 <>。这是一个简写,表示 “synthesize names for the matched values and insert a comma-separated list here” 。在这种情况下,只有一个匹配的值 r“[0-9]+”,并且它会生成一个 &'input str,因此 LALRPOP 将为该值插入一个合成变量。请注意,我们仍然有自定义操作代码,因此我们仍然需要一个类型注释。
To control what values are selected when you use the <> expression in your action code, you can use angle brackets as we saw before. Here are some examples of alternatives and how they are expanded to give you the idea:
GPT --- 为了控制在动作代码中使用
<>
表达式时选择哪些值,你可以像之前看到的那样使用尖括号。以下是一些替代定义的示例,以及它们如何展开的,目的是帮助你理解:
MST --- 要控制在操作代码中使用 <> 表达式时选择的值,可以使用尖括号,如前所述。以下是一些替代方案的示例,以及如何扩展它们以为您提供想法:
Alternative | Equivalent to |
---|---|
A => bar(<>) | <a:A> => bar(a) |
A B => bar(<>) | <a:A> <b:B> => bar(a, b) |
A B => (<>) | <a:A> <b:B> => (a, b) |
B => bar(<>) | <a:A> B => bar(a) |
<p:A> B => bar(<>) | <p:A> B => bar(p) |
=> bar(<>) | <a:A> <b:B> => bar(a, b) |
<p:A> <q:B> => bar(<>) | <p:A> <q:B> => bar(p, q) |
<p:A> B => Foo | <p:A> B => Foo |
<p:A> <q:B> => Foo | <p:A> <q:B> => Foo |
The <> expressions also works with struct constructors (like Foo {...} in examples above). This works out well if the names of your parsed values match the names of your struct fields.
GPT ---
<>
表达式也可以与结构体构造函数一起使用(例如上面示例中的Foo {...}
)。如果你解析的值的名称与结构体字段的名称匹配,这样的用法会非常方便。
标签:Term,5.3,inference,代码,---,LALRPOP,bar,Num,Type From: https://www.cnblogs.com/Tifahfyf/p/18653172MST --- <>表达式也适用于结构体构造函数(如上面示例中的 Foo {...})。如果解析的值的名称与 struct 字段的名称匹配,则效果很好。