我是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"
.
以下是我在输入中输入"Test"
时在IParseTree
中得到的结果:
"(start (语句 (表达式 (primary (literal (string \" Test \")
)))))
但是当我输入[Test]
(几乎与"Test"
相同,但用大括号而不是引号),解析器无法识别令牌......
这是我放[Tree]
时得到的IParseTree
:
"(开始 [测试])"
与数字相同,它确实可以很好地识别孤独的数字,例如1
,123
,12.5
等,但不能识别像1+2
这样的表达式。
您是否知道为什么解析器无法识别columnNames
规则,但可以很好地与string
规则配合使用?
可能是因为"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 新手拥有更好的 了解:)