问题
I have 2 expression :
ident = alpha . (alnum|[._\-])*;
string = (printable1)+;
# Printable includes almost all Windows-1252 characters with glyphs.
main := ( ident % do_ident | string % do_string )
# The do_* actions have been defined, and generate tokens.
Obviously, any ident is a string. Ragel has priority operators to overcome this. But no matter how I've tried to set the priorities, either some idents execute both actions, or some valid strings are ignored (valid strings with a valid ident as a prefix, for example: ab$).
I have found one way around it, without using priorities:
main := ( ident % do_ident | (string - ident) % do_string )
But if I have more than a few overlapping expression, this will get cumbersome. Is this the only practical way?
Any help with the correct way to do this would be appreciated.
回答1:
Take a look at section '6.3 Scanners' in the Ragel Guide.
main := |*
ident => do_ident;
string => do_string;
*|;
Note: When using scanners, have ts
, te
, and act
defined in the host language.
回答2:
Looks like your issue is that all valid identifiers are also valid strings, you just want it to be interpreted as an identifier first if possible. You can force it to accept an identifier first by embedding a priority in the leaving action for ident, which overrides over all transitions for string:
main := ( ident %(ident_vs_string, 1) % do_ident | string $(ident_vs_string, 0) % do_string )
This will ensure that the leaving transition following a valid expression stops the machine exploring either continuing or leaving a string.
Be careful with how this combined expression is terminated. Whatever expression follows the identifier/string must start with a character not permissible in either, so that the exit transitions are well defined.
来源:https://stackoverflow.com/questions/21467471/how-do-i-prioritize-two-overlapping-expressions-ragel