根据this教程,我正在制作一个自定义语言支持插件,并且我被一些.bnf概念所困。假设我想解析一种简单的计算器语言,它支持+、-、*、/、一元-和括号。这是我目前所拥有的:
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:
{
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;首先,它抱怨expr是递归的。我如何重写它使其不是递归的?其次,当我试图编译和运行它时,它冻结了idea测试实例,当我试图解析这个语法时,看起来像是一个无尽的循环。
发布于 2019-05-17 04:26:59
将语法文件称为"BNF“有点误导,因为它们实际上是修改过的PEG (解析表达式语法)格式,这允许某些扩展运算符,包括分组、重复和可选性,以及有序选择(这在语义上与|的常规定义不同)。
由于底层技术是PEG,因此不能使用左递归规则。除非代码生成器拒绝生成左递归代码,否则左递归将在解析器中导致无限循环。幸运的是,重复运算符是可用的,所以您只需要对包含括号的语法进行递归,而这不是左递归,所以它不会出现问题。
据我所知,我找到的文档中,语法工具包没有提供运算符优先声明。如果您确实需要生成正确的解析,并且考虑到运算符的优先级,则需要使用多个优先级。但是,如果您唯一的用例是语法突出显示,则可能不需要精确的解析,只需执行以下操作就足够了:
expr ::= unary (('+' | '-' | '*' | '/') unary)*
unary ::= '-'* ( '(' expr ')' | literal )(为了精确解析,您需要将上面的expr分成两个优先级,一个用于加法运算符,另一个用于乘法运算符。但我建议不要这样做,除非您打算将解析用于计算或代码生成。)
此外,您几乎肯定需要一些词法规则来识别各种运算符字符并返回适当的单字符标记。
https://stackoverflow.com/questions/56174323
复制相似问题