The expected development environment is an IntelliJ editor.
The Lexer should be built with Java 1.8 for compatibility with the IDE.
There are three generated components of the project. These are meant to be generated with the tools provided by the GrammarKit
plugin.
This converts the GrammarKit
file into a PEG parser. It can be regenerated using Tools > Generate Parser Code
with Dhall.bnf
in focus.
This is a JFlex file and we must convert it into a Java lexer. It can be regenerated using Tools > Run JFlex Generator
with _DhallLexer.flex
in focus.
The JFlex lexer generated from the Dhall parser is meant to be committed and hand-edited, but at this stage there is no need for the lexer to be hand-edited except to remove this conflicting rule and another. This lexer can be regenerated by selecting Tools > Generate JFlex Lexer
with Dhall.bnf
in focus.
In order to run the test version of the development IDE, run the sbt
shell and then the command runIDE
.
Run test
in the SBT shell to run tests. Parser tests consist of a .dhall
file describing a Dhall program and a .txt
file containing the expected PSI structure. If the corresponding PSI file is missing, running test
will fail but also automatically generate the PSI structure from the .dhall
file for the next run.
When is it desirable for all alternatives of a rule to extend a rule?
Consider the following:
keyword ::= if | else
if ::= i f
else ::= e l s e
This generates the structure
class Keyword extends PsiElement {
getIf() {}
getElse() {}
}
class If extends PsiElement {}
class Else extends PsiElement {}
But if we extend both classes from keyword
like so
keyword ::= if | else
if ::= i f { extend = keyword }
else ::= e l s e { extend = keyword }
we get the following structure instead
class Keyword extends PsiElement {}
class If extends Keyword {}
class Else extends Keyword {}
which seems more immediately accessible to pattern-matching, and flattens the layer of structure granted by keyword
away.
A fake
rule has the advantage of allowing the custom grammar to specify a particular structure that is not present in the original grammar.
The default location where sbt
stores the downloaded development IDEA
is ~/.intellij-dhall...
. This folder can be deleted for sbt
to download the plugin again on its next run.
To reset sbt
caches, run clean
in the sbt
shell. This may be useful after regenerating parser classes if new classes are unable to be found.
When two FIRST sets conflict in subrules, and no backtracking is specified, we must be sure to pin the first rule that matches to agree with the expected semantics of the ABNF grammar. Three cases of this are double-quote interpolation, single-quote interpolation, and block comment nesting.
To make a new release, run sbt release
. This will run the tests, bump the version in version.sbt
from a snapshot to a numbered release, commit and tag the version bump, push it to the upstream (triggering a build of the artifact on Gitlab, which can be downloaded from the jobs page), and make a final commit bumping the numbered release to the next snapshot release.
Note that the raw ZIP file contains the zipped target
repository, and it is the zip file within that target repository that should be uploaded.