У меня есть 2 замечания:
1
Поскольку вы анализируете отдельные выражения (expression : orexpression EOF!;
), ввод "Skill("somename") < 10 ~ SkillExists("othername")"
не только недопустим в вашей грамматике, но и недопустим с точки зрения любого синтаксического анализатора выражений (который я знаю). notexpression
принимает только выражение "с правой стороны", поэтому ~ SkillExists("othername")
- это одно выражение, а Skill("somename") < 10
- это тоже одно выражение. Но между этими двумя отдельными выражениями нет оператора OR
или AND
. Это было бы то же самое, что вычисление выражения true false
вместо true | false
или true and false
.
Короче говоря, ваша грамматика запрещает:
Skill("somename") < 10 ~ SkillExists("othername")
но допускает:
Skill("somename") < 10 & SkillExists("othername")
что мне кажется логичным.
2
Я не совсем понимаю ваше skill
правило (которое неоднозначно, кстати):
skill
: SKILL LPAREN QUOTE NAME QUOTE RPAREN
((GT | LT| LTE | GTE | EQUALS | NOT_EQUALS)? NUMBER*)?
;
Это означает, что оператор является необязательным и в конце может быть ноль или более цифр. Это означает, что следующие данные действительны:
Skill("foo") = 10 20
Skill("foo") 10 20 30
Skill("foo") <
Возможно, вы имели в виду:
skill
: SKILL LPAREN QUOTE NAME QUOTE RPAREN
((GT | LT| LTE | GTE | EQUALS | NOT_EQUALS)^ NUMBER)?
;
вместо этого? (?
становится ^
, а *
удаляется)
Если я только изменю это правило и проанализирую ввод:
Skill("somename") < 10 & SkillExists("othername")
создается следующий AST:
![enter image description here](https://i.stack.imgur.com/nuKCo.png)
(как вы можете видеть, AST должен быть лучше сформирован: то есть вам нужны некоторые правила перезаписи в ваших skill_exists
, logged_in
и skill
правилах)
EDIT
и если вы хотите, чтобы между последовательными выражениями подразумевались токены AND
, сделайте что-то вроде этого:
grammar UserAttribute;
...
tokens {
...
I_AND; // <- added a token without any text (imaginary token)
AND = '&';
...
}
andexpression
: (notexpression -> notexpression) (AND? notexpression -> ^(I_AND $andexpression notexpression))*
;
...
Как видите, поскольку AND
теперь является необязательным, его нельзя использовать внутри правила перезаписи, но вам придется использовать воображаемый токен I_AND
.
Если вы сейчас анализируете ввод:
Skill("somename") < 10 ~ SkillExists("othername")
вы получите следующее AST:
![enter image description here](https://i.stack.imgur.com/mUeHn.png)