编写Superpower解析器的第一步是弄清楚令牌种类。你可以像这样:
enum EclToken {
LParen,
RParen,
UpKeyword,
DownKeyword,
WaitKeyword,
AtSymbol,
Number,
Comma
}
第二步,编写一个 Tokenizer<EclToken>
。这是由Superpower v1直接编程任务-没有太多可依靠的帮手,您只需要像示例中一样编写代码。
该分词器将输入字符串剥离空格,并确定令牌序列是什么。
对于您的示例输入,第一行将是:
// (UP 100),
LParen, UpKeyword, Number, RParen, Comma
对于像
Number
这样包含内容的标记,与
Result<EclToken>
相关联的跨度将指向对应于该标记的输入字符串部分。在这行代码中,数字将是一个
TextSpan
,覆盖
100
。
第三步是确定您要将输入解析为什么。对于具有嵌套表达式的编程语言,通常是AST。在ECL示例的情况下,它非常简单,因此您可能会将其缩减为:
struct ElevatorCommand {
public int Distance;
public bool IsRelative;
}
步骤 4,解析器。通常嵌入静态类中。解析器的工作是从简单结果(数字,移动)构建更复杂的结果(这里是ElevatorCommand[]
)。
这就是Superpower发挥作用的地方,特别是在期望和错误方面。
static class EclParser
{
static TokenListParser<EclToken, int> Number =
Token.EqualTo(EclToken.Number).Apply(Numerics.IntegerInt32);
}
我们要做的第一件事是定义数字解析器;这个解析器将内置的TextParser<int>
应用于EclToken.Number
区域的内容。
您可以在这个示例中看到更多的解析机制。
还有一些提示,以帮助您找到正确的方法(未经过语法检查,更不用说编译/测试了):
static TokenListParser<EclToken, ElevatorCommand> Up =
from _ in Token.EqualTo(EclToken.UpKeyword)
from distance in Number
select new ElevatorCommand {
Distance = distance,
IsRelative = false
};
static TokenListParser<EclToken, ElevatorCommand> Command =
from lp in Token.EqualTo(EclToken.LParen)
from command in Up
from rp in Token.EqualTo(EclToken.RParen)
select command;
static TokenListParser<EclToken, ElevatorCommand[]> Commands =
Command.ManyDelimitedBy(Token.EqualTo(EclToken.Comma));
}
Commands
是一个完成的解析器,可以应用到输入中。
最好逐步构建解析器,在预期解析的输入块上测试每个较小的解析器。