/*
	Usage: Vis-amb -i parsetree.asfix -o parsetree.ambs

	This module defines a strategy to extract and display the
	ambiguities in a parse tree represented in AsFix.  Ambiguities
	are displayed by printing the non-terminals of the nodes of
	the parse trees in the ambiguities. For instance, consider
	the syntax definition

\begin{verbatim}
definition
module Main
exports
  sorts Exp
  lexical syntax
    [\ \t\n] -> LAYOUT
  context-free syntax
    "id"    -> Exp
    Exp Exp -> Exp
\end{verbatim}

	The following displays the ambiguity caused by the phrase
	\verb|id id id|:

\begin{verbatim}
# ambiguities = 1
* id id id
+ <Exp-CF>
    <Exp-CF>
      "id"
    <LAYOUT?-CF>
      <LAYOUT-CF>
        " "
    <Exp-CF>
      <Exp-CF>
        "id"
      <LAYOUT?-CF>
        <LAYOUT-CF>
          " "
      <Exp-CF>
        "id"
+ <Exp-CF>
    <Exp-CF>
      <Exp-CF>
        "id"
      <LAYOUT?-CF>
        <LAYOUT-CF>
          " "
      <Exp-CF>
        "id"
    <LAYOUT?-CF>
      <LAYOUT-CF>
        " "
    <Exp-CF>
      "id"
\end{verbatim}
	
	Note: Only the inner ambiguities are displayed, i.e., if a
	phrase \emph{and} one of its sub-phrases are ambiguous, only
	the ambiguities of the sub-phrase is displayed.

	\paragraph{Main}

	The strategy first collects the ambiguities, then abbreviates
	them to the tree format shown above, and finally pretty-prints
	the tree using the text module.

*/
module Vis-amb
imports libstratego-lib AsFix
signature
  constructors
    amb-abbr : String * AbbrTree -> AmbAbbr
strategies

/*
  short-description(p) = !["Usage: ", <p>(), " [options]"]
  long-description(p)  = ![
        "The SDF2 implementation caters for arbitrary context-free grammars. That is,\n",
        "even for ambiguous grammars the parser will produce a parse trees containing\n",
        "a concise encoding of allpossible parses. Ambiguities are represented by\n",
        "means of amb nodes that contain a list of possible parse trees at that\n",
        "point. For most applications, however, it is desirable to develop\n",
        "unambiguous grammars. To aid the grammar writer in detecting and solving the\n",
        "ambiguities, the visamb tool extracts the ambiguities from a parse tree and\n",
        "displays them in a readable format.\n"]
*/

  Vis-amb =
    io-wrap(visamb)

  visamb = 
	collect-ambs;
        abbrev-ambs

//	Ambiguity nodes are collected bottom-up.

strategies

  collect-ambs = parsetree(bu-collect(amb(id)), id)
/*

	\paragraph{Term Format}

*/
strategies

  parse-tree = rec x(is-int + 
                     amb(list(x)) + 
                     appl(prod(id,id,id), list(x)))

  format = parsetree(list(amb(list(parse-tree))), is-int)

/*

	\paragraph{Abbreviation}

	An ambiguity consists of a list of parse trees. It is abbreviated
	as \verb|amb-abbr(s, tas)|, where \verb|s| is the yield of the
	tree, i.e., the string underlying the parse tree, and \verb|tas|
	is the list of abbreviated trees.

*/
strategies

  abbrev-ambs = parsetree(map(\x -> root(<abbrev-amb>x)\ ), int-to-string)
  
rules

  abbrev-amb : amb(ts) -> amb-abbr(<Hd; yield> ts, <map(abbrev-term)> ts)

strategies

  abbrev-term = rec x((is-int + ProjectAmb) <+
                      Nsplit(get-sort, Lexical <+ get-args; map(x)))

rules

  get-sort : appl(prod(args, res, attrs), targs) -> res

  get-args : appl(p, as) -> as

  Nsplit(f, g) : x -> N(<f> x, <g> x)

  ProjectAmb : amb([x|xs]) -> x
/*

	\paragraph{Implode lexicals}

*/
rules
  F  : appl(p, ts) -> <concat> ts
  F' : x -> [x]
 
  MkLex : x -> lexical(x)
strategies

  yield = rec x((appl(id, map(x)); F) <+ F'); implode-string

  Lexical =
	appl(prod([lex(id)],cf(id),id), id); yield; MkLex; F' 
        + appl(prod(id,lit(id),id), id); ![]


// Constructors 
signature
   constructors
      lexical : a -> a
      root :    a -> a
      N :       a * a -> a   



