简体   繁体   English

如何为IntelliJ制作简单的计算器语法突出显示?

[英]How to make a simple calculator syntax highlighting for IntelliJ?

I'm making a custom language support plugin according to this tutorial and I'm stuck with a few .bnf concepts. 我根据教程制作了一个自定义语言支持插件,并且停留在一些.bnf概念上。 Let's say I want to parse a simple calculator language that supports +,-,*,/,unary -, and parentheses. 假设我想解析一种支持+,-,*,/,一元-和括号的简单计算器语言。 Here's what I currently have: 这是我目前拥有的:

Flex: 柔性:

package com.intellij.circom;

import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import com.intellij.circom.psi.CircomTypes;
import com.intellij.psi.TokenType;

%%

%class CircomLexer
%implements FlexLexer
%unicode
%function advance
%type IElementType
%eof{  return;
%eof}

WHITESPACE = [ \n\r\t]+
NUMBER = [0-9]+

%%

{WHITESPACE}    { return TokenType.WHITE_SPACE; }
{NUMBER}        { return CircomTypes.NUMBER; }

Bnf: Bnf:

{
  parserClass="com.intellij.circom.parser.CircomParser"

  extends="com.intellij.extapi.psi.ASTWrapperPsiElement"

  psiClassPrefix="Circom"
  psiImplClassSuffix="Impl"
  psiPackage="com.intellij.circom.psi"
  psiImplPackage="com.intellij.circom.psi.impl"

  elementTypeHolderClass="com.intellij.circom.psi.CircomTypes"
  elementTypeClass="com.intellij.circom.psi.CircomElementType"
  tokenTypeClass="com.intellij.circom.psi.CircomTokenType"
}

expr ::=
   expr ('+' | '-') expr
  | expr ('*' | '/') expr
  | '-' expr
  | '(' expr ')'
  | literal;
literal ::= NUMBER;

First it complains that expr is recursive. 首先,它抱怨expr是递归的。 How do I rewrite it to not be recursive? 我如何重写它而不是递归的? Second, when I try to compile and run it, it freezes idea test instance when trying to parse this syntax, looks like an endless loop. 其次,当我尝试编译并运行它时,它在尝试解析此语法时冻结了想法测试实例,看起来就像是一个无休止的循环。

Calling the grammar files "BNF" is a bit misleading, since they are actually modified PEG (parsing expression grammar) format, which allows certain extended operators, including grouping, repetition and optionality, and ordered choice (which is semantically different from the regular definition of | ). 将语法文件称为“ BNF”有点误导,因为它们实际上是修改后的PEG(解析表达式语法)格式,该格式允许某些扩展运算符,包括分组,重复和可选性以及有序选择(在语义上与常规定义不同)的| )。

Since the underlying technology is PEG, you cannot use left-recursive rules. 由于基础技术是PEG,因此您不能使用左递归规则。 Left-recursion will cause an infinite loop in the parser, unless the code generator refuses to generate left-recursive code. 除非代码生成器拒绝生成左递归代码,否则左递归将在解析器中引起无限循环。 Fortunately, repetition operators are available so you only need recursion for syntax involving parentheses, and that's not left-recursion so it presents no problem. 幸运的是,可以使用重复运算符,因此您只需要对包含括号的语法进行递归操作,而无需进行左递归操作,因此不会出现任何问题。

As far as I can see from the documentation I found, grammar kit does not provide for operator precedence declarations. 据我从找到的文档中可以看到,语法工具包不提供运算符优先级声明。 If you really need to produce a correct parse taking operator-precedence into account, you'll need to use multiple precedence levels. 如果确实需要考虑运算符优先级来生成正确的解析,则需要使用多个优先级。 However, if your only use case is syntax highlighting, you probably do not require a precisely accurate parse, and it would be sufficient to do something like the following: 但是,如果您唯一的用例是语法高亮显示,则可能不需要精确准确的解析,那么执行以下操作就足够了:

expr  ::= unary (('+' | '-' | '*' | '/') unary)*
unary ::= '-'* ( '(' expr ')' | literal )

(For precise parsing, you'd need to split expr above into two precedence levels, one for additive operators and another for multiplicative. But I suggest not doing that unless you intend to use the parse for evaluation or code-generation.) (对于精确的解析,您需要将上述expr分为两个优先级,一个优先级用于加法运算符,另一个优先级用于乘法。但是我建议您不要这样做,除非您打算将解析用于评估或代码生成。)

Also, you almost certainly require some lexical rule to recognise the various operator characters and return appropriate single character tokens. 另外,几乎可以肯定,您需要一些词汇规则来识别各种运算符并返回适当的单字符标记。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM