我正在尝试向我的antlr语法添加一种特殊类型的函数,称为窗口函数。我的语法看起来像这样:
stat: expression;
equation: expression relop expression;
expression:
multiplyingExpression ((PLUS | MINUS) multiplyingExpression)*;
multiplyingExpression:
powExpression ((TIMES | DIV) powExpression)*;
powExpression: signedAtom (POW signedAtom)?;
signedAtom:
PLUS signedAtom
| MINUS signedAtom
| winfunc
| func
| iffunc
| atom;
atom:
scientific
| string_literal
| id
| constant
| LPAREN expression RPAREN;
string_literal: STRING;
scientific: SCIENTIFIC_NUMBER;
constant: PI | EULER | I;
variable: VARIABLE;
func: funcname LPAREN expression (COMMA expression)* RPAREN;
iffunc:
'if' LPAREN equation COMMA expression COMMA expression RPAREN;
funcname: variable;
relop: EQ | GT | LT;
LPAREN: '(';
RPAREN: ')';
PLUS: '+';
MINUS: '-';
TIMES: '*';
DIV: '/';
GT: '>';
LT: '<';
EQ: '==';
COMMA: ',';
POINT: '.';
POW: '^';
id: '[' idx ']' {console.log($idx.text);};
idx:
{(this.antlrHelper.isMetric(this.getCurrentToken().text))}? metricid
| {(this.antlrHelper.isDimension(this.getCurrentToken().text))}? entityid
| unknownid;
// metricid | entityid | unknownid;
metricid: VARIABLE;
entityid: VARIABLE;
unknownid: VARIABLE;
VARIABLE: VALID_ID_START VALID_ID_CHAR*;
fragment VALID_ID_START: ('a' .. 'z') | ('A' .. 'Z') | '_';
fragment VALID_ID_CHAR: VALID_ID_START | ('0' .. '9') | '.';
SCIENTIFIC_NUMBER: NUMBER ((E1 | E2) SIGN? NUMBER)?;
fragment NUMBER: ('0' .. '9')+ ('.' ('0' .. '9')+)?;
fragment E1: 'E';
fragment E2: 'e';
fragment SIGN: ('+' | '-');
STRING: '"' StringCharacters? '"';
fragment StringCharacters: StringCharacter+;
fragment StringCharacter: ~["\\] | EscapeSequence;
// §3.10.6 Escape Sequences for Character and String Literals
fragment EscapeSequence: '\\' [btnfr"'\\] | OctalEscape;
fragment OctalEscape:
'\\' OctalDigit
| '\\' OctalDigit OctalDigit
| '\\' ZeroToThree OctalDigit OctalDigit;
fragment ZeroToThree: [0-3];
fragment OctalDigit: [0-7];
WS: [ \r\n\t]+ -> skip;
功能正常。对于Windows函数,我添加了以下规则:
winfunc:
WINDOW winfuncname LPAREN winMetricId COMMA scientific COMMA scientific RPAREN;
WINDOW: 'Window_';
winfuncname:
variable;
winMetricId: '[' winMetricIdx ']';
winMetricIdx:
{(this.antlrHelper.isMetric(this.getCurrentToken().text))}? metricid
| otherid;
otherid: VARIABLE;
解析时
Window_ADD
它正在将其解析为func规则,但是我希望我的语法将其解析为winfunc规则。
窗口_添加
它正在将其解析为winfunc,但我不希望有多余的空间。如何使Window_ADD解析为winfunc规则而不是Window_ADD?
答案 0 :(得分:1)
您有两个选择:
1。。如果您确切知道将使用哪个功能名称(端子),则可以简单地更改规则:
WINDOW: 'Window_';
到
WINDOW: 'Window_ADD';
如果要添加更多功能(例如Window_DEL),只需在此规则中再添加一个终端:
WINDOW: 'Window_' ('ADD' | 'DEL');
或
WINDOW: 'Window_';
WINDOW_ADD: WINDOW 'ADD';
WINDOW_DEL: WINDOW 'DEL';
2。。如果函数名称未知,则可能需要使用通配符来确定终端:
WINDOW: 'Window_' VALID_ID_CHAR+;
在这种情况下,函数的类型是在语义分析阶段确定的。