As Fix

XT -- A Bundle of Program Transformation Tools

Description

AsFix (ASF+SDF fixed format) is a format for representing parse trees in the ATerm format.

Currently two versions of AsFix are in used: AsFix2ME and AsFix2. AsFix2 is extremely verbose since layout and literals have a structured representation in AsFix2. AsFix2ME is a more concise since lists, layout and literals are flattened. This is the parse tree format that is used in the ASF+SDF Meta-Environment.

Application

The SGLR parser outputs the result of parsing an input in the AsFix format. The most recent versions of SGLR produce AsFix2ME by default. SGLR produces AsFix2 when the -2 flag is used.

In StrategoXT program transformation systems usually operate on abstract syntax trees. The AsFix2 output of SGLR is transformed into an abstract syntax tree by implode-asfix.

Format Internals

Usually you don't actually want to see an AsFix2 or AsFix2ME parse tree. AsFix takes the job of representing the result of parsing an input very serious. It includes all information required to reproduce the original input. This unparsing is implemented by the asfix-yield tool. The AsFix format exactly describes what kind of productions are applied. An AsFix representation is self-contained: all grammar information needed to interpret a term is also included.

Example

Consider the following SDF syntax definition.

  definition
  module Exp
  exports
    sorts Exp

    lexical syntax
      [\ \t\n]  -> LAYOUT
      [a-zA-Z]+ -> Id
      [0-9]+    -> IntConst

    context-free syntax
      Id        -> Exp {cons("Var")}
      IntConst  -> Exp {cons("Int")}

      Exp "*"  Exp -> Exp  {left, cons("Mul")}
      Exp "/"  Exp -> Exp  {left, cons("Div")}
      Exp "%"  Exp -> Exp  {left, cons("Mod")}

      Exp "+"  Exp -> Exp  {left, cons("Plus")}
      Exp "-"  Exp -> Exp  {left, cons("Minus")}

    context-free priorities
      {left:
        Exp "*"  Exp -> Exp
        Exp "/"  Exp -> Exp
        Exp "%"  Exp -> Exp
      }
    > {left:
        Exp "+"  Exp -> Exp
        Exp "-"  Exp -> Exp
      }

PGEN's sdf2table produces an SGLR parse table from this syntax definition:

  sdf2table -m Exp -i Exp.def -o Exp.tbl

Parsing to AsFix2ME

Parsing the expression 1 + a to the compact AsFix variant AsFix2ME using:

  echo "1 + a" | sglr -m -A -p Exp.tbl | pp-aterm

produces the following parse tree:

parsetree(
  appl(
    prod(
      [cf(opt(layout)), cf(sort("Exp")), cf(opt(layout))]
    , sort("<START>")
    , no-attrs
    )
  , [ appl(prod([], cf(opt(layout)), no-attrs), [])
    , appl(
        prod(
          [ cf(sort("Exp"))
          , cf(opt(layout))
          , lit("+")
          , cf(opt(layout))
          , cf(sort("Exp"))
          ]
        , cf(sort("Exp"))
        , attrs([assoc(left), term(cons("Plus"))])
        )
      , [ appl(
            prod(
              [cf(sort("IntConst"))]
            , cf(sort("Exp"))
            , attrs([term(cons("Int"))])
            )
          , [ appl(
                prod(
                  [lex(sort("IntConst"))]
                , cf(sort("IntConst"))
                , no-attrs
                )
              , [ appl(
                    list(iter-star(char-class([range(0, 255)])))
                  , [49]
                  )
                ]
              )
            ]
          )
        , appl(
            prod([cf(layout)], cf(opt(layout)), no-attrs)
          , [32]
          )
        , lit("+")
        , appl(
            prod([cf(layout)], cf(opt(layout)), no-attrs)
          , [32]
          )
        , appl(
            prod(
              [cf(sort("Id"))]
            , cf(sort("Exp"))
            , attrs([term(cons("Var"))])
            )
          , [ appl(
                prod(
                  [lex(sort("Id"))]
                , cf(sort("Id"))
                , no-attrs
                )
              , [ appl(
                    list(iter-star(char-class([range(0, 255)])))
                  , [97]
                  )
                ]
              )
            ]
          )
        ]
      )
    , appl(
        prod([cf(layout)], cf(opt(layout)), no-attrs)
      , [10]
      )
    ]
  )
, 0
)

Parsing to AsFix2

Parsing the same expression to AsFix2:

  echo "1 + a" | sglr -2 -A -p Exp.tbl | pp-aterm

results in:

parsetree(
  appl(
    prod(
      [cf(opt(layout)), cf(sort("Exp")), cf(opt(layout))]
    , sort("<START>")
    , no-attrs
    )
  , [ appl(prod([], cf(opt(layout)), no-attrs), [])
    , appl(
        prod(
          [ cf(sort("Exp"))
          , cf(opt(layout))
          , lit("+")
          , cf(opt(layout))
          , cf(sort("Exp"))
          ]
        , cf(sort("Exp"))
        , attrs([assoc(left), term(cons("Plus"))])
        )
      , [ appl(
            prod(
              [cf(sort("IntConst"))]
            , cf(sort("Exp"))
            , attrs([term(cons("Int"))])
            )
          , [ appl(
                prod(
                  [lex(sort("IntConst"))]
                , cf(sort("IntConst"))
                , no-attrs
                )
              , [ appl(
                    prod(
                      [lex(iter(char-class([range(48, 57)])))]
                    , lex(sort("IntConst"))
                    , no-attrs
                    )
                  , [ appl(
                        prod(
                          [char-class([range(48, 57)])]
                        , lex(iter(char-class([range(48, 57)])))
                        , no-attrs
                        )
                      , [49]
                      )
                    ]
                  )
                ]
              )
            ]
          )
        , appl(
            prod([cf(layout)], cf(opt(layout)), no-attrs)
          , [ appl(
                prod([lex(layout)], cf(layout), no-attrs)
              , [ appl(
                    prod(
                      [char-class([range(9, 10), 32])]
                    , lex(layout)
                    , no-attrs
                    )
                  , [32]
                  )
                ]
              )
            ]
          )
        , appl(
            prod([char-class([43])], lit("+"), no-attrs)
          , [43]
          )
        , appl(
            prod([cf(layout)], cf(opt(layout)), no-attrs)
          , [ appl(
                prod([lex(layout)], cf(layout), no-attrs)
              , [ appl(
                    prod(
                      [char-class([range(9, 10), 32])]
                    , lex(layout)
                    , no-attrs
                    )
                  , [32]
                  )
                ]
              )
            ]
          )
        , appl(
            prod(
              [cf(sort("Id"))]
            , cf(sort("Exp"))
            , attrs([term(cons("Var"))])
            )
          , [ appl(
                prod(
                  [lex(sort("Id"))]
                , cf(sort("Id"))
                , no-attrs
                )
              , [ appl(
                    prod(
                      [ lex(
                          iter(
                            char-class([range(65, 90), range(97, 122)])
                          )
                        )
                      ]
                    , lex(sort("Id"))
                    , no-attrs
                    )
                  , [ appl(
                        prod(
                          [char-class([range(65, 90), range(97, 122)])]
                        , lex(
                            iter(
                              char-class([range(65, 90), range(97, 122)])
                            )
                          )
                        , no-attrs
                        )
                      , [97]
                      )
                    ]
                  )
                ]
              )
            ]
          )
        ]
      )
    , appl(
        prod([cf(layout)], cf(opt(layout)), no-attrs)
      , [ appl(
            prod([lex(layout)], cf(layout), no-attrs)
          , [ appl(
                prod(
                  [char-class([range(9, 10), 32])]
                , lex(layout)
                , no-attrs
                )
              , [10]
              )
            ]
          )
        ]
      )
    ]
  )
, 0
)

Producing an Abstract Syntax Tree

Applying implode-asfix to reduce this to an abstract syntax tree:

  echo "1 + a" | sglr -2A -p Exp.tbl | implode-asfix | pp-aterm
results in:
  Plus(Int("1"), Var("a"))

implode-asfix only accepts AsFix2. The implodePT (part of the pt-support package, which is in the sdf2-bundle) implements the same implosion for AsFix2ME.

  echo "1 + a" | sglr -mA -p Exp.tbl | implodePT | pp-aterm
produces
  Plus(Int("1"), Var("a"))

Tools.AsFix moved from Stratego.AsFix on 17 Feb 2004 - 09:35 by MartinBravenboer - put it back