Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error recovery #2033

Draft
wants to merge 127 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
9deefa3
recovered Recoverer from git history
jurgenvinju Mar 30, 2022
d1fdf89
Merge branch 'main' into revive-robust-parsing
jurgenvinju Mar 30, 2022
9ae895c
fixed imports and whitespace
jurgenvinju Mar 31, 2022
4e43070
added documentation
jurgenvinju Mar 31, 2022
ff99ac9
renamed recoverer and simplified to whitespace only and all context-f…
jurgenvinju Mar 31, 2022
d2a0b66
removed unused javadoc plugin that produced warnings
jurgenvinju Mar 31, 2022
d9439a4
fixed compiler warnings
jurgenvinju Mar 31, 2022
d87b4b8
fixed warnings
jurgenvinju Mar 31, 2022
4897d88
fixed warnings
jurgenvinju Mar 31, 2022
5803411
added boolean parameter \'robust\' to parsing API
jurgenvinju Mar 31, 2022
3adee6c
wired boolean parameter for robustness from Rascal function down to p…
jurgenvinju Mar 31, 2022
7318e8f
added override
jurgenvinju Mar 31, 2022
f6e13d8
minor additions to make recovery work and removed dead code
jurgenvinju Apr 11, 2022
ba0fb43
recovered a missing piece from the recovery code
jurgenvinju Apr 13, 2022
650224a
Debugging error recovery
jurgenvinju Apr 14, 2022
6d5d49b
added possibility for recovered nodes to start back in time (at earli…
jurgenvinju Apr 15, 2022
78ee76b
fixed off-by-one: error nodes should be scheduled one character ahead…
jurgenvinju Apr 15, 2022
d9f8fc9
fixed another off-by-one
jurgenvinju Apr 15, 2022
685198d
added initial construction of skipped nodes
jurgenvinju Apr 15, 2022
1d5435b
gave skipped productions a type such that all trees have a type
jurgenvinju Apr 15, 2022
50edd09
Merge branch 'main' into revive-robust-parsing
jurgenvinju Apr 19, 2022
5265ef0
updated template
jurgenvinju Apr 20, 2022
a2162c9
bumped rascal-maven-plugin to 0.8.0 to see if we can benefit from opt…
jurgenvinju Apr 20, 2022
91fb32b
upgraded to rascal-maven-plugin 0.8.1
jurgenvinju Apr 21, 2022
018826f
[maven-release-plugin] prepare release v0.23.1
jurgenvinju Apr 21, 2022
7b6e8b8
[maven-release-plugin] prepare for next development iteration
jurgenvinju Apr 21, 2022
4aefd52
make sure that (a) BasicIDEServices are registered for the commandlin…
jurgenvinju Apr 22, 2022
dde9bd9
basic IDE services can now also browse contents of files which are no…
jurgenvinju Apr 25, 2022
6f9b2b9
Merge branch 'main' into robust-parsing-merge-main
PieterOlivier Jun 6, 2024
d88ac77
Merge branch 'main' into revive-robust-parsing
PieterOlivier Jun 9, 2024
517df9c
Started working on a simple recovery test
PieterOlivier Jun 10, 2024
c779820
Added 'toString' methods and fixed issue in recoverer.
PieterOlivier Jun 17, 2024
13ffcef
Added 'allowRecovery` keyword parameter in parsing functions.
PieterOlivier Jun 18, 2024
b8eb72e
Removed 'Reflective' prefix from StackNodeIdDispenser class name
PieterOlivier Jun 18, 2024
f82006c
WIP: recovery starting to work
PieterOlivier Jun 27, 2024
c8faf66
Merge branch 'main' into robust-parsing/simple-test
PieterOlivier Jul 8, 2024
88cddc3
Added some methods to analyze recovered parse errors in parse trees
PieterOlivier Jul 10, 2024
6d19281
Added comment and removed unused import
PieterOlivier Jul 10, 2024
bcd5914
Enabled logging when error recovery is in effect
PieterOlivier Jul 10, 2024
fb6ffe5
Made printing of productions more robust (it crashed on 'regular' pro…
PieterOlivier Jul 10, 2024
27f1afc
Added some basic recovery tests
PieterOlivier Jul 10, 2024
15fedbf
Implemented parser datastructure visualization using graphviz
PieterOlivier Jul 18, 2024
0eed9a1
Implemented skipping of remaining characters when top-level productio…
PieterOlivier Jul 18, 2024
2b044fd
Reinstated end-of-input check before recovering (for now)
PieterOlivier Jul 18, 2024
d5dbe8c
Minor comment and test changes
PieterOlivier Aug 6, 2024
2246e06
In addition to using whitespace we now also skip until after the last…
PieterOlivier Aug 8, 2024
4b11450
Implemented dynamic last/follow calculations
PieterOlivier Aug 19, 2024
8ef03b4
Minor cleanup of parser tests and debug support
PieterOlivier Aug 20, 2024
7d82f20
Implemented error tree fixup (including source locations)
PieterOlivier Aug 21, 2024
706662b
Renamed RecoveryNodeFlattener to SkippedNodeFlattener
PieterOlivier Aug 21, 2024
7d68129
Implemented basic error disambiguation
PieterOlivier Aug 22, 2024
6b2939c
Added support for error and skipped productions in vis::Text
PieterOlivier Aug 22, 2024
ff350ca
Look "through" non-terminals when finding end/next matchers
PieterOlivier Aug 26, 2024
6d3d58d
Merge branch 'main' into to-token-recoverer
PieterOlivier Aug 26, 2024
2b6a69f
Miscellaneous cleanup of error recovery code
PieterOlivier Aug 28, 2024
7ee16aa
Removed unused fields from SkippedNode
PieterOlivier Aug 28, 2024
002e7a6
Switched from hardcoding to environment variable for the parser visua…
PieterOlivier Aug 28, 2024
238e4c2
Fixed some compiler warnings in the DebugVisualizer
PieterOlivier Aug 28, 2024
704726b
Fixed some compiler warnings
PieterOlivier Aug 28, 2024
af7b5d5
INtroduced StackNodeVisitor
PieterOlivier Aug 28, 2024
2d3fbb1
Fixed more warnings
PieterOlivier Aug 28, 2024
e95b1aa
Madde AbstractStackNode.visit public
PieterOlivier Aug 28, 2024
c06dc6d
Use visitor pattern instead of instanceof in ToTokenRecoverer
PieterOlivier Aug 28, 2024
d584dfe
Renamed DebugVisualizer to ParseStateVisualizer
PieterOlivier Aug 28, 2024
41ea6e8
Generalized AbstractStackNode visitor to be able to return values
PieterOlivier Aug 28, 2024
82c156d
Removed debug print
PieterOlivier Aug 28, 2024
c406e2b
Added license header to files introduced for error recovery
PieterOlivier Aug 28, 2024
c884ceb
Added license header to more files and fixed years.
PieterOlivier Aug 28, 2024
9dce66d
Fixed bug when inputURI is missing
PieterOlivier Aug 28, 2024
a139019
Fixed issues when location information is missing
PieterOlivier Aug 29, 2024
150131e
Fixed off-by-one-error
PieterOlivier Aug 29, 2024
5b1561e
Now looking deep to find error trees in getBestErrorTree
PieterOlivier Sep 1, 2024
23d23b4
Removed prints
PieterOlivier Sep 1, 2024
93611fe
Added 'recovery' tests and introduced artificial failure to see if te…
PieterOlivier Sep 1, 2024
bd2d1ee
Added recovery tests
PieterOlivier Sep 1, 2024
dec2b29
Worked on error recovery tests
PieterOlivier Sep 1, 2024
9abd0bc
Improved comments
PieterOlivier Sep 2, 2024
4cf173e
Renamed 'input' field to 'inputUri'.
PieterOlivier Sep 2, 2024
bcb2753
Removed some obsolete comments
PieterOlivier Sep 2, 2024
5a2266b
Added backwards compatible 'parser' function
PieterOlivier Sep 4, 2024
2be0d9b
Renamed input to inputUri
PieterOlivier Sep 4, 2024
36d4964
Disabled tutor because it requires forward-compatibility of Java code…
PieterOlivier Sep 4, 2024
96fc604
Various changes based on an excellent code review by Sung.
PieterOlivier Sep 6, 2024
cf16c82
Layout changes
PieterOlivier Sep 6, 2024
b94bc02
Moved tests, replaced UnicodeConverter with String constructor
PieterOlivier Sep 17, 2024
9444d21
Control parser visualization by environment variable
PieterOlivier Sep 17, 2024
2200fdf
Introduced NopDebugListener so we can remove all the if checks
PieterOlivier Sep 17, 2024
177e425
Fixed compiler error
PieterOlivier Sep 18, 2024
377a2e1
Fixed debugListener NPE
PieterOlivier Sep 18, 2024
074b5bf
Improved parser datastructure visualization
PieterOlivier Sep 18, 2024
30b935a
Look through "nullable" productions
PieterOlivier Sep 23, 2024
a66cca4
Merge pull request #2020 from usethesource/to-token-recoverer
PieterOlivier Sep 23, 2024
0c8bc49
Started working on decent test support
PieterOlivier Sep 24, 2024
eb9615d
No longer visualize parser state by default (for instance in CI)
PieterOlivier Sep 24, 2024
bbeeae0
Merge branch 'main' into error-recovery
PieterOlivier Sep 24, 2024
6f27c75
Merge branch 'error-recovery' into recovery/testing
PieterOlivier Sep 24, 2024
89d07fe
Added Java and C recovery tests
PieterOlivier Sep 24, 2024
09de7e0
Removed obsolete tests, replaced by tests in LanguageRecoveryTests.rsc
PieterOlivier Sep 25, 2024
0401f72
Added "delete until end of line" test
PieterOlivier Sep 25, 2024
0464d89
Improved performance of `findBestError`, improved statistics reporting
PieterOlivier Sep 26, 2024
6c1efe3
Added some more languages to test and the output of a baseline run
PieterOlivier Sep 26, 2024
c93de3e
Removed space before %
PieterOlivier Sep 26, 2024
5fbc8cd
Reintroduced 'private'
PieterOlivier Sep 26, 2024
11c705e
Added removed compass direction
PieterOlivier Sep 27, 2024
480eb12
Added Rascal batch testing support
PieterOlivier Sep 27, 2024
fda09cf
Fixed problem where allocated array was too small
PieterOlivier Sep 27, 2024
01fef03
Merge branch 'error-recovery' into recovery/testing
PieterOlivier Sep 27, 2024
9bbc1e0
Fixed issue with infinite recursion during parsing
PieterOlivier Sep 28, 2024
194a079
Disabled test that are not working yet
PieterOlivier Sep 28, 2024
ed91821
Merge branch 'error-recovery' into recovery/testing
PieterOlivier Sep 28, 2024
55229cf
Check on length as actual error can fluctuate
PieterOlivier Sep 29, 2024
080c4f6
Readded missing line
PieterOlivier Sep 29, 2024
781a260
Improved benchmarking, both in speed and stat quality
PieterOlivier Sep 30, 2024
f95fba1
Fixed cumulative stats display
PieterOlivier Sep 30, 2024
b9d991b
Fixed division-by-zero when reference parse time happens to be 0
PieterOlivier Sep 30, 2024
88a3647
Added bug tests and some support for selective testing
PieterOlivier Oct 2, 2024
b17dd42
Removed unnecessary changes
PieterOlivier Oct 2, 2024
6103116
Removed unnecessary changes
PieterOlivier Oct 2, 2024
2b00b16
Printing a newline after each line of input that is processed
PieterOlivier Oct 2, 2024
e093964
Fixed off-by-one error in newline printing
PieterOlivier Oct 2, 2024
ad5f036
Merge pull request #2034 from usethesource/recovery/testing
PieterOlivier Oct 2, 2024
f65d8e9
Optimized fixErrorAppl
PieterOlivier Oct 3, 2024
76afc27
Cleaned up code by using TreeAdapter
PieterOlivier Oct 3, 2024
409aa57
Added check before error node post-processing
PieterOlivier Oct 3, 2024
5cf6b57
Merge pull request #2036 from usethesource/recovery/optimize-fix-errors
PieterOlivier Oct 3, 2024
57862c6
Merge branch 'main' into error-recovery
PieterOlivier Oct 3, 2024
3572860
Fixed recovery checking
PieterOlivier Oct 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.dot diff=-astextplain
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"request": "launch",
"mainClass": "org.rascalmpl.shell.RascalShell",
"projectName": "rascal",
"cwd" : "${workspaceFolder}/../rascal-tutor",
"cwd": "${workspaceFolder}/../rascal-tutor",
"vmArgs": "-Xss80m -Xmx2g -ea"
},
{
Expand Down
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
<goal>package</goal>
</goals>
</execution>
<!--
<execution>
<id>default-cli</id>
<phase>compile</phase>
Expand All @@ -190,6 +191,7 @@
</ignores>
</configuration>
</execution>
-->
</executions>
</plugin>
<plugin>
Expand Down
2 changes: 1 addition & 1 deletion src/org/rascalmpl/interpreter/Evaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@
IMap syntaxDefinition = curMod.getSyntaxDefinition();
IMap grammar = (IMap) getParserGenerator().getGrammarFromModules(getMonitor(), curMod.getName(), syntaxDefinition).get("rules");
IConstructor reifiedType = vf.reifiedType(dummy, grammar);
return vf.parsers(reifiedType, vf.bool(false), vf.bool(false), vf.bool(false), vf.set());
return vf.parsers(reifiedType, vf.bool(false), vf.bool(false), vf.bool(false), vf.bool(false), vf.set());

Check warning on line 992 in src/org/rascalmpl/interpreter/Evaluator.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/interpreter/Evaluator.java#L992

Added line #L992 was not covered by tests
}

private Result<IValue> evalMore(String command, ISourceLocation location)
Expand Down
241 changes: 156 additions & 85 deletions src/org/rascalmpl/library/ParseTree.rsc

Large diffs are not rendered by default.

26 changes: 15 additions & 11 deletions src/org/rascalmpl/library/Prelude.java
Original file line number Diff line number Diff line change
Expand Up @@ -2377,20 +2377,24 @@

protected final TypeReifier tr;

public IFunction parser(IValue start, IBool allowAmbiguity, IBool allowRecovery, IBool hasSideEffects, ISet filters) {
return rascalValues.parser(start, allowAmbiguity, allowRecovery, hasSideEffects, values.bool(false), filters);
}

public IFunction parser(IValue start, IBool allowAmbiguity, IBool hasSideEffects, ISet filters) {
return rascalValues.parser(start, allowAmbiguity, hasSideEffects, values.bool(false), filters);
return rascalValues.parser(start, allowAmbiguity, values.bool(false), hasSideEffects, values.bool(false), filters);

Check warning on line 2385 in src/org/rascalmpl/library/Prelude.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/Prelude.java#L2385

Added line #L2385 was not covered by tests
}

public IFunction firstAmbiguityFinder(IValue start, IBool hasSideEffects, ISet filters) {
return rascalValues.parser(start, values.bool(true), hasSideEffects, values.bool(true), filters);
public IFunction firstAmbiguityFinder(IValue start, IBool allowRecovery, IBool hasSideEffects, ISet filters) {
return rascalValues.parser(start, values.bool(true), allowRecovery, hasSideEffects, values.bool(true), filters);
}

public IFunction parsers(IValue start, IBool allowAmbiguity, IBool hasSideEffects, ISet filters) {
return rascalValues.parsers(start, allowAmbiguity, hasSideEffects, values.bool(false), filters);
public IFunction parsers(IValue start, IBool allowAmbiguity, IBool allowRecovery, IBool hasSideEffects, ISet filters) {
return rascalValues.parsers(start, allowAmbiguity, allowRecovery, hasSideEffects, values.bool(false), filters);

Check warning on line 2393 in src/org/rascalmpl/library/Prelude.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/Prelude.java#L2393

Added line #L2393 was not covered by tests
}

public IFunction firstAmbiguityFinders(IValue start, IBool hasSideEffects, ISet filters) {
return rascalValues.parsers(start, values.bool(true), hasSideEffects, values.bool(true), filters);
public IFunction firstAmbiguityFinders(IValue start, IBool allowRecovery, IBool hasSideEffects, ISet filters) {
return rascalValues.parsers(start, values.bool(true), allowRecovery, hasSideEffects, values.bool(true), filters);

Check warning on line 2397 in src/org/rascalmpl/library/Prelude.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/Prelude.java#L2397

Added line #L2397 was not covered by tests
}

public void storeParsers(IValue start, ISourceLocation saveLocation) {
Expand All @@ -2405,18 +2409,18 @@
}
}

public IFunction loadParsers(ISourceLocation savedLocation, IBool allowAmbiguity, IBool hasSideEffects, ISet filters) {
public IFunction loadParsers(ISourceLocation savedLocation, IBool allowAmbiguity, IBool allowRecovery, IBool hasSideEffects, ISet filters) {
try {
return rascalValues.loadParsers(savedLocation, allowAmbiguity, hasSideEffects, values.bool(false), filters);
return rascalValues.loadParsers(savedLocation, allowAmbiguity, allowRecovery, hasSideEffects, values.bool(false), filters);
}
catch (IOException | ClassNotFoundException e) {
throw RuntimeExceptionFactory.io(e.getMessage());
}
}

public IFunction loadParser(IValue grammar, ISourceLocation savedLocation, IBool allowAmbiguity, IBool hasSideEffects, ISet filters) {
public IFunction loadParser(IValue grammar, ISourceLocation savedLocation, IBool allowRecovery, IBool allowAmbiguity, IBool hasSideEffects, ISet filters) {
try {
return rascalValues.loadParser(grammar, savedLocation, allowAmbiguity, hasSideEffects, values.bool(false), filters);
return rascalValues.loadParser(grammar, savedLocation, allowAmbiguity, allowRecovery, hasSideEffects, values.bool(false), filters);

Check warning on line 2423 in src/org/rascalmpl/library/Prelude.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/Prelude.java#L2423

Added line #L2423 was not covered by tests
}
catch (IOException | ClassNotFoundException e) {
throw RuntimeExceptionFactory.io(e.getMessage());
Expand Down
19 changes: 19 additions & 0 deletions src/org/rascalmpl/library/lang/c90/examples/hello-world.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

int print(const char *text);

void printHello(char *name) {
print("Hello ");
print(name);
print("!");
}

int main(int argc, char *argv[]) {
char *name;
if (argc > 1) {
name = argv[1];
} else {
name = "World";
}

printHello(name);
}
2 changes: 2 additions & 0 deletions src/org/rascalmpl/library/lang/diff/unified/UnifiedDiff.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
@contributor{Tijs van der Storm - [email protected] (CWI)}
module lang::diff::unified::UnifiedDiff

start syntax DiffFile = Diff;

syntax Diff
= Header old Header new Chunk* chunks
;
Expand Down
39 changes: 39 additions & 0 deletions src/org/rascalmpl/library/lang/diff/unified/examples/example.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--- a/src/org/rascalmpl/parser/uptr/UPTRNodeFactory.java
+++ b/src/org/rascalmpl/parser/uptr/UPTRNodeFactory.java
@@ -1,6 +1,7 @@
package org.rascalmpl.parser.uptr;

import java.net.URI;
+import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.Map;

@@ -21,7 +22,9 @@ import org.rascalmpl.values.parsetrees.ProductionAdapter;
import org.rascalmpl.values.parsetrees.TreeAdapter;

public class UPTRNodeFactory implements INodeConstructorFactory<ITree, ISourceLocation>{
- private final static RascalValueFactory VF = (RascalValueFactory) ValueFactoryFactory.getValueFactory();
+ private static final RascalValueFactory VF = (RascalValueFactory) ValueFactoryFactory.getValueFactory();
+ private static final IConstructor SKIPPED = VF.constructor(RascalValueFactory.Production_Skipped, VF.constructor(RascalValueFactory.Symbol_IterStar, VF.constructor(RascalValueFactory.Symbol_CharClass, VF.list(VF.constructor(RascalValueFactory.CharRange_Range, VF.integer(1), VF.integer(Character.MAX_CODE_POINT))))));
+
private boolean allowAmb;

public UPTRNodeFactory(boolean allowAmbiguity){
@@ -141,7 +144,14 @@ public class UPTRNodeFactory implements INodeConstructorFactory<ITree, ISourceLo
}

@Override
- public ITree createRecoveryNode(int[] characters) {
- throw new UnsupportedOperationException();
- }
+ public ITree createSkippedNode(int[] characters) {
+ return createLiteralNode(characters, SKIPPED);
+ }
+
+ public ITree createErrorNode(ArrayList<ITree> children, Object production) {
+ IConstructor prod = (IConstructor) production;
+ IConstructor errorProd = VF.constructor(RascalValueFactory.Production_Error, prod.get(0), prod, VF.integer(children.size()-1));
+ return buildAppl(children, errorProd);
+ }
+
}
65 changes: 65 additions & 0 deletions src/org/rascalmpl/library/lang/dot/examples/parser-state.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
digraph Parser {
"Parser"["label"="Parser\nInput: \"void f(){if(1){}}\"\nLocation: 0 ('v')\nStep 5: Reducing terminals"];
"todo-1"["label"="<0> 0", "shape"="record"];
"-2"["label"="Epsilon: \n.0@0 ,matchable,end\n?\nin: 'lex(\"LAYOUT\") -> regular(\iter-star(lex(\"LAYOUT\")))'"];
"7226"["label"="List: 7226\n.0@0 ,expandable,end\n7226\nin: 'LAYOUTLIST -> \iter-star(lex(\"LAYOUT\"))'"];
"12860"["label"="NonTerminal: LAYOUTLIST\n.1@0 \nlayouts_LAYOUTLIST\nin: Tags Visibility Signature '=' Expression 'when' 12878 ';'"];
"-1"["label"="NonTerminal: FunctionDeclaration\n.0@-1 \nFunctionDeclaration"];
"12860" -> "-1";
"7226" -> "12860";
"-2" -> "7226";
"todo-1":"0":sw -> "-2"["label"="Stack"];
"46484886"["shape"="octagon", "label"="Epsilon"];
"todo-1":"0":se -> "46484886"["label"="Node"];
"todoLists":"1" -> "todo-1";
"todoLists"["label"="<0> 0 | <1> 1 | <2> 2 | <3> 3 | <4> 4 | <5> 5 | <6> 6 | <7> 7 | <8> 8 | <9> 9 | <10> 10 | <11> 11 | <12> 12 | <13> 13 | <14> 14 | <15> 15", "shape"="record"];
"Parser" -> "todoLists"["label"="todo lists"];
"stacksToExpand"["label"="", "shape"="record"];
"Parser" -> "stacksToExpand"["label"="stacks to expand"];
"terminalsToReduce"["label"="<0> 0", "shape"="record", "color"="red"];
"terminalsToReduce":"0":sw -> "-2"["label"="Stack"];
"terminalsToReduce":"0":se -> "46484886"["label"="Node"];
"Parser" -> "terminalsToReduce"["label"="terminals to reduce"];
"nonTerminalsToReduce"["label"="", "shape"="record"];
"Parser" -> "nonTerminalsToReduce"["label"="non-terminals to reduce"];
"122"["label"="NonTerminal: Tag\n.0@0 ,end\nTag\nin: 'sort(\"Tag\") -> regular(\iter-star-seps(sort(\"Tag\"),[layouts(\"LAYOUTLIST\")]))'"];
"124"["label"="SeparatedList: 124\n.0@0 ,expandable,end\n124\nin: 'default -> tags'"];
"12858"["label"="NonTerminal: Tags\n.0@0 \nTags\nin: Tags Visibility Signature '=' Expression 'when' 12878 ';'"];
"12858" -> "-1";
"124" -> "12858";
"122" -> "124";
"unexpandableNodes":"0" -> "122";
"13120"["label"="NonTerminal: Comment\n.0@0 ,end\nComment\nin: 'LAYOUT -> Comment'"];
"7221"["label"="NonTerminal: LAYOUT\n.0@0 ,end\nLAYOUT\nin: 'lex(\"LAYOUT\") -> regular(\iter-star(lex(\"LAYOUT\")))'"];
"7221" -> "7226";
"13120" -> "7221";
"unexpandableNodes":"1" -> "13120";
"unexpandableNodes"["label"="<0> 0 | <1> 1", "shape"="record"];
"12824"["label"="Char: \n.0@-1 ,matchable\n0\nin: 0 'sort(\"FunctionDeclaration\")' ':' 12828 0"];
"unmatchableLeafNodes":"0" -> "12824";
"128"["label"="Char: \n.0@-1 ,matchable\n0\nin: 0 'sort(\"Tags\")' ':' 132 0"];
"unmatchableLeafNodes":"1" -> "128";
"2043"["label"="Literal: \n.0@-1 ,matchable\n'@'\nin: '@' Name '=' Expression"];
"unmatchableLeafNodes":"2" -> "2043";
"2065"["label"="Char: \n.0@-1 ,matchable\n0\nin: 0 '\iter-star(sort(\"Tag\"))' ':' 2069 0"];
"unmatchableLeafNodes":"3" -> "2065";
"13122"["label"="Char: \n.0@-1 ,matchable,end\n9-13,32,133,160,5760,6158,8192-8202,8232-8233,8239,8287,12288\nin: 'LAYOUT -> [range(9,13),range(32,32),range(133,133),range(160,160),range(5760,5760),range(6158,6158),range(8192,8202),range(8232,8233),range(8239,8239),range(8287,8287),range(12288,12288)]'"];
"unmatchableLeafNodes":"4" -> "13122";
"13125"["label"="Char: \n.0@-1 ,matchable\n0\nin: 0 '\iter-star(sort(\"LAYOUT\"))' ':' 13129 0"];
"unmatchableLeafNodes":"5" -> "13125";
"7373"["label"="Literal: \n.0@-1 ,matchable\n'/*'\nin: '/*' 7379 '*/'"];
"unmatchableLeafNodes":"6" -> "7373";
"7382"["label"="Literal: \n.0@-1 ,matchable\n'//'\nin: '//' 7386"];
"unmatchableLeafNodes":"7" -> "7382";
"7389"["label"="Char: \n.0@-1 ,matchable\n0\nin: 0 'sort(\"Comment\")' ':' 7393 0"];
"unmatchableLeafNodes":"8" -> "7389";
"unmatchableLeafNodes"["label"="<0> 0 | <1> 1 | <2> 2 | <3> 3 | <4> 4 | <5> 5 | <6> 6 | <7> 7 | <8> 8", "shape"="record"];
"unmatchableMidProductionNodes"["shape"="record", "label"=""];
"filteredNodes"["label"="", "shape"="record"];
"error"["label"="Errors"];
"Parser" -> "error"["label"="error tracking"];
"error" -> "unexpandableNodes"["label"="unexpandable"];
"error" -> "unmatchableLeafNodes"["label"="unmatchable leafs"];
"error" -> "unmatchableMidProductionNodes"["label"="unmatchable mid-prod"];
"error" -> "filteredNodes"["label"="filtered"];
}
2 changes: 1 addition & 1 deletion src/org/rascalmpl/library/lang/dot/syntax/Dot.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ syntax NodeId
| Id Port
;

syntax Port = ":" Id Id?
syntax Port = ":" Id (":" Id)?
// | ":" Id
// | ":" CompassPt
;
Expand Down
18 changes: 18 additions & 0 deletions src/org/rascalmpl/library/lang/pico/examples/fac.pico
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
begin declare input : natural,
output : natural,
repnr : natural,
rep : natural,
s1 : string,
s2 : string;
input := 14;
output := 1;
while input - 1 do
rep := output;
repnr := input;
while repnr - 1 do
output := output + rep;
repnr := repnr - 1
od;
input := input - 1
od
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2024, NWO-I Centrum Wiskunde & Informatica (CWI)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

module lang::rascal::tests::concrete::recovery::BasicRecoveryTests

import ParseTree;

layout Layout = [\ ]* !>> [\ ];

syntax S = T;

syntax T = ABC End;
syntax ABC = 'a' 'b' 'c';
syntax End = "$";

private Tree parseS(str input, bool visualize=false)
= parser(#S, allowRecovery=true, allowAmbiguity=true)(input, |unknown:///?visualize=<"<visualize>">|);

test bool basicOk() {
return !hasErrors(parseS("a b c $"));
}

test bool abx() {
Tree t = parseS("a b x $");
return getErrorText(findBestError(t)) == "x ";
}

test bool axc() {
Tree t = parseS("a x c $");
return getErrorText(findBestError(t)) == "x c";
}

test bool ax() {
Tree t = parseS("a x $");
return getErrorText(findBestError(t)) == "x ";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module lang::rascal::tests::concrete::recovery::ErrorRecoveryBenchmark

import lang::rascal::tests::concrete::recovery::RecoveryTestSupport;

import IO;
import util::Benchmark;
import String;
import List;

void runTestC() { testRecoveryC(); }
void runTestDiff() { testRecoveryDiff(); }
void runTestDot() { testRecoveryDot(); }
void runTestJava() { testRecoveryJava(); }
void runTestJson() { testRecoveryJson(); }
void runTestPico() { testRecoveryPico(); }
void runTestRascal() { testRecoveryRascal(); }

FileStats testRecoveryC() = testErrorRecovery(|std:///lang/c90/syntax/C.rsc|, "TranslationUnit", |std:///lang/c90/examples/hello-world.c|);
FileStats testRecoveryDiff() = testErrorRecovery(|std:///lang/diff/unified/UnifiedDiff.rsc|, "DiffFile", |std:///lang/diff/unified/examples/example.diff|);
FileStats testRecoveryDot() = testErrorRecovery(|std:///lang/dot/syntax/Dot.rsc|, "DOT", |std:///lang/dot/examples/parser-state.dot|);
FileStats testRecoveryJava() = testErrorRecovery(|std:///lang/java/syntax/Java15.rsc|, "CompilationUnit", zippedFile("m3/snakes-and-ladders-project-source.zip", "src/snakes/LastSquare.java"));
FileStats testRecoveryJson() = testErrorRecovery(|std:///lang/json/syntax/JSON.rsc|, "JSONText", |std:///lang/json/examples/ex01.json|);
FileStats testRecoveryPico() = testErrorRecovery(|std:///lang/pico/syntax/Main.rsc|, "Program", |std:///lang/pico/examples/fac.pico|);
FileStats testRecoveryRascal() = testErrorRecovery(|std:///lang/rascal/syntax/Rascal.rsc|, "Module", |std:///lang/rascal/vis/ImportGraph.rsc|);

void runLanguageTests() {
testRecoveryC();
testRecoveryDiff();
testRecoveryDot();
testRecoveryJava();
testRecoveryJson();
testRecoveryPico();
testRecoveryRascal();
}

void runRascalBatchTest(int maxFiles=1000, int maxFileSize=4000) {
int startTime = realTime();
TestStats stats = batchRecoveryTest(|std:///lang/rascal/syntax/Rascal.rsc|, "Module", |std:///|, ".rsc", maxFiles, maxFileSize);
int duration = realTime() - startTime;
println();
println("========================im========================================");
println("Rascal batch test done in <duration/1000> seconds, total result:");
printStats(stats);
}

int main(list[str] args) {
int maxFiles = 1000;
int maxFileSize = 4000;
if (size(args) == 2) {
maxFiles = toInt(args[0]);
maxFileSize = toInt(args[1]);
} else if (size(args) != 0) {
println("Usage: ErrorRecoveryBenchmark <max-files> <max-file-size>");
}

runRascalBatchTest(maxFiles=maxFiles, maxFileSize=maxFileSize);
return 0;
}
Loading
Loading