C# Antlr4语法问题(不完全解析)
我是ANTLR的新手,我正在努力让这个语法正常工作:C# Antlr4语法问题(不完全解析),c#,.net,parsing,antlr4,lexer,C#,.net,Parsing,Antlr4,Lexer,我是ANTLR的新手,我正在努力让这个语法正常工作: grammar TemplateGrammar; //Parser Rules start : block | statement | expression | parExpression | primary ; block : LBRACE statement* RBRACE ; statement : block | IF parExpression
grammar TemplateGrammar;
//Parser Rules
start
: block
| statement
| expression
| parExpression
| primary
;
block
: LBRACE statement* RBRACE
;
statement
: block
| IF parExpression statement (ELSE statement)?
| expression
;
parExpression
: LPAREN expression RPAREN
;
expression
: primary #PRIMARY
| number op=('*'|'/') number #MULDIV
| number op=('+'|'-') number #ADDSUB
| number op=('>='|'<='|'>'|'<') number #GRLWOREQUALS
| expression op=('='|'!=') expression #EQDIFF
;
primary
: parExpression
| literal
;
literal
: number #NumberLiteral
| string #StringLiteral
| columnName #ColumnNameLiteral
;
number
: DecimalIntegerLiteral #DecimalIntegerLiteral
| DecimalFloatingPointLiteral #FloatLiteral
;
string
: '"' StringChars? '"'
;
columnName
: '[' StringChars? ']'
;
// Lexer Rules
//Integers
DecimalIntegerLiteral
: DecimalNumeral
;
fragment
DecimalNumeral
: '0'
| NonZeroDigit (Digits? | Underscores Digits)
;
fragment
Digits
: Digit (DigitOrUnderscore* Digit)?
;
fragment
Digit
: '0'
| NonZeroDigit
;
fragment
NonZeroDigit
: [1-9]
;
fragment
DigitOrUnderscore
: Digit
| '_'
;
fragment
Underscores
: '_'+
;
//Floating point
DecimalFloatingPointLiteral
: Digits '.' Digits? ExponentPart?
| '.' Digits ExponentPart?
| Digits ExponentPart
| Digits
;
fragment
ExponentPart
: ExponentIndicator SignedInteger
;
fragment
ExponentIndicator
: [eE]
;
fragment
SignedInteger
: Sign? Digits
;
fragment
Sign
: [+-]
;
//Strings
StringChars
: StringChar+
;
fragment
StringChar
: ~["\\]
| EscapeSequence
;
fragment
EscapeSequence
: '\\' [btnfr"'\\]
;
//Separators
LPAREN : '(';
RPAREN : ')';
LBRACE : '{';
RBRACE : '}';
LBRACK : '[';
RBRACK : ']';
COMMA : ',';
DOT : '.';
//Keywords
IF : 'IF';
ELSE : 'ELSE';
THEN : 'THEN';
//Operators
PLUS : '+';
MINUS : '-';
MULTIPLY : '*';
DIVIDE : '/';
EQUALS : '=';
DIFFERENT : '!=';
GRTHAN : '>';
GROREQUALS : '>=';
LWTHAN : '<';
LWOREQUALS : '<=';
AND : '&';
OR : '|';
WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ -> skip ;
语法模板语法;
//解析器规则
开始
:块
|声明
|表情
|副表达
|初级的
;
块
:LBRACE语句*RBRACE
;
陈述
:块
|IF parExpression语句(ELSE语句)?
|表情
;
副表达
:LPAREN表达式RPAREN
;
表达
:primary#primary
|数字op=(“*”|“/”)数字#MULDIV
|数字op=(“+”|“-”)数字ADDSUB
|数字op=(“>=”|“|”跳过;
当我将
“Test”
放入输入时,它正在工作并返回字符串“Test”
。
以下是我在输入中放入
“Test”
时在IParseTree
中得到的结果:
“(start(语句(表达式(主(文本(字符串\“Test\”)))))))”
但是当我放置
[Test]
(它几乎与的“Test”
相同,但使用大括号而不是引号)时,解析器无法识别标记。。。
这是我放置
[Tree]
时得到的IParseTree
:
“(开始[测试])
与数字一样,它可以很好地识别诸如
1
、123
、12.5
等孤独的数字,但不能识别像1+2
这样的表达式
你知道为什么解析器不能识别列名
规则,但却能很好地处理字符串
规则吗?可能是因为“StringChar”的定义不正确,无法处理“]”
也许您希望将StringChar定义为:
fragment
StringChar
: ~["\\\]]
| EscapeSequence
;
如果这是我的语法,我会定义一个QuotedStringChar,就像您为引号字符串定义的那样,并将BracketStringChar定义为~[\]\\]以用于括号列名
欢迎在词汇级别调试语法,并为不同类型的字符串定义不同类型的“引号”。这非常常见。(您应该看到Ruby,可以在其中定义字符串开头的字符串引号,ick。)。我最终通过以下方式实现了这一功能:
QuotedStringChars
: '"' ~[\"]+ '"'
;
BracketStringChars
: '[' ~[\]]+ ']'
;
在引号或括号之间输入任何字符。然后:
primary
: literal #PrimLiteral
| number #PrimNumber
;
literal
: QuotedStringChars #OneString
| BracketStringChars #ColumnName
| number #NUMBER
;
number
: DecimalIntegerLiteral #DecimalIntegerLiteral
| DecimalFloatingPointLiteral #FloatLiteral
;
literal
规则有助于区分带引号的字符串、括号字符串和数字
在primary
和literal
规则中有一个重复的number
,因为我需要在应用程序中为每个规则指定不同的行为
我在Ira Baxter的建议下成功地做到了这一点:)
希望这将帮助其他新手像我一样有一个更好的ANTLR
理解:)
我删除了片段
StringChar
和EscapeSequence
,并将StringChars
替换为:[A-Za-z0-9]+
。它可以更好地识别列名,但不匹配只包含数字的字符串,如“123”
。我将尝试您的解决方案:)很抱歉,您的解决方案不适用于字符串,如“Test”
,也不适用于列名,如[Test]
。:/因此,您同意我的评估,您需要在非字符串字符集中包含“]”。解释为什么你认为你需要在这个集合中有“[”。另外,解释为什么你必须把数字作为一个特例来输入;当然0-9被字符串接受的方式与a-Z完全相同。没有这些解释,我认为这对其他ANTLR新手没有帮助。好吧,如果输入是[[Test]
它仍然会返回Test
,所以这没关系。我真的不明白为什么我必须将数字作为一个特例来处理,但是当我测试[123]
输入时,解析器无法识别123
序列。将数字作为一个特例,它就像一个符咒。如果你没有得到“为什么”,你不明白你做了什么,需要花更多的时间在上面。在编程/调试时,如果你不太清楚你的解决方案为什么起作用,那么它可能真的不起作用,或者因为错误的原因起作用。我不打算为你调试语法,但我认为不需要为数字制定单独的规范nse。(这就是为什么我认为这个答案对其他ANTLR新手没有帮助的原因)。我从来没有说过我完全理解语法,只是说它在工作,而且我至少理解了StringChars中的转义部分。当我调试输入解析时,[123]
它在start()崩溃
使用Antlr4.Runtime.NoViableAltException
我不明白为什么…我建议你把语法去掉,只剩下字符串部分,然后用它进行实验,直到找到有趣的地方。