Skip to content

garetht/intellij-dhall

Repository files navigation

Requirements

The expected development environment is an IntelliJ editor.

The Lexer should be built with Java 1.8 for compatibility with the IDE.

Building Generated Files

There are three generated components of the project. These are meant to be generated with the tools provided by the GrammarKit plugin.

Dhall.bnf to Dhall Parser

This converts the GrammarKit file into a PEG parser. It can be regenerated using Tools > Generate Parser Code with Dhall.bnf in focus.

_DhallLexer.flex to Lexer

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.

Dhall.bnf to _DhallLexer.flex

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.

Basic Development Commands

In order to run the test version of the development IDE, run the sbt shell and then the command runIDE.

Basic Testing Commands

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.

Thoughts on Grammar Structure

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.

Resetting State

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.

FIRST Set Conflicts

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.

Releasing

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.

About

A Dhall plugin for IntelliJ IDEs

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages