gpt4 book ai didi

antlr4 - 关于处理 ANTLR 4 语法中不明确运算符的建议

转载 作者:行者123 更新时间:2023-12-02 08:17:36 25 4
gpt4 key购买 nike

我正在为 basic 方言编写 antlr 语法文件。其中大部分要么有效,要么我很清楚下一步需要做什么。但是,我完全不确定应该如何处理用于相等测试和赋值的“=”字符。

例如,这是一个有效的语句

t = (x = 5) And (y = 3) 

它评估 x 是否等于 5,如果 y 等于 3,则对这些结果执行逻辑 AND 并将结果分配给 t。

我的语法会解析这个;虽然不正确,但我认为一旦歧义得到解决,问题就会自行解决。

ParseTreeExample

如何区分“=”字符的两种用法?
1)我是否应该从表达式中删除赋值规则并在代码生成期间在访问者和/或监听器实现中处理这些情况(赋值与相等测试)

2)是否有更好的方法来定义语法,使其已经整理完毕

有人能够简单地为我指明如何最好地实现这种语言“功能”的正确方向吗?

此外,我一直在阅读 ANTLR4 的权威指南以及语言实现模式,寻找解决方案。它可能在那里,但我还没有找到它。

下面是完整的解析器语法。 ASSIGN 标记当前设置为“=”。 EQUAL 设置为“==”。

parser grammar wlParser;

options { tokenVocab=wlLexer; }

program
: multistatement (NEWLINE multistatement)* NEWLINE?
;

multistatement
: statement (COLON statement)*
;

statement
: declarationStat
| defTypeStat
| assignment
| expression
;

assignment
: lvalue op=ASSIGN expression
;

expression
: <assoc=right> left=expression op=CARAT right=expression #exponentiationExprStat
| (PLUS|MINUS) expression #signExprStat
| IDENTIFIER DATATYPESUFFIX? LPAREN expression RPAREN #arrayIndexExprStat
| left=expression op=(ASTERISK|FSLASH) right=expression #multDivExprStat
| left=expression op=BSLASH right=expression #integerDivExprStat
| left=expression op=KW_MOD right=expression #modulusDivExprStat
| left=expression op=(PLUS|MINUS) right=expression #addSubExprStat
| left=string op=AMPERSAND right=string #stringConcatenation
| left=expression op=(RELATIONALOPERATORS | KW_IS | KW_ISA) right=expression #relationalComparisonExprStat
| left=expression (op=LOGICALOPERATORS right=expression)+ #logicalOrAndExprStat
| op=KW_LIKE patternString #likeExprStat
| LPAREN expression RPAREN #groupingExprStat
| NUMBER #atom
| string #atom
| IDENTIFIER DATATYPESUFFIX? #atom
;

lvalue
: (IDENTIFIER DATATYPESUFFIX?) | (IDENTIFIER DATATYPESUFFIX? LPAREN expression RPAREN)
;

string
: STRING
;

patternString
: DQUOT (QUESTIONMARK | POUND | ASTERISK | LBRACKET BANG? .*? RBRACKET)+ DQUOT
;

referenceType
: DATATYPE
;

declarationStat
: constDecl
| varDecl
;

constDecl
: CONSTDECL? KW_CONST IDENTIFIER EQUAL expression
;

varDecl
: VARDECL (varDeclPart (COMMA varDeclPart)*)? | listDeclPart
;

varDeclPart
: IDENTIFIER DATATYPESUFFIX? ((arrayBounds)? KW_AS DATATYPE (COMMA DATATYPE)*)?
;

listDeclPart
: IDENTIFIER DATATYPESUFFIX? KW_LIST KW_AS DATATYPE
;

arrayBounds
: LPAREN (arrayDimension (COMMA arrayDimension)*)? RPAREN
;

arrayDimension
: INTEGER (KW_TO INTEGER)?
;

defTypeStat
: DEFTYPES DEFTYPERANGE (COMMA DEFTYPERANGE)*
;

这是词法分析器语法。

lexer grammar wlLexer;

NUMBER
: INTEGER
| REAL
| BINARY
| OCTAL
| HEXIDECIMAL
;

RELATIONALOPERATORS
: EQUAL
| NEQUAL
| LT
| LTE
| GT
| GTE
;

LOGICALOPERATORS
: KW_OR
| KW_XOR
| KW_AND
| KW_NOT
| KW_IMP
| KW_EQV
;

INSTANCEOF
: KW_IS
| KW_ISA
;

CONSTDECL
: KW_PUBLIC
| KW_PRIVATE
;

DATATYPE
: KW_BOOLEAN
| KW_BYTE
| KW_INTEGER
| KW_LONG
| KW_SINGLE
| KW_DOUBLE
| KW_CURRENCY
| KW_STRING
;

VARDECL
: KW_DIM
| KW_STATIC
| KW_PUBLIC
| KW_PRIVATE
;

LABEL
: IDENTIFIER COLON
;

DEFTYPERANGE
: [a-zA-Z] MINUS [a-zA-Z]
;

DEFTYPES
: KW_DEFBOOL
| KW_DEFBYTE
| KW_DEFCUR
| KW_DEFDBL
| KW_DEFINT
| KW_DEFLNG
| KW_DEFSNG
| KW_DEFSTR
| KW_DEFVAR
;

DATATYPESUFFIX
: PERCENT
| AMPERSAND
| BANG
| POUND
| AT
| DOLLARSIGN
;

STRING
: (DQUOT (DQUOTESC|.)*? DQUOT)
| (LBRACE (RBRACEESC|.)*? RBRACE)
| (PIPE (PIPESC|.|NEWLINE)*? PIPE)
;

fragment DQUOTESC: '\"\"' ;
fragment RBRACEESC: '}}' ;
fragment PIPESC: '||' ;

INTEGER
: DIGIT+ (E (PLUS|MINUS)? DIGIT+)?
;

REAL
: DIGIT+ PERIOD DIGIT+ (E (PLUS|MINUS)? DIGIT+)?
;

BINARY
: AMPERSAND B BINARYDIGIT+
;

OCTAL
: AMPERSAND O OCTALDIGIT+
;

HEXIDECIMAL
: AMPERSAND H HEXDIGIT+
;

QUESTIONMARK: '?' ;
COLON: ':' ;
ASSIGN: '=';
SEMICOLON: ';' ;
AT: '@' ;
LPAREN: '(' ;
RPAREN: ')' ;
DQUOT: '"' ;
LBRACE: '{' ;
RBRACE: '}' ;
LBRACKET: '[' ;
RBRACKET: ']' ;
CARAT: '^' ;
PLUS: '+' ;
MINUS: '-' ;
ASTERISK: '*' ;
FSLASH: '/' ;
BSLASH: '\\' ;
AMPERSAND: '&' ;
BANG: '!' ;
POUND: '#' ;
DOLLARSIGN: '$' ;
PERCENT: '%' ;
COMMA: ',' ;
APOSTROPHE: '\'' ;
TWOPERIODS: '..' ;
PERIOD: '.' ;
UNDERSCORE: '_' ;
PIPE: '|' ;
NEWLINE: '\r\n' | '\r' | '\n';
EQUAL: '==' ;
NEQUAL: '<>' | '><' ;
LT: '<' ;
LTE: '<=' | '=<';
GT: '>' ;
GTE: '=<'|'<=' ;

KW_AND: A N D ;
KW_BINARY: B I N A R Y ;
KW_BOOLEAN: B O O L E A N ;
KW_BYTE: B Y T E ;
KW_DATATYPE: D A T A T Y P E ;
KW_DATE: D A T E ;
KW_INTEGER: I N T E G E R ;
KW_IS: I S ;
KW_ISA: I S A ;
KW_LIKE: L I K E ;
KW_LONG: L O N G ;
KW_MOD: M O D ;
KW_NOT: N O T ;
KW_TO: T O ;
KW_FALSE: F A L S E ;
KW_TRUE: T R U E ;
KW_SINGLE: S I N G L E ;
KW_DOUBLE: D O U B L E ;
KW_CURRENCY: C U R R E N C Y ;
KW_STRING: S T R I N G ;

fragment BINARYDIGIT: ('0'|'1') ;
fragment OCTALDIGIT: ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7') ;
fragment DIGIT: '0'..'9' ;
fragment HEXDIGIT: ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' | A | B | C | D | E | F) ;
fragment A: ('a'|'A');
fragment B: ('b'|'B');
fragment C: ('c'|'C');
fragment D: ('d'|'D');
fragment E: ('e'|'E');
fragment F: ('f'|'F');
fragment G: ('g'|'G');
fragment H: ('h'|'H');
fragment I: ('i'|'I');
fragment J: ('j'|'J');
fragment K: ('k'|'K');
fragment L: ('l'|'L');
fragment M: ('m'|'M');
fragment N: ('n'|'N');
fragment O: ('o'|'O');
fragment P: ('p'|'P');
fragment Q: ('q'|'Q');
fragment R: ('r'|'R');
fragment S: ('s'|'S');
fragment T: ('t'|'T');
fragment U: ('u'|'U');
fragment V: ('v'|'V');
fragment W: ('w'|'W');
fragment X: ('x'|'X');
fragment Y: ('y'|'Y');
fragment Z: ('z'|'Z');

IDENTIFIER
: [a-zA-Z_][a-zA-Z0-9_~]*
;


LINE_ESCAPE
: (' ' | '\t') UNDERSCORE ('\r'? | '\n')
;

WS
: [ \t] -> skip
;

最佳答案

看一下这个语法(请注意,这个语法不应该是 BASIC 的语法,它只是一个示例,展示如何使用“=”来消除赋值和相等的歧义):

grammar Foo;

program:
(statement | exprOtherThanEquality)*
;

statement:
assignment
;

expr:
equality | exprOtherThanEquality
;

exprOtherThanEquality:
boolAndOr
;

boolAndOr:
atom (BOOL_OP expr)*
;

equality:
atom EQUAL expr
;

assignment:
VAR EQUAL expr ENDL
;

atom:
BOOL |
VAR |
INT |
group
;

group:
LEFT_PARENTH expr RGHT_PARENTH
;

ENDL : ';' ;
LEFT_PARENTH : '(' ;
RGHT_PARENTH : ')' ;
EQUAL : '=' ;

BOOL:
'true' | 'false'
;

BOOL_OP:
'and' | 'or'
;

VAR:
[A-Za-z_]+ [A-Za-z_0-9]*
;

INT:
'-'? [0-9]+
;

WS:
[ \t\r\n] -> skip
;

这是输入的解析树:t = (x = 5) and (y = 2); enter image description here

在上面的一条评论中,我问您是否可以假设一行上的第一个等号始终对应于一个赋值。我稍微收回这个假设...一行上的第一个等号总是对应于一个赋值,除非它包含在括号内。根据上面的语法,这是一个有效的行:(x = 2)。这是解析树:

enter image description here

关于antlr4 - 关于处理 ANTLR 4 语法中不明确运算符的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26315048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com