Tutorial 08

Previous Table of contents Next

Description

The previous tutorial showed how to use a custom Autocompleter. Using a ParseStartListener, the pixel calibration unit string is saved. The 'units' autocompleter then suggests the two options 'pixel(s)' and the actual calibration unit string.

A much better solution would be, if the 'units' type could be defined as 'pixel(s)' and as 'mm' in the first place (similar to Tutorial05), and this would work here because the image to be processed is fixed.

However, in a more general case, the designed language should work on any image, and therefore, at the time of designing the language the actual pixel units are not known yet, and this is why Tutorial05 used the fixed literal 'calibrated units' instead of the actual units string.

This tutorial shows how the 'units' type can be re-defined dynamically, and this is again best done within in the ParseStartListener's parsingStarted() function.

The result will be similar to that of Tutorial05, but instead of the general 'calibrated units' autocompletion option, the actual units string will be shown as an option.

For details, see also

The code


<!doctype html>
<html>
  <body>
    <!-- The HTML element that will hold the editor -->
    <div id="nls-container"></div>

    <!-- The only javascript file needed for nlScript -->
    <script src="https://cdn.jsdelivr.net/npm/@nlscript/nlscript@0.3.0/dist/umd/nlScript.js"></script>

    <!-- Load the library for the actual processing -->
    <script src="preprocessing.js"></script>

    <script>
      let preprocessing = new Preprocessing("output");
      
      preprocessing.setPixelWidth(0.25, "mm");
      
      let parser = new nlScript.Parser();
      
      let imageUnits = "";
      parser.addParseStartListener(() => {
        imageUnits = preprocessing.getUnits();
      
        // At the start of parsing (remember this is done whenever auto-completion
        // needs to be performed), the 'units' type is undefined and then
        // re-defined, according to the pixel calibration unit string of the current image:
        parser.undefineType("units");
      
        parser.defineType("units", "pixel(s)", pn => false);
        parser.defineType("units", imageUnits, pn => true);
      });
      
      parser.defineType("units", "pixel(s)", pn => false);
      
      parser.defineType("filter-size", "{stddev:float} {units:units}", pn => {
        let stddev = pn.evaluate("stddev");
        let units = pn.evaluate("units");
        if(units)
          stddev /= preprocessing.getPixelWidth();
        return stddev;
      }, true);
      
      parser.defineSentence(
        "Apply Gaussian blurring with a standard deviation of {stddev:filter-size}.",
        pn => {
          let stdDev = pn.evaluate("stddev");
          preprocessing.gaussianBlur(stdDev);
          preprocessing.show("output");
          return undefined;
        });
      
      new nlScript.ACEditor(parser, document.getElementById("nls-container"));

    </script>
  </body>
</html>

Demo

The result