Refactoring

This commit is contained in:
Victor 2014-09-18 13:34:37 +03:00
parent 267e623dc3
commit f2049dd085
10 changed files with 205 additions and 205 deletions

View File

@ -1,141 +1,137 @@
package com.annimon.asm; package com.annimon.asm;
import com.annimon.asm.exceptions.ExceptionWithLineNumber; import com.annimon.asm.exceptions.ExceptionWithLineNumber;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTextPane; import javax.swing.JTextPane;
import javax.swing.event.CaretEvent; import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener; import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException; import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
import javax.swing.text.Utilities; import javax.swing.text.Utilities;
/** /**
* Îñíîâíàÿ ïàíåëü ïðèëîæåíèÿ. * Îñíîâíàÿ ïàíåëü ïðèëîæåíèÿ.
* @author aNNiMON * @author aNNiMON
*/ */
public final class AnalyzerPanel extends JPanel { public final class AnalyzerPanel extends JPanel {
private JLabel lineNumberLabel; private JLabel lineNumberLabel;
private JTextPane textPane; private JTextPane textPane;
private JButton analyzeButton; private JButton analyzeButton;
public AnalyzerPanel() { public AnalyzerPanel() {
lineNumberLabel = new JLabel("Line: 1"); lineNumberLabel = new JLabel("Line: 1");
initTextPane(); initTextPane();
initAnalyzeButton(); initAnalyzeButton();
setLayout(new BorderLayout(0, 0)); setLayout(new BorderLayout(0, 0));
add(lineNumberLabel, BorderLayout.NORTH); add(lineNumberLabel, BorderLayout.NORTH);
add(new JScrollPane(textPane)); add(new JScrollPane(textPane));
add(analyzeButton, BorderLayout.SOUTH); add(analyzeButton, BorderLayout.SOUTH);
} }
public AnalyzerPanel(String text) { public AnalyzerPanel(String text) {
textPane = new JTextPane(); textPane = new JTextPane();
textPane.setPreferredSize(new Dimension(300, 300)); textPane.setPreferredSize(new Dimension(300, 300));
textPane.setFont(new Font("Consolas", Font.PLAIN, 14)); textPane.setFont(new Font("Consolas", Font.PLAIN, 14));
textPane.setText(text); textPane.setText(text);
setLayout(new BorderLayout(0, 0)); setLayout(new BorderLayout(0, 0));
add(new JScrollPane(textPane)); add(new JScrollPane(textPane));
} }
private void initTextPane() { private void initTextPane() {
textPane = new JTextPane(); textPane = new JTextPane();
textPane.setPreferredSize(new Dimension(300, 350)); textPane.setPreferredSize(new Dimension(300, 350));
textPane.addCaretListener(new CaretListener() { textPane.addCaretListener(new CaretListener() {
@Override @Override
public void caretUpdate(CaretEvent caretEvent) { public void caretUpdate(CaretEvent caretEvent) {
// Âûâåñòè ïîçèöèþ êàðåòêè â lineNumberLabel. // Âûâåñòè ïîçèöèþ êàðåòêè â lineNumberLabel.
JTextComponent textComponent = (JTextComponent)caretEvent.getSource(); JTextComponent textComponent = (JTextComponent)caretEvent.getSource();
int pos = caretEvent.getDot(); int pos = caretEvent.getDot();
int rowNumber = (pos == 0) ? 1 : 0; int rowNumber = (pos == 0) ? 1 : 0;
try { try {
int offset = pos; int offset = pos;
while (offset > 0) { while (offset > 0) {
offset = Utilities.getRowStart(textComponent, offset) - 1; offset = Utilities.getRowStart(textComponent, offset) - 1;
rowNumber++; rowNumber++;
} }
} catch (BadLocationException ex) {} } catch (BadLocationException ex) {}
lineNumberLabel.setText("Line: " + rowNumber); lineNumberLabel.setText("Line: " + rowNumber);
} }
}); });
textPane.setFont(new Font("Consolas", Font.PLAIN, 14)); textPane.setFont(new Font("Consolas", Font.PLAIN, 14));
textPane.setText(getTextFromResource("/test.asm")); textPane.setText(getTextFromResource("/test.asm"));
} }
private void initAnalyzeButton() { private void initAnalyzeButton() {
analyzeButton = new JButton("Analyze"); analyzeButton = new JButton("Analyze");
analyzeButton.addActionListener(new ActionListener() { analyzeButton.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
String allText = textPane.getText(); String allText = textPane.getText();
// Ëåêñè÷åñêèé àíàëèç - ïåðåâîäèì íàáîð äèðåêòèâ â êîäîâóþ òàáëèöó. // Ëåêñè÷åñêèé àíàëèç - ïåðåâîäèì íàáîð äèðåêòèâ â êîäîâóþ òàáëèöó.
LexicalAnalyzer lex = new LexicalAnalyzer(allText); LexicalAnalyzer lex = new LexicalAnalyzer(allText);
lex.analyze(); lex.analyze();
// Ñèíòàêñè÷åñêèé àíàëèç - ïðîâåðêà ïðàâèëüíîñòè íàáîðà äèðåêòèâ. // Ñèíòàêñè÷åñêèé àíàëèç - ïðîâåðêà ïðàâèëüíîñòè íàáîðà äèðåêòèâ.
SyntaxAnalyzer syn = new SyntaxAnalyzer(lex.getLexicTable()); SyntaxAnalyzer syn = new SyntaxAnalyzer(lex.getLexicTable());
try { try {
syn.analyze(); syn.analyze();
} catch (ExceptionWithLineNumber ex) { } catch (ExceptionWithLineNumber ex) {
showMessageBox("Error", ex.getMessage(), true); showMessageBox("Error", ex.getMessage(), true);
return; return;
} }
//showMessageBox("Info","Source is correct!", false); //showMessageBox("Info","Source is correct!", false);
// Ãåíåðèðóåì ëèñòèíã. // Ãåíåðèðóåì ëèñòèíã.
ListingGenerator gen = new ListingGenerator(lex.getLexicTable(), lex.getVarTable(), lex.getLines()); ListingGenerator gen = new ListingGenerator(lex.getLexicTable(), lex.getVarTable(), lex.getLines());
String listing = gen.generate(); String listing = gen.generate();
showListing(listing); showListing(listing);
} }
}); });
} }
private void showMessageBox(String title, String text, boolean errorMessage) { private void showMessageBox(String title, String text, boolean errorMessage) {
int msgType = errorMessage ? JOptionPane.ERROR_MESSAGE : int msgType = errorMessage ? JOptionPane.ERROR_MESSAGE :
JOptionPane.INFORMATION_MESSAGE; JOptionPane.INFORMATION_MESSAGE;
JOptionPane.showMessageDialog(this, text, title, msgType); JOptionPane.showMessageDialog(this, text, title, msgType);
} }
private void showListing(String listing) { private void showListing(String listing) {
JOptionPane.showMessageDialog(this, new AnalyzerPanel(listing), JOptionPane.showMessageDialog(this, new AnalyzerPanel(listing),
"Listing", JOptionPane.PLAIN_MESSAGE); "Listing", JOptionPane.PLAIN_MESSAGE);
} }
private String getTextFromResource(String res) { private String getTextFromResource(String res) {
try { final StringBuilder text = new StringBuilder();
InputStream is = getClass().getResourceAsStream(res); try (InputStream is = getClass().getResourceAsStream(res)) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
String line;
StringBuilder text = new StringBuilder(); while ( (line = reader.readLine()) != null ) {
String line; text.append(line).append(System.lineSeparator());
while( (line = reader.readLine()) != null ) { }
text.append(line).append(System.lineSeparator()); }
} } catch (IOException ex) {}
return text.toString();
reader.close(); }
return text.toString(); }
} catch (IOException ex) {}
return "";
}
}

View File

@ -2,6 +2,8 @@ package com.annimon.asm;
import com.annimon.asm.directives.*; import com.annimon.asm.directives.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/** /**
* Êîíâåðòåð äèðåêòèâ. * Êîíâåðòåð äèðåêòèâ.
@ -39,8 +41,7 @@ public final class DirectiveConverter {
* @return Integer ÷èñëî. * @return Integer ÷èñëî.
*/ */
public static Integer parseInteger(String text) { public static Integer parseInteger(String text) {
int value; if (text.toLowerCase(Locale.ENGLISH).endsWith("h")) {
if (text.toLowerCase().endsWith("h")) {
char first = Character.toLowerCase(text.charAt(0)); char first = Character.toLowerCase(text.charAt(0));
if ( (first >= 'a') && (first <= 'f') ) { if ( (first >= 'a') && (first <= 'f') ) {
// Ïåðâûé ñèìâîë hex ÷èñëà íå äîëæåí áûòü îò a äî f // Ïåðâûé ñèìâîë hex ÷èñëà íå äîëæåí áûòü îò a äî f
@ -49,15 +50,13 @@ public final class DirectiveConverter {
String hex = text.substring(0, text.length() - 1); String hex = text.substring(0, text.length() - 1);
try { try {
value = Integer.parseInt(hex, 16); return Integer.parseInt(hex, 16);
return value;
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
return null; return null;
} }
} }
try { try {
value = Integer.parseInt(text); return Integer.parseInt(text);
return value;
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
return null; return null;
} }
@ -69,28 +68,28 @@ public final class DirectiveConverter {
* @return ìàññèâ ñòðîê. * @return ìàññèâ ñòðîê.
*/ */
public static String[] split(String text) { public static String[] split(String text) {
ArrayList<String> parts = new ArrayList<>(); final List<String> parts = new ArrayList<>();
int length = text.length(); final int length = text.length();
StringBuilder sb = new StringBuilder(); final StringBuilder word = new StringBuilder();
for (int ch = 0; ch < length; ch++) { for (int ch = 0; ch < length; ch++) {
int i = text.charAt(ch); final int currentChar = text.charAt(ch);
if (i == ' ') { if (currentChar == ' ') {
if (sb.length() > 0) { if (word.length() > 0) {
parts.add(sb.toString().trim()); parts.add(word.toString().trim());
sb.setLength(0); word.setLength(0);
} }
} else if (i == ',') { } else if (currentChar == ',') {
if (sb.length() > 0) { if (word.length() > 0) {
parts.add(sb.toString().trim()); parts.add(word.toString().trim());
parts.add(","); parts.add(",");
sb.setLength(0); word.setLength(0);
} }
} else { } else {
sb.append((char) i); word.append((char) currentChar);
} }
} }
if (sb.length() > 0) { if (word.length() > 0) {
parts.add(sb.toString().trim()); parts.add(word.toString().trim());
} }
String[] m = new String[parts.size()]; String[] m = new String[parts.size()];
m = parts.toArray(m); m = parts.toArray(m);

View File

@ -1,5 +1,7 @@
package com.annimon.asm; package com.annimon.asm;
import java.util.Arrays;
/** /**
* *
* @author aNNiMON * @author aNNiMON
@ -11,6 +13,6 @@ public final class LexicLine {
public LexicLine(int lineNumber, int[] line) { public LexicLine(int lineNumber, int[] line) {
this.lineNumber = lineNumber; this.lineNumber = lineNumber;
this.line = line; this.line = Arrays.copyOf(line, line.length);
} }
} }

View File

@ -1,6 +1,7 @@
package com.annimon.asm; package com.annimon.asm;
import com.annimon.asm.directives.ID; import com.annimon.asm.directives.ID;
import java.util.Arrays;
/** /**
* Ëåêñè÷åñêèé àíàëèçàòîð. * Ëåêñè÷åñêèé àíàëèçàòîð.
@ -28,7 +29,7 @@ public final class LexicalAnalyzer {
} }
public String[] getLines() { public String[] getLines() {
return lines; return Arrays.copyOf(lines, lines.length);
} }
public void analyze() { public void analyze() {

View File

@ -1,6 +1,7 @@
package com.annimon.asm; package com.annimon.asm;
import com.annimon.asm.directives.ID; import com.annimon.asm.directives.ID;
import java.util.Locale;
/** /**
* *
@ -18,9 +19,10 @@ public final class ListingGenerateHelper {
* @return ñòðîêîâîå çíà÷åíèå ÷èñëà â HEX. * @return ñòðîêîâîå çíà÷åíèå ÷èñëà â HEX.
*/ */
public static String toHexString(int value) { public static String toHexString(int value) {
String str = Integer.toString(value, 16).toUpperCase(); String str = Integer.toString(value, 16).toUpperCase(Locale.ENGLISH);
if (str.length() == 1) str = "0" + str; if ( (str.length() == 1) || (str.length() == 3) ) {
else if (str.length() == 3) str = "0" + str; return "0" + str;
}
return str; return str;
} }
@ -75,7 +77,7 @@ public final class ListingGenerateHelper {
* @return êîä ðåãèñòðà (3 áèòà). * @return êîä ðåãèñòðà (3 áèòà).
*/ */
public static byte getRegisterCode(String register) { public static byte getRegisterCode(String register) {
final String reg = register.toLowerCase(); final String reg = register.toLowerCase(Locale.ENGLISH);
switch (reg) { switch (reg) {
case "ax": case "al": return 0b000; case "ax": case "al": return 0b000;
@ -97,7 +99,7 @@ public final class ListingGenerateHelper {
* @return êîä ñåãìåíòíîãî ðåãèñòðà, ëèáî -1, åñëè ðåãèñòð íå ñåãìåíòíûé. * @return êîä ñåãìåíòíîãî ðåãèñòðà, ëèáî -1, åñëè ðåãèñòð íå ñåãìåíòíûé.
*/ */
public static byte getSegmentRegisterCode(String register) { public static byte getSegmentRegisterCode(String register) {
final String reg = register.toLowerCase(); final String reg = register.toLowerCase(Locale.ENGLISH);
for (byte i = 0; i < SEGMENT_REGISTERS.length; i++) { for (byte i = 0; i < SEGMENT_REGISTERS.length; i++) {
if (reg.equals(SEGMENT_REGISTERS[i])) return i; if (reg.equals(SEGMENT_REGISTERS[i])) return i;
} }

View File

@ -7,6 +7,7 @@ import com.annimon.asm.exceptions.ExceptionWithLineNumber;
import com.annimon.asm.exceptions.FewArgumentsException; import com.annimon.asm.exceptions.FewArgumentsException;
import com.annimon.asm.exceptions.TooManyArgumentsException; import com.annimon.asm.exceptions.TooManyArgumentsException;
import com.annimon.asm.exceptions.WrongArgumentException; import com.annimon.asm.exceptions.WrongArgumentException;
import java.util.Locale;
/** /**
* *
@ -18,45 +19,45 @@ public final class Add extends Directive implements ISyntaxChecker, IListingGene
super("add", ID.ADD); super("add", ID.ADD);
} }
private static final int[] PAIRS = {
// Ðåãèñòð - Ðåãèñòð
ID.REGISTER_BYTE, ID.REGISTER_BYTE,
ID.REGISTER_WORD, ID.REGISTER_WORD,
ID.REGISTER_WORD, ID.REGISTER_BYTE,
// Ðåãèñòð - Ïàìÿòü
ID.REGISTER_BYTE, ID.VAR_BYTE,
ID.REGISTER_WORD, ID.VAR_WORD,
ID.REGISTER_WORD, ID.VAR_BYTE,
// Ïàìÿòü - Ðåãèñòð
ID.VAR_BYTE, ID.REGISTER_BYTE,
ID.VAR_WORD, ID.REGISTER_WORD,
ID.VAR_WORD, ID.REGISTER_BYTE,
// Ðåãèñòð - Çíà÷åíèå
ID.REGISTER_BYTE, ID.NUMBER_BYTE,
ID.REGISTER_WORD, ID.NUMBER_WORD,
ID.REGISTER_WORD, ID.NUMBER_BYTE,
// Ïàìÿòü - Çíà÷åíèå
ID.VAR_BYTE, ID.NUMBER_BYTE,
ID.VAR_WORD, ID.NUMBER_WORD,
ID.VAR_WORD, ID.NUMBER_BYTE,
};
@Override @Override
public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber {
if (ids[0] != getId()) return false; if (ids[0] != getId()) return false;
if (ids.length < 4) throw new FewArgumentsException(lineNumber); if (ids.length < 4) throw new FewArgumentsException(lineNumber);
else if (ids.length > 4) throw new TooManyArgumentsException(lineNumber); if (ids.length > 4) throw new TooManyArgumentsException(lineNumber);
if (ids[2] != ID.COMMA) throw new CommaExpectedException(lineNumber); if (ids[2] != ID.COMMA) throw new CommaExpectedException(lineNumber);
int[] pairs = new int[] {
// Ðåãèñòð - Ðåãèñòð
ID.REGISTER_BYTE, ID.REGISTER_BYTE,
ID.REGISTER_WORD, ID.REGISTER_WORD,
ID.REGISTER_WORD, ID.REGISTER_BYTE,
// Ðåãèñòð - Ïàìÿòü
ID.REGISTER_BYTE, ID.VAR_BYTE,
ID.REGISTER_WORD, ID.VAR_WORD,
ID.REGISTER_WORD, ID.VAR_BYTE,
// Ïàìÿòü - Ðåãèñòð
ID.VAR_BYTE, ID.REGISTER_BYTE,
ID.VAR_WORD, ID.REGISTER_WORD,
ID.VAR_WORD, ID.REGISTER_BYTE,
// Ðåãèñòð - Çíà÷åíèå
ID.REGISTER_BYTE, ID.NUMBER_BYTE,
ID.REGISTER_WORD, ID.NUMBER_WORD,
ID.REGISTER_WORD, ID.NUMBER_BYTE,
// Ïàìÿòü - Çíà÷åíèå
ID.VAR_BYTE, ID.NUMBER_BYTE,
ID.VAR_WORD, ID.NUMBER_WORD,
ID.VAR_WORD, ID.NUMBER_BYTE,
};
boolean correct = false; boolean correct = false;
for(int i = 0; i < pairs.length; i += 2) { for (int i = 0; i < PAIRS.length; i += 2) {
if ( (ids[1] == pairs[i]) && (ids[3] == pairs[i+1]) ) { if ( (ids[1] == PAIRS[i]) && (ids[3] == PAIRS[i+1]) ) {
correct = true; correct = true;
break; break;
} }
@ -103,8 +104,8 @@ public final class Add extends Directive implements ISyntaxChecker, IListingGene
modreg <<= 6; modreg <<= 6;
// r/m // r/m
if (strs[1].toLowerCase().contains("si")) modreg |= 0b100; if (strs[1].toLowerCase(Locale.ENGLISH).contains("si")) modreg |= 0b100;
else if (strs[1].toLowerCase().contains("di")) modreg |= 0b101; else if (strs[1].toLowerCase(Locale.ENGLISH).contains("di")) modreg |= 0b101;
else modreg |= 0b110; else modreg |= 0b110;
sb.append(ListingGenerateHelper.toHexString(val)) sb.append(ListingGenerateHelper.toHexString(val))

View File

@ -22,7 +22,7 @@ public final class Idiv extends Directive implements ISyntaxChecker, IListingGen
if (ids[0] != getId()) return false; if (ids[0] != getId()) return false;
if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1);
else if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1); if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1);
if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) && if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) &&
(ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) { (ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) {

View File

@ -22,7 +22,7 @@ public final class Mul extends Directive implements ISyntaxChecker, IListingGene
if (ids[0] != getId()) return false; if (ids[0] != getId()) return false;
if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1);
else if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1); if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1);
if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) && if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) &&
(ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) { (ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) {

View File

@ -28,7 +28,6 @@ public final class Push extends Directive implements ISyntaxChecker, IListingGen
} }
} }
return true; return true;
} }
@Override @Override

View File

@ -31,7 +31,7 @@ public final class Variable extends Directive implements ISyntaxChecker, IListin
if (ids[0] != getId()) return false; if (ids[0] != getId()) return false;
if (ids.length < 3) throw new FewArgumentsException(lineNumber, 2); if (ids.length < 3) throw new FewArgumentsException(lineNumber, 2);
else if (ids.length > 3) throw new TooManyArgumentsException(lineNumber, 2); if (ids.length > 3) throw new TooManyArgumentsException(lineNumber, 2);
boolean db = ( (ids[1] == ID.DB) && boolean db = ( (ids[1] == ID.DB) &&
((ids[2] == ID.NUMBER_BYTE) || (ids[2] == ID.NUMBER_INFINITY)) ); ((ids[2] == ID.NUMBER_BYTE) || (ids[2] == ID.NUMBER_INFINITY)) );