无法匹配 Alex 语法中的单个字符
我终于重新充实了一个 GitCommit 消息模式,我想将其添加到 YI 中,但我似乎缺少一些基本的东西。我似乎无法匹配语法中的单个字符,我的所有规则只有在匹配整行时才有效。我知道这必须是可能的,因为 YI 中的其他语法显然会这样做,但做同样的事情似乎不起作用。
我想要一种最终看起来与 vim 中的提交模式非常相似的提交模式。在 vim 模式中有用的事情之一是注释内的关键字突出显示。 Git 在它所做的几乎所有事情(提交、变基等)中都会在注释中放入大量信息,因此这很有用。我的想法是匹配 git 注释中的起始“#”字符,并切换到与关键字匹配的不同上下文。但是,我似乎无法制定仅匹配“#”的规则,该规则在“仅”包含“#”但在行上切换为注释样式包含“#”之后的任何内容,它不会切换样式。
我现在拥有的是:
<0> {
\# { m (const $ LineComment) Style.commentStyle }
$commitChars*$ { c Style.defaultStyle }
}
<lineComment> {
$nl { m (const Digest) Style.defaultStyle }
· { c Style.regexStyle }
}
细节明显省略。这个想法是当我们看到“#”时切换到“lineComment”模式,并以不同的方式设置样式,直到看到行尾。根据文档和示例,应该有一种方法可以做到我想要的。我已经尝试了几乎所有我能想到的“#”模式排列,但没有任何改变我所看到的行为。
我错过了什么明显的事情?
编辑: 上面的代码来自我的YI分支内部的实现。我有一个独立的解析器,此处也出现同样的问题。如果您运行 alex GitCommit.x && ghc --make GitCommit.hs && ./GitCommit < Shortmsg 您将看到内容解析为 MessageLine
的注释行以及正确标记为 CommentStart
的空注释行。
I finally got back to fleshing out a GitCommit message mode that I want to add to YI but I seem to missing something basic. I can't seem to match a single character in a grammar, all my rules only work if they match the entire line. I know this has to be possible because other grammars in YI obviously do this but doing the same thing doesn't seem to work.
I want to have a commit mode that eventually looks very similar to the one in vim. One of the things that's useful in vim's mode is the keyword highlighting inside comments. Git puts a bunch of information inside comments in most everything it does (commit, rebase, etc.) so this is useful. My thinking was match the starting '#' character in git comments and switch to a different context that will match keywords. However I can't seem to make a rule that matches just the '#', the rule switches to comment style on lines that only contain a '#' but on lines that contain anything after the '#' it does not switch styles.
What I have right now is:
<0> {
\# { m (const $ LineComment) Style.commentStyle }
$commitChars*$ { c Style.defaultStyle }
}
<lineComment> {
$nl { m (const Digest) Style.defaultStyle }
· { c Style.regexStyle }
}
Details omitted obviously. The idea is to switch to 'lineComment' mode when we see a '#' and style things differently until we see the end of the line. According to the documentation and examples there should be a way to do what I want. I've tried pretty much every permutation I can think of for the '#' pattern but nothing changes the behavior I'm seeing.
What obvious thing am I missing?
Edit:
The above code is from the implementation inside my YI branch. I have a standalone parser that exhibits the same problem here. If you run alex GitCommit.x && ghc --make GitCommit.hs && ./GitCommit < shortmsg
you will see comment lines with content parsed as MessageLine
and empty comment lines correctly marked CommentStart
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我终于明白了。看起来 Alex 总是选择最长的比赛,而不是第一场比赛。匹配提交行的规则总是会更长,因为它匹配整行。这会导致 Alex 始终选择该分支而不是评论分支。引用 Alex 文档
当输入流匹配多个规则时,匹配输入流最长前缀的规则获胜。如果仍有多个规则匹配相同数量的字符,则文件中最早出现的规则获胜。
我想我应该不止一次地阅读这些文档。解决方案是从
$commitChars
字符集中删除“#”。Okay I finally figured this out. It looks like Alex always takes the longest match, not the first match. The rule for matching commit lines will always be longer since it matches the whole line. This causes Alex to always choose that branch over the comment branch. Quoting from the Alex docs
When the input stream matches more than one rule, the rule which matches the longest prefix of the input stream wins. If there are still several rules which match an equal number of characters, then the rule which appears earliest in the file wins.
I guess I should have read the docs more than once. The solution is to remove the '#' from the
$commitChars
character set.