Skip to main content

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 into a and b
  • ❷ here we see that leta could be a single identifier, or let followed by a 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.