Depager

2007.05.26 maita & Nakai "Language" Lab.

What is Depager?

Install

  $ sudo gem install depager

or

  $ tar xvzf depager-0.1.9.tgz
  $ cd depager
  $ sudo ruby setup.rb

If you use emacs, depager-mode.el is available.

  $ cd <depager-root>
  $ cp data/depager/misc/depager-mode.el <your site-lisp>

Then modify your .emacs as following.

  (autoload 'depager-mode "depager-mode" "alternate mode for editing depager files" t)
  (setq auto-mode-alist (append '(("\\.dr$" . depager-mode)) auto-mode-alist))

Usage

  $ depager -o outputfine inputfile

Examples

calc(Lex + Action)

Note: val[x] is the value of the x-th symbol in right hand side.

  %class TinyCalc
  %extend Lexer ('depager/lex.rb')
  %extend Action ('depager/action.rb')
  %decorate @Action
  %%
  %LEX{
    /\s+/, /\#.*/ { }
    /[1-9][0-9]*/ { yield _Token(:NUM, $&.to_i) }
    /./           { yield _Token($&, $&) }
  %}
  #begin-rule
    expr : 
        expr '+' term { val[0] + val[2] }
      | expr '-' term { val[0] - val[2] }
      | term          { val[0] }
    ;
    term :
        term '*' fact { val[0] * val[2] }
      | term '/' fact { val[0] / val[2] }
      | fact          { val[0] }
    ;
    fact :
        NUM           { val[0].value }
      | '(' expr ')'  { val[1] }
    ;
  #end-rule
  %%
  parser = TinyCalc::createDecoratedParser
  r, = parser.yyparse(STDIN)
  puts r

calc(Lex + AST)

Note: ~node is the child node of the AST node.

  %class TinyCalc
  %extend Lexer ('depager/lex.rb')
  %extend ASTBuilderDepthFirst ('depager/astdf.rb')
  %decorate @ASTBuilderDepthFirst
  %%
  %LEX{
    /\s+/, /\#.*/ { }
    /[1-9][0-9]*/ { yield _Token(:NUM, $&.to_i) }
    /./           { yield _Token($&, $&) }
  %}
  %AST{
    Node [value]     { @value = nil }
    Visitor          { }
    add(left, right) { ~value = ~left.value + ~right.value }
    sub(left, right) { ~value = ~left.value - ~right.value }
    mul(left, right) { ~value = ~left.value * ~right.value }
    div(left, right) { ~value = ~left.value / ~right.value }
    literal(-n)      { ~value = ~n.value }
  %}
  #begin-rule
    expr :
        expr '+' term
        => add(expr, term)
      | expr '-' term
        => sub(expr, term)
      | term
        => term
    ;
    term :
        term '*' fact
        => mul(term, fact)
      | term '/' fact
        => div(term, fact)
      | fact
        => fact
    ;
    fact :
        NUM
        => literal(NUM)
      | '(' expr ')'
        => expr
    ;
  #end-rule
  %%
  require 'pp'
  parser = TinyCalc::createDecoratedParser
  t, = parser.yyparse(STDIN)
  v = Visitor.new
  pp t.accept(v).value
  pp t

License

GPL.