-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix the trampoline functions of recurring labeled alternatives (#243)
These trampoline functions are normally only used in mutation scenarios when a subtree of a labeled alternative is re-generated by calling the function named as the labeled alternative. If the label is recurring, this function is an artificial trampoline that calls one of the functions that have the same name prefix but differ in a numbered suffix (e.g., `rule_Label` calls `rule_Label_1` or `rule_Label_2`). The trampoline function is expected to be transparent, i.e., to create a tree structure as if one of the number-suffixed functions was called. However, until now, the tree structures created by the trampolines and the way the trees were created were incorrect. The trampoline created two extra nodes in the tree: one UnparserRule node named as the labeled alternative (e.g., `rule_Lable`) and one UnparserRuleAlternative node. - Issue 1: Both nodes are superfluous in the end result. - Issue 2: Both nodes are necessary to help the decision model choose between the number-suffixed functions. But then, the UnparserRule should be named as the main rule that contains the labeled alternatives (e.g., `rule`). This commit fixes both issues.
- Loading branch information
1 parent
35417bc
commit bcd9526
Showing
3 changed files
with
71 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright (c) 2024 Renata Hodovan, Akos Kiss. | ||
* | ||
* Licensed under the BSD 3-Clause License | ||
* <LICENSE.rst or https://opensource.org/licenses/BSD-3-Clause>. | ||
* This file may not be copied, modified, or distributed except | ||
* according to those terms. | ||
*/ | ||
|
||
/* | ||
* This test checks whether the trampoline functions of recurring labeled | ||
* alternatives create the correct tree structure. | ||
*/ | ||
|
||
// TEST-PROCESS: {grammar}.g4 -o {tmpdir} | ||
// TEST-GENERATE: {grammar}Generator.{grammar}Generator -r start -m {grammar}Generator.CustomModel -j 1 -n 5 -o {tmpdir}/{grammar}%d.txt | ||
|
||
grammar RecurringLabelTrampolines; | ||
|
||
@header { | ||
from grammarinator.runtime import DispatchingModel | ||
class CustomModel(DispatchingModel): | ||
def __init__(self): | ||
self.alt = 1 | ||
def choice_start(self, node, idx, weights): | ||
self.alt = 1 - self.alt | ||
return self.alt | ||
} | ||
|
||
start | ||
@after { | ||
assert current.name == 'start', current.name | ||
assert isinstance(current.last_child, UnparserRuleAlternative), repr(current.last_child) | ||
assert len(current.last_child.children) == 1, current.last_child.children | ||
assert current.last_child.last_child.name == 'start_Foo', repr(current.last_child.last_child) | ||
assert current.last_child.last_child.last_child.name == 'Bar', repr(current.last_child.last_child.last_child) | ||
assert str(current) == 'bar', str(current) | ||
current.last_child.last_child.replace(self.start_Foo()) | ||
assert current.name == 'start', current.name | ||
assert isinstance(current.last_child, UnparserRuleAlternative), repr(current.last_child) | ||
assert len(current.last_child.children) == 1, current.last_child.children | ||
assert current.last_child.last_child.name == 'start_Foo', repr(current.last_child.last_child) | ||
assert current.last_child.last_child.last_child.name == 'Baz', repr(current.last_child.last_child.last_child) | ||
assert str(current) == 'baz', str(current) | ||
} | ||
: Bar # Foo | ||
| Baz # Foo | ||
; | ||
|
||
Bar : 'bar' ; | ||
Baz : 'baz' ; |