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 #2038

Draft
wants to merge 197 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
197 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
d765aaa
Miscellaneous cleanup of error recovery code
PieterOlivier Aug 28, 2024
a4c4494
Removed unused fields from SkippedNode
PieterOlivier Aug 28, 2024
34dccde
Switched from hardcoding to environment variable for the parser visua…
PieterOlivier Aug 28, 2024
7eceab2
Fixed some compiler warnings in the DebugVisualizer
PieterOlivier Aug 28, 2024
8e8f4cb
Fixed some compiler warnings
PieterOlivier Aug 28, 2024
70d04cc
INtroduced StackNodeVisitor
PieterOlivier Aug 28, 2024
defa9ae
Fixed more warnings
PieterOlivier Aug 28, 2024
a8194e6
Madde AbstractStackNode.visit public
PieterOlivier Aug 28, 2024
6feaf4d
Use visitor pattern instead of instanceof in ToTokenRecoverer
PieterOlivier Aug 28, 2024
b95e14e
Renamed DebugVisualizer to ParseStateVisualizer
PieterOlivier Aug 28, 2024
f185e70
Generalized AbstractStackNode visitor to be able to return values
PieterOlivier Aug 28, 2024
4c9664f
Removed debug print
PieterOlivier Aug 28, 2024
154a0b8
Added license header to files introduced for error recovery
PieterOlivier Aug 28, 2024
6e19cd9
Added license header to more files and fixed years.
PieterOlivier Aug 28, 2024
ada22e9
Fixed bug when inputURI is missing
PieterOlivier Aug 28, 2024
b4ac5ee
Fixed issues when location information is missing
PieterOlivier Aug 29, 2024
2a9734d
Fixed off-by-one-error
PieterOlivier Aug 29, 2024
72324dc
Now looking deep to find error trees in getBestErrorTree
PieterOlivier Sep 1, 2024
8a6c089
Removed prints
PieterOlivier Sep 1, 2024
fe4a633
Added 'recovery' tests and introduced artificial failure to see if te…
PieterOlivier Sep 1, 2024
b5c1355
Added recovery tests
PieterOlivier Sep 1, 2024
80307f2
Worked on error recovery tests
PieterOlivier Sep 1, 2024
2fcbf59
Improved comments
PieterOlivier Sep 2, 2024
cacf744
Renamed 'input' field to 'inputUri'.
PieterOlivier Sep 2, 2024
4962772
Removed some obsolete comments
PieterOlivier Sep 2, 2024
1c3f65d
Added backwards compatible 'parser' function
PieterOlivier Sep 4, 2024
6ce5f1c
Renamed input to inputUri
PieterOlivier Sep 4, 2024
346f1d9
Disabled tutor because it requires forward-compatibility of Java code…
PieterOlivier Sep 4, 2024
3675201
Various changes based on an excellent code review by Sung.
PieterOlivier Sep 6, 2024
dbc7fb5
Layout changes
PieterOlivier Sep 6, 2024
b11ea45
Moved tests, replaced UnicodeConverter with String constructor
PieterOlivier Sep 17, 2024
622d406
Control parser visualization by environment variable
PieterOlivier Sep 17, 2024
0679ca7
Introduced NopDebugListener so we can remove all the if checks
PieterOlivier Sep 17, 2024
74362f8
Fixed compiler error
PieterOlivier Sep 18, 2024
5e2ac44
Fixed debugListener NPE
PieterOlivier Sep 18, 2024
7131d5f
Improved parser datastructure visualization
PieterOlivier Sep 18, 2024
4fc8dd1
Look through "nullable" productions
PieterOlivier Sep 23, 2024
b415e7a
Merge pull request #2020 from usethesource/to-token-recoverer
PieterOlivier Sep 23, 2024
fc076d3
Started working on decent test support
PieterOlivier Sep 24, 2024
9d1b403
No longer visualize parser state by default (for instance in CI)
PieterOlivier Sep 24, 2024
a98a96b
Merge branch 'main' into error-recovery
PieterOlivier Sep 24, 2024
61ab83b
Merge branch 'error-recovery' into recovery/testing
PieterOlivier Sep 24, 2024
de0bfca
Added Java and C recovery tests
PieterOlivier Sep 24, 2024
1397669
Removed obsolete tests, replaced by tests in LanguageRecoveryTests.rsc
PieterOlivier Sep 25, 2024
c48a010
Added "delete until end of line" test
PieterOlivier Sep 25, 2024
4b763e9
Improved performance of `findBestError`, improved statistics reporting
PieterOlivier Sep 26, 2024
2a53c90
Added some more languages to test and the output of a baseline run
PieterOlivier Sep 26, 2024
e9b1c5e
Reintroduced 'private'
PieterOlivier Sep 26, 2024
2a47f44
Added removed compass direction
PieterOlivier Sep 27, 2024
191b9c5
Added Rascal batch testing support
PieterOlivier Sep 27, 2024
2c4cfdf
Fixed problem where allocated array was too small
PieterOlivier Sep 27, 2024
2c8cccf
Merge branch 'error-recovery' into recovery/testing
PieterOlivier Sep 27, 2024
495fcdc
Fixed issue with infinite recursion during parsing
PieterOlivier Sep 28, 2024
2abd6b5
Disabled test that are not working yet
PieterOlivier Sep 28, 2024
3177361
Merge branch 'error-recovery' into recovery/testing
PieterOlivier Sep 28, 2024
cd6528d
Check on length as actual error can fluctuate
PieterOlivier Sep 29, 2024
f818086
Improved benchmarking, both in speed and stat quality
PieterOlivier Sep 30, 2024
c2b97a9
Fixed cumulative stats display
PieterOlivier Sep 30, 2024
9cb9e17
Fixed division-by-zero when reference parse time happens to be 0
PieterOlivier Sep 30, 2024
52ea339
Added bug tests and some support for selective testing
PieterOlivier Oct 2, 2024
03a4620
Removed unnecessary changes
PieterOlivier Oct 2, 2024
31080c5
Removed unnecessary changes
PieterOlivier Oct 2, 2024
54e4e0f
Printing a newline after each line of input that is processed
PieterOlivier Oct 2, 2024
c2b7d68
Fixed off-by-one error in newline printing
PieterOlivier Oct 2, 2024
76311db
Merge pull request #2034 from usethesource/recovery/testing
PieterOlivier Oct 2, 2024
4144103
Reimplemented error tree disambiguation in Java
PieterOlivier Oct 2, 2024
6e1b128
Removed references to obsolete 'defaultErrorDisambiguationFilter'
PieterOlivier Oct 2, 2024
f7641ec
Added support for "automatic" disambiguation of error trees
PieterOlivier Oct 2, 2024
92a0570
Error disambiguation can actually return a tree without errors.
PieterOlivier Oct 3, 2024
0aa104b
Moved disambiguator to a better location (and fixed a bug)
PieterOlivier Oct 3, 2024
f70dc3b
Optimized fixErrorAppl
PieterOlivier Oct 3, 2024
323c330
Cleaned up code by using TreeAdapter
PieterOlivier Oct 3, 2024
826eb29
Added check before error node post-processing
PieterOlivier Oct 3, 2024
1f1c70a
Merge pull request #2036 from usethesource/recovery/optimize-fix-errors
PieterOlivier Oct 3, 2024
790a590
Merge branch 'error-recovery' into error-disambiguation-in-java
PieterOlivier Oct 3, 2024
c78ad6f
Fixed imports after moving a class
PieterOlivier Oct 3, 2024
c562109
Merge branch 'main' into error-recovery
PieterOlivier Oct 3, 2024
d548012
Merge branch 'error-recovery' into error-disambiguation-in-java
PieterOlivier Oct 3, 2024
bd25ac7
Fixed recovery checking
PieterOlivier Oct 3, 2024
c7c2e99
Merge branch 'error-recovery' into error-disambiguation-in-java
PieterOlivier Oct 3, 2024
bfbf752
Fixed bug in disambiguator (insert is not the same as append!)
PieterOlivier Oct 3, 2024
b62fec8
Fixed array index out of bounds issue
PieterOlivier Oct 4, 2024
3c96712
Removed 'synchronized'
PieterOlivier Oct 4, 2024
1796da6
Fixed end-of-line sequence to the source end-of-lines
PieterOlivier Oct 4, 2024
c039de5
Merge branch 'main' into feat/error-recovery
PieterOlivier Oct 4, 2024
fac588f
Merge branch 'feat/error-recovery' into error-disambiguation-in-java
PieterOlivier Oct 4, 2024
477552f
Implemented preservation of sharing
PieterOlivier Oct 7, 2024
9827f5a
Slight optimization in ParseErrorDisambiguator
PieterOlivier Oct 7, 2024
b0e4514
Merge pull request #2035 from usethesource/error-disambiguation-in-java
PieterOlivier Oct 8, 2024
cec954c
Moved error recovery functions from ParseTree to util::ErrorRecovery
PieterOlivier Oct 8, 2024
340fc0f
Fixed parse time measurement bug
PieterOlivier Oct 8, 2024
b5561a7
Merge pull request #2042 from usethesource/recovery/recovery-func-to-…
PieterOlivier Oct 8, 2024
ad2988f
Reimplemented `findAllErrors` function in Java because we need it in …
PieterOlivier Oct 8, 2024
740bbe2
Update src/org/rascalmpl/library/util/ErrorRecovery.java
PieterOlivier Oct 8, 2024
399eaf1
Slight optimization
PieterOlivier Oct 8, 2024
e28ea9a
Merge pull request #2043 from usethesource/recovery/find-all-errors-j…
PieterOlivier Oct 8, 2024
9ef4026
Refactored test support
PieterOlivier Oct 12, 2024
e1547f5
Added support for retrieving all errors instead of just one
PieterOlivier Oct 12, 2024
31e5407
Added visualization of AbstractNodes
PieterOlivier Oct 12, 2024
adf6704
Implemented recovery when the input is a valid prefix (or is so after…
PieterOlivier Oct 12, 2024
aa95103
Added a file used to profile error disambiguation
PieterOlivier Oct 12, 2024
e58aefc
Refactored tests, added stats, and removed obsolete function
PieterOlivier Oct 14, 2024
46b707a
Replaced findBestError with findBestErrors
PieterOlivier Oct 14, 2024
40fabd6
Removed unused test files
PieterOlivier Oct 14, 2024
2921bdc
Update src/org/rascalmpl/library/lang/rascal/tests/concrete/recovery/…
PieterOlivier Oct 15, 2024
3d8c2ca
Update src/org/rascalmpl/library/lang/rascal/tests/concrete/recovery/…
PieterOlivier Oct 15, 2024
06eb325
Merge pull request #2053 from usethesource/recovery/multi-errors
PieterOlivier Oct 15, 2024
6528e77
Merge branch 'main' into recovery/no-ws-with-timestamps
PieterOlivier Oct 22, 2024
2683d8c
Removed obsolete keyword parameter
PieterOlivier Oct 22, 2024
1616898
Started working on multi-error support
PieterOlivier Oct 18, 2024
93c1277
Fixed formatting of main parse function
PieterOlivier Oct 18, 2024
9df7f4a
Trigger error recovery when only recovery stacks are left
PieterOlivier Oct 19, 2024
0637b14
Ignoring generated file
PieterOlivier Oct 19, 2024
1700d1b
Filter skipped nodes that skip the same chars and have the same resul…
PieterOlivier Oct 21, 2024
af5ab3a
Fixed tests that failed because error recovery has been improved
PieterOlivier Oct 21, 2024
5c7398f
Simplified MultiErrorPico test
PieterOlivier Oct 22, 2024
e764a94
Merge branch 'recovery/only-recovery-stacks-left' into recovery/no-ws…
PieterOlivier Oct 22, 2024
fa0ed1d
Fixed indentation
PieterOlivier Oct 22, 2024
90c3f23
Added comment on the use of "max match length"
PieterOlivier Oct 23, 2024
b1622c0
Consolidated multi-error issue encountered in Rascal.
PieterOlivier Oct 23, 2024
68c7538
Fixed limit calculation in CaseInsenstiveLiteralMatcher
PieterOlivier Oct 23, 2024
4d94b28
Removed obsolete comment
PieterOlivier Oct 23, 2024
c75cba6
Merge pull request #2057 from usethesource/recovery/only-recovery-sta…
PieterOlivier Oct 24, 2024
803724c
Fixed whitespace issues
PieterOlivier Oct 24, 2024
eadc959
Fixed size inconsistency between allocating and enlarging
PieterOlivier Oct 24, 2024
1633109
Merge pull request #2062 from usethesource/recovery/prop-prefix-bug
PieterOlivier Oct 24, 2024
e123bdc
Fixed regression.
PieterOlivier Oct 25, 2024
32db7de
Added `hasErrors` method
PieterOlivier Oct 25, 2024
e1c2f56
Removed whitespace
PieterOlivier Oct 25, 2024
93b4205
Layout fixes
PieterOlivier Oct 29, 2024
ff5f36d
Added '\n' end matcher so end-of-line is also seen as skip terminator
PieterOlivier Oct 29, 2024
377cb8c
Fixed Pico test
PieterOlivier Oct 29, 2024
79267ce
Merge pull request #2064 from usethesource/recovery/end-of-line-token
PieterOlivier Oct 31, 2024
54a9c53
Removed whitespace
PieterOlivier Oct 31, 2024
8d35fc9
Showing mean with two digit precision
PieterOlivier Nov 3, 2024
37ce549
Single whitespace change
PieterOlivier Nov 3, 2024
415773f
Merge branch 'main' into feat/error-recovery
PieterOlivier Nov 5, 2024
79be4a0
Merge branch 'main' into feat/error-recovery
PieterOlivier Nov 8, 2024
e523ce2
Renamed 'symbol' field in skipped production to 'def'
PieterOlivier Nov 13, 2024
c861e93
Merge pull request #2078 from usethesource/recovery/symbol-to-def
PieterOlivier Nov 13, 2024
e8bed22
Added timing ratio column and replaced ',' with ':' in end-of-line uri
PieterOlivier Nov 16, 2024
ea5658f
Improved recovery stats gathering and added R script to process the s…
PieterOlivier Nov 18, 2024
e848bb5
Fixed use of '|unknown:///|' as stats location
PieterOlivier Nov 22, 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ dependency-reduced-pom.xml

*.iml
.idea/

# generated by error recovery benchmark
rascal-recovery-stats.csv
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 @@ private IFunction parserForCurrentModule(RascalFunctionValueFactory vf, ModuleEn
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());
}

private Result<IValue> evalMore(String command, ISourceLocation location)
Expand Down
46 changes: 31 additions & 15 deletions src/org/rascalmpl/library/ParseTree.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ extend Type;
extend Message;
extend List;


@synopsis{The Tree data type as produced by the parser.}
@description{
A `Tree` defines the trees normally found after parsing; additional constructors exist for execptional cases:
Expand Down Expand Up @@ -177,6 +176,8 @@ construct ordered and un-ordered compositions, and associativity groups.
<4> `assoc` means all alternatives are acceptable, but nested on the declared side;
<5> `reference` means a reference to another production rule which should be substituted there,
for extending priority chains and such.
<6> `error` means a node produced by error recovery.
<7> `skipped` means characters skipped during error recovery, always the last child of an `appl` with a `error` production.
}
data Production
= prod(Symbol def, list[Symbol] symbols, set[Attr] attributes) // <1>
Expand All @@ -189,6 +190,9 @@ data Production
| \reference(Symbol def, str cons) // <5>
;

data Production
= \error(Symbol def, Production prod, int dot)
| \skipped(Symbol def);

@synopsis{Attributes in productions.}
@description{
Expand Down Expand Up @@ -348,6 +352,16 @@ The latter option terminates much faster, i.e. always in cubic time, and always
while constructing ambiguous parse forests may grow to O(n^p+1), where p is the length of the longest production rule and n
is the length of the input.

The `allowRecovery` can be set to `true` to enable error recovery. This is an experimental feature.
When error recovery is enabled, the parser will attempt to recover from parse errors and continue parsing.
If successful, a parse tree with error and skipped productions is returned (see the definition of `Production` above).
A number of functions is provided to analyze trees with errors, for example `hasErrors`, `getSkipped`, and `getErrorText`.
Note that the resulting parse forest can contain a lot of error nodes. `disambiguateErrors` can be used to prune the forest
and leave a tree with a single (or even zero) errors based on simple heuristics.
When `allowAmbiguity` is set to false, `allowRecovery` is set to true, and `filters` is empty, this disambiguation is done
automatically so you should end up with a tree with no error ambiguities. Regular ambiguities can still occur
and will result in an error.

The `filters` set contains functions which may be called optionally after the parse algorithm has finished and just before
the Tree representation is built. The set of functions contain alternative functions, only on of them is successfully applied
to each node in a tree. If such a function fails to apply, the other ones are tried. There is no fixed-point computation, so
Expand Down Expand Up @@ -392,14 +406,15 @@ catch ParseError(loc l): {
}
```
}
&T<:Tree parse(type[&T<:Tree] begin, str input, bool allowAmbiguity=false, bool hasSideEffects=false, set[Tree(Tree)] filters={})
= parser(begin, allowAmbiguity=allowAmbiguity, hasSideEffects=hasSideEffects, filters=filters)(input, |unknown:///|);

&T<:Tree parse(type[&T<:Tree] begin, str input, loc origin, bool allowAmbiguity=false, bool hasSideEffects=false, set[Tree(Tree)] filters={})
= parser(begin, allowAmbiguity=allowAmbiguity, hasSideEffects=hasSideEffects, filters=filters)(input, origin);
&T<:Tree parse(type[&T<:Tree] begin, str input, bool allowAmbiguity=false, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={})
= parser(begin, allowAmbiguity=allowAmbiguity, allowRecovery=allowRecovery, hasSideEffects=hasSideEffects, filters=filters)(input, |unknown:///|);

&T<:Tree parse(type[&T<:Tree] begin, str input, loc origin, bool allowAmbiguity=false, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={})
= parser(begin, allowAmbiguity=allowAmbiguity, allowRecovery=allowRecovery, hasSideEffects=hasSideEffects, filters=filters)(input, origin);

&T<:Tree parse(type[&T<:Tree] begin, loc input, bool allowAmbiguity=false, bool hasSideEffects=false, set[Tree(Tree)] filters={})
= parser(begin, allowAmbiguity=allowAmbiguity, hasSideEffects=hasSideEffects, filters=filters)(input, input);
&T<:Tree parse(type[&T<:Tree] begin, loc input, bool allowAmbiguity=false, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={})
= parser(begin, allowAmbiguity=allowAmbiguity, allowRecovery=allowRecovery, hasSideEffects=hasSideEffects, filters=filters)(input, input);


@synopsis{Generates a parser from an input grammar.}
Expand All @@ -415,15 +430,16 @@ So the parse function reads either directly from a str or via the contents of a
which leads to the prefix of the `src` fields of the resulting tree.

The parse function behaves differently depending of the given keyword parameters:
* `allowAmbiguity`: if true then no exception is thrown in case of ambiguity and a parse forest is returned. if false,
* `allowAmbiguity`: if true then no exception is thrown in case of ambiguity and a parse forest is returned. if false,
the parser throws an exception during tree building and produces only the first ambiguous subtree in its message.
if set to `false`, the parse constructs trees in linear time. if set to `true` the parser constructs trees in polynomial time.
*
* 'allowRecovery`: ***experimental*** if true, the parser tries to recover when it encounters a parse error. if a parse error is encountered that can be recovered from,
special `error` and `skipped` nodes are included in the resulting parse tree. More documentation will be added here when this feature matures.
* `hasSideEffects`: if false then the parser is a lot faster when constructing trees, since it does not execute the parse _actions_ in an
interpreted environment to make side effects (like a symbol table) and it can share more intermediate results as a result.
}
@javaClass{org.rascalmpl.library.Prelude}
java &T (value input, loc origin) parser(type[&T] grammar, bool allowAmbiguity=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});
java &T (value input, loc origin) parser(type[&T] grammar, bool allowAmbiguity=false, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});

@javaClass{org.rascalmpl.library.Prelude}
@synopsis{Generates a parser function that can be used to find the left-most deepest ambiguous sub-sentence.}
Expand All @@ -436,15 +452,15 @@ the tree that exhibits ambiguity. This can be done very quickly, while the whole
* The returned sub-tree usually has a different type than the parameter of the type[] symbol that was passed in.
The reason is that sub-trees typically have a different non-terminal than the start non-terminal of a grammar.
}
java Tree (value input, loc origin) firstAmbiguityFinder(type[Tree] grammar, bool hasSideEffects=false, set[Tree(Tree)] filters={});
java Tree (value input, loc origin) firstAmbiguityFinder(type[Tree] grammar, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});

@synopsis{Generates parsers from a grammar (reified type), where all non-terminals in the grammar can be used as start-symbol.}
@description{
This parser generator behaves the same as the `parser` function, but it produces parser functions which have an additional
nonterminal parameter. This can be used to select a specific non-terminal from the grammar to use as start-symbol for parsing.
}
@javaClass{org.rascalmpl.library.Prelude}
java &U (type[&U] nonterminal, value input, loc origin) parsers(type[&T] grammar, bool allowAmbiguity=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});
java &U (type[&U] nonterminal, value input, loc origin) parsers(type[&T] grammar, bool allowAmbiguity=false, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});

@javaClass{org.rascalmpl.library.Prelude}
@synopsis{Generates a parser function that can be used to find the left-most deepest ambiguous sub-sentence.}
Expand All @@ -457,7 +473,7 @@ the tree that exhibits ambiguity. This can be done very quickly, while the whole
* The returned sub-tree usually has a different type than the parameter of the type[] symbol that was passed in.
The reason is that sub-trees typically have a different non-terminal than the start non-terminal of a grammar.
}
java Tree (type[Tree] nonterminal, value input, loc origin) firstAmbiguityFinders(type[Tree] grammar, bool hasSideEffects=false, set[Tree(Tree)] filters={});
java Tree (type[Tree] nonterminal, value input, loc origin) firstAmbiguityFinders(type[Tree] grammar, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});

@synopsis{Parse the input but instead of returning the entire tree, return the trees for the first ambiguous substring.}
@description{
Expand Down Expand Up @@ -535,15 +551,15 @@ p(type(sort("E"), ()), "e+e", |src:///|);
* reifiying types (use of `#`) will trigger the loading of a parser generator anyway. You have to use
this notation for types to avoid that: `type(\start(sort("MySort")), ())` to avoid the computation for `#start[A]`
}
java &U (type[&U] nonterminal, value input, loc origin) loadParsers(loc savedParsers, bool allowAmbiguity=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});
java &U (type[&U] nonterminal, value input, loc origin) loadParsers(loc savedParsers, bool allowAmbiguity=false, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});

@synopsis{Load a previously serialized parser, for a specific non-terminal, from disk for usage}
@description{
This loader behaves just like ((loadParsers)), except that the resulting parser function is already
bound to a specific non-terminal.
}
@javaClass{org.rascalmpl.library.Prelude}
java &U (value input, loc origin) loadParser(type[&U] nonterminal, loc savedParsers, bool allowAmbiguity=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});
java &U (value input, loc origin) loadParser(type[&U] nonterminal, loc savedParsers, bool allowAmbiguity=false, bool allowRecovery=false, bool hasSideEffects=false, set[Tree(Tree)] filters={});

@synopsis{Yield the string of characters that form the leafs of the given parse tree.}
@description{
Expand Down
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 @@ public INode arbNode() {

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);
}

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);
}

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);
}

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

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);
}
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);
+ }
+
}
Loading