RCBF/D

From Rosetta Code

Jump to: navigation, search

Implementation
This is an implementation of Brainf***.

You may find other implementations of this language at Category:Brainf*** Implementations.

RCBF member
This is part of RCBF.

You may find other members of RCBF at Category:RCBF.

Works with: D version 2.007+

An implementation of Rosetta Code BrainF*ck interpreter in D.

Implement notes:

  • Needs D version 2.007+, because closure support is required (it should compile in D1, but will run abnormally if brackets/loop-commands are in the BF source).
  • Memory is represented by an associative array, so that negative addresses are allowed, though it is not efficient.
  • Input and output are in character mode, rather than in numerical.
  • Nesting level is checked during parsing, and if loops/brackets are not matched, an error is thrown before executing the code.
module rcbf ; 
import std.file, std.c.stdio ;
 
alias void delegate() Act ;
 
char[int] mem ;   // memory
Act[char] cmd ;   // bf command except loop-control
int ptr ;         // mem pointer
 
static this() {
  cmd['>'] = { if(!(++ptr in mem)) mem[ptr] = 0 ; } ;
  cmd['<'] = { if(!(--ptr in mem)) mem[ptr] = 0 ; } ;
  cmd['+'] = { mem[ptr] += 1 ; } ;
  cmd['-'] = { mem[ptr] -= 1 ; } ;
  cmd['.'] = { printf("%c", mem[ptr]) ; } ;
  cmd[','] = { printf("%c", mem[ptr] = getch()) ; flushall ; } ;
}
 
void bf(string code) {
  int cp = 0  ;     // code pointer 
  int nested = 0 ;  // nested loop level
 
  Act bfAct() { 
    Act[] acts ;    // store commands of current nesting level
    char cc ;       
    while(cp < code.length)
      switch(cc = code[cp++]) { // cc get next command and code pointer cp is advanced 
        case '[':
          nested++ ;
          acts ~= bfAct() ;     // begin inner loop
          break ;
        case ']':                    
          if(--nested < 0) throw new Exception("Unmatched Loops") ;
          return { while(mem[ptr]) { foreach(x ; acts){x();} } } ;
        default:
          if(cc in cmd)
            acts ~= cmd[cc] ;
        //else ignore other non-command char
      }   
    return { foreach(x ; acts){x();} } ;
  }
 
  mem = null ;  mem[0] = 0 ;  ptr = 0 ; // reset memory
  Act run = bfAct() ;
  if(nested != 0) throw new Exception("Unmatched Loops") ;
  run() ; // execute the whole bf program
  printf("\n") ;
}
 
void main(string[] args) {      // if no argument, demo code will be run, else 
  if(args.length > 1)           // the arguments are treated as filenames of bf source
      foreach(f ; args[1..$])   // and executed one by one.
        try bf(cast(string)read(f)) ;
        catch (Exception e) printf("%*s",e.msg) ;
  else 
    bf(">+++++++++[<+++++++++>-]<+.>+++[<----->-]"
       "<.-.++++.>++++++[<------>-]<--.>++++++++["
       "<+++++++++>-]<+.>++[<++>-]<+.>++++++++[<-"
       "-------->-]<------.>++++++[<++++++>-]<.>+"
       "++++[<------->-]<.") ;    
}
Personal tools