Download: http://porkynator.altervista.org/pbfi-1.1.zip
Sorgenti:
Main.java
- Codice: Seleziona tutto
/*
Copyright 2009 Sebastiano Tronto <sebastiano@luganega.org>
This file is part of PBFI (Porky's Brain F*** Interpreter).
PBFI is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
PBFI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PBFI; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
import javax.swing.JFrame;
import java.util.Scanner;
public class Main {
public static Scanner scanner;
public static char totalCode[], charCodeAux[], charCode[], chars;
public static byte a[];
public static int i;
public static void main( String args[] ) {
Frame frame = new Frame();
frame.setSize( 200, 300 );
frame.setVisible( true );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public static void run( String code ) {
chars = 'a';
int j = 0;
totalCode = code.toCharArray();
charCodeAux = new char[totalCode.length*2];
for ( int k = 0; k < totalCode.length; k++ ) {
switch ( totalCode[k] ) {
case '>':
case '<':
case '+':
case '-':
case '.':
case ',':
charCodeAux[j] = totalCode[k];
j++;
break;
case '[':
charCodeAux[j] = totalCode[k];
j++;
charCodeAux[j] = chars;
chars++;
j++;
break;
case ']':
chars--;
charCodeAux[j] = chars;
j++;
charCodeAux[j] = totalCode[k];
j++;
break;
}
}
charCode = new char[j];
for ( int k = 0; k < charCode.length; k++ )
charCode[k] = charCodeAux[k];
scanner = new Scanner( System.in );
a = new byte[30000];
for ( int count = 0; count < a.length; count++ )
a[count] = 0;
i = 0;
execute( scanner, charCode, a, i, 0, charCode.length );
}
public static void execute( Scanner scanner, char charCode[], byte a[], int i, int start, int stop ) {
for ( int count = start; count < stop; count++ ) {
switch ( charCode[count] ) {
case '>':
i++;
break;
case '<':
i--;
break;
case '+':
a[i]++;
break;
case '-':
a[i]--;
break;
case '.':
System.out.print( (char) a[i] );
break;
case ',':
String stringa = scanner.nextLine();
a[i] = (byte) ( ( stringa.toCharArray() )[0] );
break;
case '[':
if ( a[i] == 0 ) {
count++;
char key = charCode[count];
count++;
for ( ; charCode[count] != key; count++ ) ;
count++;
}
break;
case ']':
if ( a[i] != 0 ) {
count --;
char key = charCode[count];
count --;
for ( ; charCode[count] != key; count-- ) ;
}
break;
}
}
}
}
Frame.java
- Codice: Seleziona tutto
/*
Copyright 2009 Sebastiano Tronto <sebastiano@luganega.org>
This file is part of PBFI (Porky's Brain F*** Interpreter).
PBFI is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
PBFI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PBFI; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.*;
import java.io.*;
public class Frame extends JFrame {
public static int valoreChooser;
public static boolean firstSave;
public static String defaultSave;
public static Main main;
public static JTextArea textArea;
public static JButton runButton;
public static JMenuBar bar;
public static JMenu menuFile, menuAiuto;
public static JMenuItem esci, esegui, salva, salvaConNome, apri, info;
public static JFileChooser chooser;
public static FileInputStream in;
public static FileOutputStream out;
public Frame() {
super( "Porky's BrainF** Interpreter - v1.1" );
firstSave = true;
main = new Main();
defaultSave = "";
chooser = new JFileChooser();
textArea = new JTextArea( "Digitare qui il codice BrainF***", 15, 15 );
bar = new JMenuBar();
menuFile = new JMenu( "File" );
menuAiuto = new JMenu( "?" );
esci = new JMenuItem( "Esci" );
esegui = new JMenuItem( "Esegui" );
salva = new JMenuItem( "Salva" );
salvaConNome = new JMenuItem( "Salva con nome" );
apri = new JMenuItem( "Apri" );
info = new JMenuItem( "Aiuto" );
menuFile.setMnemonic( 'F' );
menuAiuto.setMnemonic( '?' );
esci.setMnemonic( 'E' );
esegui.setMnemonic( 's' );
salva.setMnemonic( 'a' );
salvaConNome.setMnemonic( 'n' );
apri.setMnemonic( 'p' );
info.setMnemonic( 'i' );
esci.addActionListener(
new ActionListener() {
public void actionPerformed ( ActionEvent e ) {
System.exit( 0 );
}
}
);
esegui.addActionListener(
new ActionListener() {
public void actionPerformed ( ActionEvent e ) {
main.run( textArea.getText() );
}
}
);
salva.addActionListener(
new ActionListener() {
public void actionPerformed ( ActionEvent e ) {
if ( firstSave ) {
valoreChooser = chooser.showSaveDialog( Frame.this );
switch ( valoreChooser ) {
case JFileChooser.APPROVE_OPTION:
try {
out = new FileOutputStream( chooser.getSelectedFile().getPath() );
defaultSave = chooser.getSelectedFile().getPath();
char caratteri[];
byte bytes[];
caratteri = textArea.getText().toCharArray();
bytes = new byte[caratteri.length];
for ( int i = 0; i < caratteri.length; i++ )
bytes[i] = ( byte ) caratteri[i];
out.write( bytes );
} catch ( Exception ex ) {
JOptionPane.showMessageDialog( Frame.this, "Errore sconosciuto:\n\n" + ex + "\n\nPer favore riportare il bug a sebastiano@luganega.org", "Errore", JOptionPane.ERROR_MESSAGE );
}
break;
case JFileChooser.ERROR_OPTION:
JOptionPane.showMessageDialog( Frame.this, "Errore sconosciuto:\n\n" + e + "\n\nPer favore riportare il bug a sebastiano@luganega.org", "Errore", JOptionPane.ERROR_MESSAGE );
break;
//case JFileChooser.CANCEL_OPTION:
}
firstSave = false;
} else {
try {
out = new FileOutputStream( defaultSave );
char caratteri[];
byte bytes[];
caratteri = textArea.getText().toCharArray();
bytes = new byte[caratteri.length];
for ( int i = 0; i < caratteri.length; i++ )
bytes[i] = ( byte ) caratteri[i];
out.write( bytes );
} catch ( Exception ex ) {
JOptionPane.showMessageDialog( Frame.this, "Errore sconosciuto:\n\n" + ex + "\n\nPer favore riportare il bug a sebastiano@luganega.org", "Errore", JOptionPane.ERROR_MESSAGE );
}
}
}
}
);
salvaConNome.addActionListener(
new ActionListener() {
public void actionPerformed ( ActionEvent e ) {
valoreChooser = chooser.showSaveDialog( Frame.this );
switch ( valoreChooser ) {
case JFileChooser.APPROVE_OPTION:
try {
out = new FileOutputStream( chooser.getSelectedFile().getPath() );
defaultSave = chooser.getSelectedFile().getPath();
char caratteri[];
byte bytes[];
caratteri = textArea.getText().toCharArray();
bytes = new byte[caratteri.length];
for ( int i = 0; i < caratteri.length; i++ )
bytes[i] = ( byte ) caratteri[i];
out.write( bytes );
} catch ( Exception ex ) {
JOptionPane.showMessageDialog( Frame.this, "Errore sconosciuto:\n\n" + ex + "\n\nPer favore riportare il bug a sebastiano@luganega.org", "Errore", JOptionPane.ERROR_MESSAGE );
}
break;
case JFileChooser.ERROR_OPTION:
JOptionPane.showMessageDialog( Frame.this, "Errore sconosciuto:\n\n" + e + "\n\nPer favore riportare il bug a sebastiano@luganega.org", "Errore", JOptionPane.ERROR_MESSAGE );
break;
//case JFileChooser.CANCEL_OPTION:
}
firstSave = false;
}
}
);
apri.addActionListener(
new ActionListener() {
public void actionPerformed ( ActionEvent e ) {
valoreChooser = chooser.showOpenDialog( Frame.this );
switch ( valoreChooser ) {
case JFileChooser.APPROVE_OPTION:
try {
String stringa;
byte bytes[];
char caratteri[];
in = new FileInputStream( chooser.getSelectedFile().getPath() );
bytes = new byte[in.available()];
caratteri = new char[in.available()];
in.read( bytes );
for ( int i = 0; i < bytes.length; i++ )
caratteri[i] = ( char ) bytes[i];
stringa = new String( caratteri );
textArea.setText( stringa );
} catch ( Exception ex ) {
JOptionPane.showMessageDialog( Frame.this, "Errore sconosciuto:\n\n" + ex + "\n\nPer favore riportare il bug a sebastiano@luganega.org", "Errore", JOptionPane.ERROR_MESSAGE );
}
break;
case JFileChooser.ERROR_OPTION:
JOptionPane.showMessageDialog( Frame.this, "Errore sconosciuto:\n\n" + e + "\n\nPer favore riportare il bug a sebastiano@luganega.org", "Errore", JOptionPane.ERROR_MESSAGE );
break;
//case JFileChooser.CANCEL_OPTION:
}
}
}
);
info.addActionListener(
new ActionListener() {
public void actionPerformed ( ActionEvent e ) {
JOptionPane.showMessageDialog( Frame.this, "Brainfuck è un linguaggio di programmazione esoterico per computer,\ncreato da Urban Müller intorno al 1993. Il linguaggio viene\nin taluni casi denominato Brainf*ck, Brainf***\no anche soltanto BF per evitare di offendere\nla sensibilità altrui.\nNella directory src trovate alcuni esempi di programmi in questo linguaggio.\n\nPer maggiori informazioni visitate la pagina:\nhttp://it.wikipedia.org/wiki/Brainfuck", "BrainF*** - Informazioni", JOptionPane.INFORMATION_MESSAGE );
}
}
);
menuFile.add( esegui );
menuFile.add( salva );
menuFile.add( salvaConNome );
menuFile.add( apri );
menuFile.add( esci );
menuAiuto.add( info );
bar.add( menuFile );
bar.add( menuAiuto );
runButton = new JButton( "Esegui" );
runButton.addActionListener(
new ActionListener() {
public void actionPerformed( ActionEvent e ) {
main.run( textArea.getText() );
}
}
);
setLayout( new BorderLayout() );
setJMenuBar( bar );
add( new JScrollPane( textArea ), BorderLayout.CENTER );
add( runButton, BorderLayout.SOUTH );
}
}
Permette anche di salvare/aprire un progetto.
Riguardo alla gestione delle parentesi: non riuscivo a uscirne (scusate il gioco di parole), quindi ho usato questo " trucchetto": innanzitutto creo un array di char che contiene tutti i caratteri .,+-><[] che trova nella casella di testo e aggiunge un carattere (da 'a' in avanti) dopo ogni parentesi aperta e prima di ogni chiusa, in modo da segnare le corrispondenti. quindi se inserite il codice:
- Codice: Seleziona tutto
codice casuale che non ho la minima idea di cosa faccia:
,+++++++[ dg< +++++++. [ -- <] [ ++ > [ +. <] --> ]>>]
il mio compilatore se lo traduce in :
- Codice: Seleziona tutto
,+++++++[a<+++++++.[b --<b][b++>[c+.<c]-->b]>>a]
per riuscire a trovare le parentesi corrispondenti.
Ad esempio quando arriva a una parentesi aperta, se il byte al puntatore è 0, guarda il byte successivo e lo memorizza come "chiave", poi va avanti fino all'istruzione dopo la parentesi quadra chiusa che segue il successivo simbolo chiave.
Si lo so è un casino, mi sono scervellato 2 giorni (o erano 3? ho anche perso il conto...) per arrivarci.

