Examples

From richreports
Jump to: navigation, search

This page contains short examples illustrating how the RichReports libraries can be used within each of the languages and platforms.

Haskell

Assume that we are defining a Haskell module that imports the Haskell RichReports module.

import qualified Text.RichReports as R

Suppose we have the following abstract syntax data structure for a small example of a programming language.

data Program =
    Program [Stmt]
 
data Stmt =
    Repeat [Stmt]
  | Prints Exp
  | Errors
  | Pass
 
data Exp =
    OpPlus Exp Exp
  | OpMax Exp Exp
  | OpAbs Exp
  | Num Integer

It is possible to define a function that converts any abstract syntax tree into a report.

instance R.ToReport Program where
  report (Program ss) =
    R.Page $ R.Block [] [] [R.report s | s <- ss]
 
instance R.ToReport Stmt where
  report s = case s of
    Repeat ss ->
      R.Concat [R.Line [R.Keyword "repeat", R.Block [] [] [R.report s | s <- ss]]]
    Prints e  ->
      R.Line [R.Keyword "print", R.Entity R.Space, R.report e]
    Errors    ->
      R.Line [
        R.Span
          [R.HighlightError]
          [R.Text "This is a message that applies to the whole highlighted span"]
          [R.Keyword "error"],
        R.Entity R.Space,
        R.Text "outside",
        R.Entity R.Space,
        R.Text "span"
      ]
    Pass      ->
      R.Line [R.Keyword "pass"]
 
instance R.ToReport Exp where
  report e = case e of
    OpPlus e1 e2 ->
      R.Concat [R.report e1, R.Keyword "+", R.report e2]
    OpMax e1 e2  ->
      R.Concat [
        R.Builtin "max", 
        R.Punctuation "(",
        R.report e1,
        R.Punctuation ",",
        R.report e2,
        R.Punctuation ")"
      ]
    OpAbs e      ->
      R.Concat [R.Builtin "abs", R.Punctuation "(", R.report e, R.Punctuation ")"]
    Num i        ->
      R.Atom [] [R.Text "int"] [R.Konstant (show i)]

JavaScript

Assume that we are defining a JavaScript module that imports the JavaScript RichReports module.

  var uxadt = require('uxadt'); var _ = null;
  var R = require('richreports');

Suppose we have the following abstract syntax data structure for a small example of a programming language (defined using the JavaScript UxADT library).

  uxadt._('Program', {
      Program: [['Stmt']]
    });
 
  uxadt._('Stmt', {
      Repeat: [['Stmt']],
      Prints: ['Exp'],
      Errors: [],
      Pass: []
    });
 
  uxadt._('Exp', {
      OpPlus: ['Exp', 'Exp'],
      OpMax: ['Exp', 'Exp'],
      OpAbs: ['Exp'],
      Num: ['#']
    });

It is possible to define a function that converts any abstract syntax tree into a report (again, we use the JavaScript UxADT library to define an implementation that uses pattern matching).

  function report(a) {
    return a
      ._(Program(_), function(ss) {
          var rs = [];
          for (var i = 0; i < ss.length; i++)
            rs.push(report(ss[i]));
          return R.Page(R.Block([], [], rs));
        })
      ._(Repeat(_), function(ss) {
          var rs = [];
          for (var i = 0; i < ss.length; i++)
            rs.push(report(ss[i]));
          return (
            R.Concat([
              R.Line([R.Keyword('repeat')]),
              R.Block([], [], rs)
            ])
          );
        })
      ._(Prints(_), function(e) {
          return R.Line([R.Keyword('print'), R.Entity(R.Space()), report(e)]);
        })
      ._(Errors(), function() {
          return (
            R.Line([
              R.Span(
                [R.HighlightError()],
                [R.Text('This is a message that applies to the whole highlighted span.')],
                [R.Keyword('error')]
              ),
              R.Entity(R.Space()),
              R.Text('outside'),
              R.Entity(R.Space()),
              R.Text('span')
            ])
          );
        })
       ._(Pass(), function() {
          return R.Line([R.Keyword('pass')]);
        })
       ._(OpPlus(_, _), function(e1, e2) {
          return R.Concat([report(e1), R.Keyword('+'), report(e2)]);
        })
       ._(OpMax(_, _), function(e1, e2) {
          return R.Concat([
            R.Builtin('max'),
            R.Punctuation('('),
            report(e1),
            R.Punctuation(','),
            report(e2),
            R.Punctuation(')')
          ]);
        })
       ._(OpAbs(_), function(e) {
          return R.Concat([
            R.Builtin('abs'), R.Punctuation('('), report(e), R.Punctuation(')')
          ]);
        })
       ._(Num(_), function(n) {
          return R.Atom([], [R.Text('int')], [R.Konstant(''+n+'')]);
        })
       .end;
  }

PHP

Assume that we are defining a Haskell module that imports the PHP RichReports library.

include_once("uxadt.php"); if (!defined('_')) define('_', null);
include_once("richreports.php");

Suppose we have the following abstract syntax data structure for a small example of a programming language (defined using the PHP UxADT library).

\uxadt\_('Program', array(
    'Program' => array(array('Stmt'))
  ));
 
\uxadt\_('Stmt', array(
    'Repeat' => array(array('Stmt')),
    'Prints' => array('Exp'),
    'Errors' => array(),
    'Pass' => array()
  ));
 
\uxadt\_('Exp', array(
    'OpPlus' => array('Exp', 'Exp'),
    'OpMax' => array('Exp', 'Exp'),
    'OpAbs' => array('Exp'),
    'Num' => array('#')
  ));

It is possible to define a function that converts any abstract syntax tree into a report (again, we use the PHP UxADT library to define an implementation that uses pattern matching).

function report($a) {
  if ($a->_(Program(_))) {
    list($ss) = $a();
    $rs = array(); foreach ($ss as $s) array_push($rs, report($s));
    return Page(Block(array(), array(), $rs));
  } else if ($a->_(Repeat(_))) {
    list($ss) = $a();
    $rs = array(); foreach ($ss as $s) array_push($rs, report($s));
    return
      Concat(array(
        Line(array(Keyword('repeat'))),
        Block(array(), array(), $rs)
      ));
  } else if ($a->_(Prints(_))) {
    list($e) = $a();
    return Line(array(Keyword('print'), Entity(Space()), report($e)));
  } else if ($a->_(Errors())) {
    return
      Line(array(
        Span(
          array(HighlightError()),
          array(Text('This is a message that applies to the whole highlighted span.')),
          array(Keyword('error'))
        ),
        Entity(Space()),
        Text('outside'),
        Entity(Space()),
        Text('span')
      ));
  } else if ($a->_(Pass())) {
    return Line(array(Keyword('pass')));
  } else if ($a->_(OpPlus(_,_))) {
    list($e1,$e2) = $a();
    return Concat(array(report($e1), Keyword('+'), report($e2)));
  } else if ($a->_(OpMax(_,_))) {
    list($e1,$e2) = $a();
    return Concat(array(
      Builtin('max'),
      Punctuation('('),
      report($e1),
      Punctuation(','),
      report($e2),
      Punctuation(')')
    ));
  } else if ($a->_(OpAbs(_))) {
    list($e) = $a();
    return Concat(array(Builtin('abs'), Punctuation('('), report($e), Punctuation(')')));
  } else if ($a->_(Num(_))) {
    list($n) = $a();
    return Atom(array(), array(Text('int')), array(Konstant(''.$n.'')));
  }
}

Python

Assume that we are defining a Haskell module that imports the Python RichReports module.

import uxadt
import richreports as R

Suppose we have the following abstract syntax data structure for a small example of a programming language (defined using the Python UxADT library).

uxadt._('Program', {\
    'Program': [['Stmt']]
  })
 
uxadt._('Stmt', {\
    'Repeat': [['Stmt']],\
    'Prints': ['Exp'],\
    'Errors': [],\
    'Pass': []\
  })
 
uxadt._('Exp', {\
    'OpPlus': ['Exp', 'Exp'],\
    'OpMax': ['Exp', 'Exp'],\
    'OpAbs': ['Exp'],\
    'Num': ['#']
  })

It is possible to define a function that converts any abstract syntax tree into a report (again, we use the Python UxADT library to define an implementation that uses pattern matching).

def report(a):
    if a < Program(_):
        (ss,) = a
        return R.Page(R.Block([], [], [report(s) for s in ss]))
 
    if a < Repeat(_):
        (ss,) = a
        return\
          R.Concat([\
              R.Line([R.Keyword('repeat')]),\
              R.Block([], [], [report(s) for s in ss])\
            ])
    if a < Prints(_):
        (e,) = a
        return R.Line([R.Keyword('print'), R.Entity(R.Space()), report(e)])
    if a < Errors():
        return\
          R.Line([\
              R.Span(\
                  [R.HighlightError()],\
                  [R.Text('This is a message that applies to the whole highlighted span.')],\
                  [R.Keyword('error')]\
                ),\
              R.Entity(R.Space()),\
              R.Text('outside'),\
              R.Entity(R.Space()),\
              R.Text('span')\
            ])
    if a < Pass():
        return R.Line([R.Keyword('pass')])
 
    if a < OpPlus(_,_):
        (e1,e2) = a
        return R.Concat([report(e1), R.Keyword('+'), report(e2)])
    if a < OpMax(_,_):
        (e1,e2) = a
        return R.Concat([\
            R.Builtin('max'),\
            R.Punctuation('('),\
            report(e1),\
            R.Punctuation(','),\
            report(e2),\
            R.Punctuation(')')\
          ])
    if a < OpAbs(_):
        (e,) = a
        return R.Concat([R.Builtin('abs'), R.Punctuation('('), report(e), R.Punctuation(')')])
    if a < Num(_):
        (n,) = a
        return R.Atom([], [R.Text('int')], [R.Konstant(str(n))])