Antlr4语法问题(不完全解析)

时间:2016-02-25 09:00:26

标签: c# .net parsing antlr4 lexer

我是ANTLR的新手,我正在努力让这个语法有效:

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 ;


当我将"Test"放入输入时,它正在工作并返回字符串"Test"

当我将IParseTree放入输入时,我就会在"Test"中获得以下内容:

  

“(start(statement(expression(primary(literal(string \”Test \“))))))”


但是当我把[Test](与"Test"几乎相同但用括号而不是引号)时,解析器无法识别令牌......

以下是IParseTree时我得到的[Tree]

  

“(开始[测试])”


与数字相同,它很好地识别孤独的数字,例如112312.5等,而不是像1+2 ...

这样的表达式

您是否知道为什么解析器无法识别columnNames规则但与string规则配合良好?

2 个答案:

答案 0 :(得分:1)

可能是因为“StringChar”的定义不正确?它不处理“]”

也许您想将StringChar定义为:

fragment
StringChar
:   ~["\\\]]
|   EscapeSequence
;

如果是我的语法,我会为引用的字符串定义一个QuotedStringChar,并将BracketStringChar定义为〜[\] \\] 以用于括号列名。

欢迎在词汇级别调试语法,并为不同类型的字符串定义不同类型的“引号”。这很常见。 (您应该看到Ruby,您可以在字符串的开头定义字符串引用,ick。)。

答案 1 :(得分:0)

我最终通过以下方式让它发挥作用:

QuotedStringChars
    :   '"' ~[\"]+ '"'
    ;

BracketStringChars
    :   '[' ~[\]]+ ']'
    ;

在引号或括号之间取任何字符。然后:

primary
    :   literal #PrimLiteral
    |   number  #PrimNumber
    ;

literal
    :   QuotedStringChars   #OneString
    |   BracketStringChars  #ColumnName
    |   number              #NUMBER
    ;

number
    :   DecimalIntegerLiteral       #DecimalIntegerLiteral
    |   DecimalFloatingPointLiteral #FloatLiteral
    ;

literal规则有助于区分带引号的字符串,括号字符串和数字。

numberprimary规则中存在literal重复项,因为我的应用程序中每个规则都需要不同的行为。

我用Ira Baxter的好建议来管理这个:)

  

希望这会帮助像我这样的ANTLR其他新手有更好的表现   理解:))