Precede Declaration
rascal-0.40.17
Synopsis
A conditional Symbol, constraining the characters that can immediately precede a symbol in the input source text.
Syntax
constraint << Symbol
constraint !<< Symbol
where a constraint is any character class, a literal or a keyword non-terminal Symbol.
Description
Using !<<
, the parser will not accept the Symbol if it is immediately preceded by the terminal in the input string. If the start of the symbol coincides with start of the inout, the constraint will always succeed and the symbol is accepted.
Examples
Typically precede restrictions are used when keywords can become part of identifiers accidentally. For example:
lexical Id = [a-z]+ \ "let" !>> [a-z]; ❶
syntax E
= "let" Id ❷
| Id+ ❷
;
layout Spaces = [\ ]*; ❸
- ❶ we already have keyword reservation via Reserve to make sure
let
does not become an identifier by itself - ❶ we also have a Follow restriction to make sure that identifiers like
ab
are not split intoa
andb
- ❷ here we see that
leta
could be a single identifier, orlet
followed bya
and neither the Follow nor the Reserve disambiguate this.
rascal>import ParseTree;
ok
rascal>parse(#E, "leta");
|TODO:///|: Ambiguity(
|unknown:///|(0,4,<1,0>,<1,4>),
"E",
"leta")
ok
The solution looks as follows:
lexical Id = "let" !<< [a-z]+ \ "let" !>> [a-z];
syntax E
= "let" Id
| Id+
;
layout Spaces = [\ ]*;
Or, more generally, if there are more keywords in the language where this might happen:
lexical Id = [a-z] !<< [a-z]+ \ "let" !>> [a-z];
syntax E
= "let" Id
| Id+
;
layout Spaces = [\ ]*;
The ambiguity is resolved:
rascal>import ParseTree;
ok
rascal>parse(#E, "leta");
E: (E) `leta`
Benefits
- Precede restrictions complement Follow restrictions such that you do not have to spread follow restrictions over the grammar; namely after every
"let"
you'd have to write:"let" !>> [a-z]
- All disambiguations regarding identifiers are focused on the rule for identifiers.
- Precede restrictions are a way to enfore non-empty layout in certain positions in the grammar without having to adapt the definition of
layout
.
Pitfalls
- Precede restrictions are powerful. They rigorously filter trees that do not satify their constraints, based on context-information. Therefore they might introduce parse errors in places where you do not expect them.