From b1d8591410d763eb4292f323f2616760cdf57cec Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 22 Aug 2014 11:56:18 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=BE=D0=BF=D1=82=D0=B8?= =?UTF-8?q?=D0=BC=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/com/annimon/asm/AnalyzerPanel.java | 282 +++++++++--------- src/com/annimon/asm/DirectiveConverter.java | 198 ++++++------ src/com/annimon/asm/LexicLine.java | 32 +- src/com/annimon/asm/LexicTable.java | 94 +++--- src/com/annimon/asm/LexicalAnalyzer.java | 224 +++++++------- .../annimon/asm/ListingGenerateHelper.java | 214 ++++++------- src/com/annimon/asm/ListingGenerator.java | 126 ++++---- src/com/annimon/asm/Main.java | 44 +-- src/com/annimon/asm/SyntaxAnalyzer.java | 88 +++--- src/com/annimon/asm/Var.java | 50 ++-- src/com/annimon/asm/VarTable.java | 104 +++---- src/com/annimon/asm/directives/Add.java | 2 +- .../annimon/asm/directives/ByteRegister.java | 2 +- src/com/annimon/asm/directives/ByteValue.java | 2 +- src/com/annimon/asm/directives/Comma.java | 26 +- src/com/annimon/asm/directives/DB.java | 26 +- src/com/annimon/asm/directives/DW.java | 26 +- src/com/annimon/asm/directives/Idiv.java | 154 +++++----- .../annimon/asm/directives/InfinityValue.java | 2 +- src/com/annimon/asm/directives/Mul.java | 154 +++++----- src/com/annimon/asm/directives/Pop.java | 128 ++++---- src/com/annimon/asm/directives/Push.java | 130 ++++---- src/com/annimon/asm/directives/Variable.java | 122 ++++---- .../annimon/asm/directives/WordRegister.java | 2 +- src/com/annimon/asm/directives/WordValue.java | 2 +- .../exceptions/CommaExpectedException.java | 24 +- .../exceptions/ExceptionWithLineNumber.java | 42 +-- .../asm/exceptions/FewArgumentsException.java | 32 +- .../exceptions/TooManyArgumentsException.java | 32 +- .../exceptions/WrongArgumentException.java | 24 +- 30 files changed, 1194 insertions(+), 1194 deletions(-) diff --git a/src/com/annimon/asm/AnalyzerPanel.java b/src/com/annimon/asm/AnalyzerPanel.java index 3c25b7a..8d0f05b 100644 --- a/src/com/annimon/asm/AnalyzerPanel.java +++ b/src/com/annimon/asm/AnalyzerPanel.java @@ -1,141 +1,141 @@ -package com.annimon.asm; - -import com.annimon.asm.exceptions.ExceptionWithLineNumber; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextPane; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import javax.swing.text.BadLocationException; -import javax.swing.text.JTextComponent; -import javax.swing.text.Utilities; - -/** - * Основная панель приложения. - * @author aNNiMON - */ -public class AnalyzerPanel extends JPanel { - - private JLabel lineNumberLabel; - private JTextPane textPane; - private JButton analyzeButton; - - public AnalyzerPanel() { - lineNumberLabel = new JLabel("Line: 1"); - initTextPane(); - initAnalyzeButton(); - - setLayout(new BorderLayout(0, 0)); - add(lineNumberLabel, BorderLayout.NORTH); - add(new JScrollPane(textPane)); - add(analyzeButton, BorderLayout.SOUTH); - } - - public AnalyzerPanel(String text) { - textPane = new JTextPane(); - textPane.setPreferredSize(new Dimension(300, 300)); - textPane.setFont(new Font("Consolas", Font.PLAIN, 14)); - textPane.setText(text); - - setLayout(new BorderLayout(0, 0)); - add(new JScrollPane(textPane)); - } - - private void initTextPane() { - textPane = new JTextPane(); - textPane.setPreferredSize(new Dimension(300, 350)); - textPane.addCaretListener(new CaretListener() { - - @Override - public void caretUpdate(CaretEvent caretEvent) { - // Вывести позицию каретки в lineNumberLabel. - JTextComponent textComponent = (JTextComponent)caretEvent.getSource(); - - int pos = caretEvent.getDot(); - int rowNumber = (pos == 0) ? 1 : 0; - try { - int offset = pos; - while (offset > 0) { - offset = Utilities.getRowStart(textComponent, offset) - 1; - rowNumber++; - } - } catch (BadLocationException ex) {} - - lineNumberLabel.setText("Line: " + rowNumber); - } - }); - textPane.setFont(new Font("Consolas", Font.PLAIN, 14)); - textPane.setText(getTextFromResource("/test.asm")); - } - - private void initAnalyzeButton() { - analyzeButton = new JButton("Analyze"); - analyzeButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent actionEvent) { - String allText = textPane.getText(); - - // Лексический анализ - переводим набор директив в кодовую таблицу. - LexicalAnalyzer lex = new LexicalAnalyzer(allText); - lex.analyze(); - - // Синтаксический анализ - проверка правильности набора директив. - SyntaxAnalyzer syn = new SyntaxAnalyzer(lex.getLexicTable()); - try { - syn.analyze(); - } catch (ExceptionWithLineNumber ex) { - showMessageBox("Error", ex.getMessage(), true); - return; - } - - //showMessageBox("Info","Source is correct!", false); - // Генерируем листинг. - ListingGenerator gen = new ListingGenerator(lex.getLexicTable(), lex.getVarTable(), lex.getLines()); - String listing = gen.generate(); - - showListing(listing); - } - }); - } - - private void showMessageBox(String title, String text, boolean errorMessage) { - int msgType = errorMessage ? JOptionPane.ERROR_MESSAGE : - JOptionPane.INFORMATION_MESSAGE; - JOptionPane.showMessageDialog(this, text, title, msgType); - } - - private void showListing(String listing) { - JOptionPane.showMessageDialog(this, new AnalyzerPanel(listing), - "Listing", JOptionPane.PLAIN_MESSAGE); - } - - private String getTextFromResource(String res) { - try { - InputStream is = getClass().getResourceAsStream(res); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - - StringBuilder text = new StringBuilder(); - String line; - while( (line = reader.readLine()) != null ) { - text.append(line).append(System.lineSeparator()); - } - - reader.close(); - return text.toString(); - } catch (IOException ex) {} - return ""; - } -} +package com.annimon.asm; + +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import javax.swing.text.Utilities; + +/** + * Основная панель приложения. + * @author aNNiMON + */ +public final class AnalyzerPanel extends JPanel { + + private JLabel lineNumberLabel; + private JTextPane textPane; + private JButton analyzeButton; + + public AnalyzerPanel() { + lineNumberLabel = new JLabel("Line: 1"); + initTextPane(); + initAnalyzeButton(); + + setLayout(new BorderLayout(0, 0)); + add(lineNumberLabel, BorderLayout.NORTH); + add(new JScrollPane(textPane)); + add(analyzeButton, BorderLayout.SOUTH); + } + + public AnalyzerPanel(String text) { + textPane = new JTextPane(); + textPane.setPreferredSize(new Dimension(300, 300)); + textPane.setFont(new Font("Consolas", Font.PLAIN, 14)); + textPane.setText(text); + + setLayout(new BorderLayout(0, 0)); + add(new JScrollPane(textPane)); + } + + private void initTextPane() { + textPane = new JTextPane(); + textPane.setPreferredSize(new Dimension(300, 350)); + textPane.addCaretListener(new CaretListener() { + + @Override + public void caretUpdate(CaretEvent caretEvent) { + // Вывести позицию каретки в lineNumberLabel. + JTextComponent textComponent = (JTextComponent)caretEvent.getSource(); + + int pos = caretEvent.getDot(); + int rowNumber = (pos == 0) ? 1 : 0; + try { + int offset = pos; + while (offset > 0) { + offset = Utilities.getRowStart(textComponent, offset) - 1; + rowNumber++; + } + } catch (BadLocationException ex) {} + + lineNumberLabel.setText("Line: " + rowNumber); + } + }); + textPane.setFont(new Font("Consolas", Font.PLAIN, 14)); + textPane.setText(getTextFromResource("/test.asm")); + } + + private void initAnalyzeButton() { + analyzeButton = new JButton("Analyze"); + analyzeButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent actionEvent) { + String allText = textPane.getText(); + + // Лексический анализ - переводим набор директив в кодовую таблицу. + LexicalAnalyzer lex = new LexicalAnalyzer(allText); + lex.analyze(); + + // Синтаксический анализ - проверка правильности набора директив. + SyntaxAnalyzer syn = new SyntaxAnalyzer(lex.getLexicTable()); + try { + syn.analyze(); + } catch (ExceptionWithLineNumber ex) { + showMessageBox("Error", ex.getMessage(), true); + return; + } + + //showMessageBox("Info","Source is correct!", false); + // Генерируем листинг. + ListingGenerator gen = new ListingGenerator(lex.getLexicTable(), lex.getVarTable(), lex.getLines()); + String listing = gen.generate(); + + showListing(listing); + } + }); + } + + private void showMessageBox(String title, String text, boolean errorMessage) { + int msgType = errorMessage ? JOptionPane.ERROR_MESSAGE : + JOptionPane.INFORMATION_MESSAGE; + JOptionPane.showMessageDialog(this, text, title, msgType); + } + + private void showListing(String listing) { + JOptionPane.showMessageDialog(this, new AnalyzerPanel(listing), + "Listing", JOptionPane.PLAIN_MESSAGE); + } + + private String getTextFromResource(String res) { + try { + InputStream is = getClass().getResourceAsStream(res); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + + StringBuilder text = new StringBuilder(); + String line; + while( (line = reader.readLine()) != null ) { + text.append(line).append(System.lineSeparator()); + } + + reader.close(); + return text.toString(); + } catch (IOException ex) {} + return ""; + } +} diff --git a/src/com/annimon/asm/DirectiveConverter.java b/src/com/annimon/asm/DirectiveConverter.java index da6c017..750d790 100644 --- a/src/com/annimon/asm/DirectiveConverter.java +++ b/src/com/annimon/asm/DirectiveConverter.java @@ -1,99 +1,99 @@ -package com.annimon.asm; - -import com.annimon.asm.directives.*; -import java.util.ArrayList; - -/** - * Конвертер директив. - * @author aNNiMON - */ -public class DirectiveConverter { - - private static final Directive[] DIRECTIVES = { - new Comma(), - new DB(), new DW(), - new InfinityValue(), new ByteValue(), new WordValue(), - new Add(), new Mul(), new Push(), new Pop(), new Idiv(), - new ByteRegister(), new WordRegister(), - new Variable() - }; - - /** - * Конвертировать директиву в её идентификатор. - * @param text директива (dw, push, 0 и т.д.) - * @return идентификатор директивы. - */ - public static int convert(String text) { - for (int i = 0; i < DIRECTIVES.length; i++) { - if (DIRECTIVES[i].isDirective(text)) { - return DIRECTIVES[i].getId(); - } - } - - return -1; - } - - /** - * Получить значение числа из строки. - * @param text строка с числом. - * @return Integer число. - */ - public static Integer parseInteger(String text) { - int value; - if (text.toLowerCase().endsWith("h")) { - char first = Character.toLowerCase(text.charAt(0)); - if ( (first >= 'a') && (first <= 'f') ) { - // Первый символ hex числа не должен быть от a до f - return null; - } - - String hex = text.substring(0, text.length() - 1); - try { - value = Integer.parseInt(hex, 16); - return value; - } catch (NumberFormatException nfe) { - return null; - } - } - try { - value = Integer.parseInt(text); - return value; - } catch (NumberFormatException nfe) { - return null; - } - } - - /** - * Разбить строку на подстроки с учётом запятых. - * @param text текст. - * @return массив строк. - */ - public static String[] split(String text) { - ArrayList parts = new ArrayList<>(); - int length = text.length(); - StringBuilder sb = new StringBuilder(); - for (int ch = 0; ch < length; ch++) { - int i = text.charAt(ch); - if (i == ' ') { - if (sb.length() > 0) { - parts.add(sb.toString().trim()); - sb.setLength(0); - } - } else if (i == ',') { - if (sb.length() > 0) { - parts.add(sb.toString().trim()); - parts.add(","); - sb.setLength(0); - } - } else { - sb.append((char) i); - } - } - if (sb.length() > 0) { - parts.add(sb.toString().trim()); - } - String[] m = new String[parts.size()]; - m = parts.toArray(m); - return m; - } -} +package com.annimon.asm; + +import com.annimon.asm.directives.*; +import java.util.ArrayList; + +/** + * Конвертер директив. + * @author aNNiMON + */ +public final class DirectiveConverter { + + private static final Directive[] DIRECTIVES = { + new Comma(), + new DB(), new DW(), + new InfinityValue(), new ByteValue(), new WordValue(), + new Add(), new Mul(), new Push(), new Pop(), new Idiv(), + new ByteRegister(), new WordRegister(), + new Variable() + }; + + /** + * Конвертировать директиву в её идентификатор. + * @param text директива (dw, push, 0 и т.д.) + * @return идентификатор директивы. + */ + public static int convert(String text) { + for (Directive dir : DIRECTIVES) { + if (dir.isDirective(text)) { + return dir.getId(); + } + } + + return -1; + } + + /** + * Получить значение числа из строки. + * @param text строка с числом. + * @return Integer число. + */ + public static Integer parseInteger(String text) { + int value; + if (text.toLowerCase().endsWith("h")) { + char first = Character.toLowerCase(text.charAt(0)); + if ( (first >= 'a') && (first <= 'f') ) { + // Первый символ hex числа не должен быть от a до f + return null; + } + + String hex = text.substring(0, text.length() - 1); + try { + value = Integer.parseInt(hex, 16); + return value; + } catch (NumberFormatException nfe) { + return null; + } + } + try { + value = Integer.parseInt(text); + return value; + } catch (NumberFormatException nfe) { + return null; + } + } + + /** + * Разбить строку на подстроки с учётом запятых. + * @param text текст. + * @return массив строк. + */ + public static String[] split(String text) { + ArrayList parts = new ArrayList<>(); + int length = text.length(); + StringBuilder sb = new StringBuilder(); + for (int ch = 0; ch < length; ch++) { + int i = text.charAt(ch); + if (i == ' ') { + if (sb.length() > 0) { + parts.add(sb.toString().trim()); + sb.setLength(0); + } + } else if (i == ',') { + if (sb.length() > 0) { + parts.add(sb.toString().trim()); + parts.add(","); + sb.setLength(0); + } + } else { + sb.append((char) i); + } + } + if (sb.length() > 0) { + parts.add(sb.toString().trim()); + } + String[] m = new String[parts.size()]; + m = parts.toArray(m); + return m; + } +} diff --git a/src/com/annimon/asm/LexicLine.java b/src/com/annimon/asm/LexicLine.java index 935e77a..218e11e 100644 --- a/src/com/annimon/asm/LexicLine.java +++ b/src/com/annimon/asm/LexicLine.java @@ -1,16 +1,16 @@ -package com.annimon.asm; - -/** - * - * @author aNNiMON - */ -public class LexicLine { - - int lineNumber; - int[] line; - - public LexicLine(int lineNumber, int[] line) { - this.lineNumber = lineNumber; - this.line = line; - } -} +package com.annimon.asm; + +/** + * + * @author aNNiMON + */ +public final class LexicLine { + + int lineNumber; + int[] line; + + public LexicLine(int lineNumber, int[] line) { + this.lineNumber = lineNumber; + this.line = line; + } +} diff --git a/src/com/annimon/asm/LexicTable.java b/src/com/annimon/asm/LexicTable.java index e01828c..e2844b6 100644 --- a/src/com/annimon/asm/LexicTable.java +++ b/src/com/annimon/asm/LexicTable.java @@ -1,47 +1,47 @@ -package com.annimon.asm; - -import java.util.ArrayList; - -/** - * @author aNNiMON - */ -public class LexicTable { - - private ArrayList lexicLines; - - public LexicTable() { - lexicLines = new ArrayList<>(); - } - - public void addLexicLine(int lineNumber, int[] line) { - lexicLines.add(new LexicLine(lineNumber, line)); - } - - public int getSize() { - return lexicLines.size(); - } - - public LexicLine getLexicAt(int pos) { - return lexicLines.get(pos); - } - - public void updateLexicAt(int pos, LexicLine line) { - lexicLines.set(pos, line); - } - - @Override - public String toString() { - StringBuilder text = new StringBuilder(); - for(LexicLine lexic : lexicLines) { - text.append(lexic.lineNumber).append(':'); - int[] array = lexic.line; - for (int i = 0; i < array.length; i++) { - text.append(" "); - text.append(array[i]); - } - text.append(System.lineSeparator()); - } - return text.toString(); - } - -} +package com.annimon.asm; + +import java.util.ArrayList; + +/** + * @author aNNiMON + */ +public final class LexicTable { + + private final ArrayList lexicLines; + + public LexicTable() { + lexicLines = new ArrayList<>(); + } + + public void addLexicLine(int lineNumber, int[] line) { + lexicLines.add(new LexicLine(lineNumber, line)); + } + + public int getSize() { + return lexicLines.size(); + } + + public LexicLine getLexicAt(int pos) { + return lexicLines.get(pos); + } + + public void updateLexicAt(int pos, LexicLine line) { + lexicLines.set(pos, line); + } + + @Override + public String toString() { + final StringBuilder text = new StringBuilder(); + for(LexicLine lexic : lexicLines) { + text.append(lexic.lineNumber).append(':'); + int[] array = lexic.line; + for (int i = 0; i < array.length; i++) { + text.append(" "); + text.append(array[i]); + } + text.append(System.lineSeparator()); + } + return text.toString(); + } + +} diff --git a/src/com/annimon/asm/LexicalAnalyzer.java b/src/com/annimon/asm/LexicalAnalyzer.java index 1525e69..76db76b 100644 --- a/src/com/annimon/asm/LexicalAnalyzer.java +++ b/src/com/annimon/asm/LexicalAnalyzer.java @@ -1,112 +1,112 @@ -package com.annimon.asm; - -import com.annimon.asm.directives.ID; - -/** - * Лексический анализатор. - * @author aNNiMON - */ -public class LexicalAnalyzer { - - private String[] lines; - private LexicTable lexicTable; - private VarTable varTable; - - public LexicalAnalyzer(String text) { - lines = text.split(System.lineSeparator()); - - lexicTable = new LexicTable(); - varTable = new VarTable(); - } - - public LexicTable getLexicTable() { - return lexicTable; - } - - public VarTable getVarTable() { - return varTable; - } - - public String[] getLines() { - return lines; - } - - public void analyze() { - for (int i = 0; i < lines.length; i++) { - analyzeLine(i); - } - analyzeVariables(); - System.out.println(lexicTable.toString()); - } - - private void analyzeLine(int lineNumber) { - String line = lines[lineNumber]; - // Если строка не содержит команд - пропускаем. - if (line.isEmpty()) return; - String[] parts = DirectiveConverter.split(line); - - // Конвертируем директивы в соответствующие им идентификаторы. - int length = parts.length; - int[] lexicIds = new int[length]; - for (int i = 0; i < length; i++) { - lexicIds[i] = DirectiveConverter.convert(parts[i].trim()); - } - - // Добавляем полученную строку в таблицу. - lexicTable.addLexicLine(lineNumber+1, lexicIds); - } - - private void analyzeVariables() { - // Добавляем переменные в таблицу. - for (int i = 0; i < lexicTable.getSize(); i++) { - LexicLine line = lexicTable.getLexicAt(i); - addVariableToTable(line); - } - // Сопоставляем типы переменных. - for (int i = 0; i < lexicTable.getSize(); i++) { - LexicLine line = lexicTable.getLexicAt(i); - line = assignVariableTypes(line); - lexicTable.updateLexicAt(i, line); - } - } - - private void addVariableToTable(LexicLine lexicLine) { - if (lexicLine.line[0] != ID.VAR) return; - if (lexicLine.line.length != 3) return; - - String line = lines[lexicLine.lineNumber - 1]; - // Если строка не содержит команд - пропускаем. - if (line.isEmpty()) return; - String[] parts = DirectiveConverter.split(line); - if (parts.length != 3) return; - - String varName = parts[0].trim(); - int typeId = lexicLine.line[1]; - String value = parts[2].trim(); - - varTable.addVariable(varName, typeId, value); - } - - private LexicLine assignVariableTypes(LexicLine lexicLine) { - // Для переменных назначаем их тип. - int[] lexicIds = lexicLine.line; - - for (int i = 0; i < lexicIds.length; i++) { - if (lexicIds[i] == ID.VAR) { - // Назначаем тип из таблицы переменных. - String line = lines[lexicLine.lineNumber - 1]; - if (line.isEmpty()) continue; - String[] parts = DirectiveConverter.split(line); - if (parts.length != lexicIds.length) continue; - - lexicIds[i] = varTable.getTypeOfVariable(parts[i]); - } - } - lexicLine.line = lexicIds; - - return lexicLine; - } - - - -} +package com.annimon.asm; + +import com.annimon.asm.directives.ID; + +/** + * Лексический анализатор. + * @author aNNiMON + */ +public final class LexicalAnalyzer { + + private final String[] lines; + private final LexicTable lexicTable; + private final VarTable varTable; + + public LexicalAnalyzer(String text) { + lines = text.split(System.lineSeparator()); + + lexicTable = new LexicTable(); + varTable = new VarTable(); + } + + public LexicTable getLexicTable() { + return lexicTable; + } + + public VarTable getVarTable() { + return varTable; + } + + public String[] getLines() { + return lines; + } + + public void analyze() { + for (int i = 0; i < lines.length; i++) { + analyzeLine(i); + } + analyzeVariables(); + System.out.println(lexicTable.toString()); + } + + private void analyzeLine(int lineNumber) { + final String line = lines[lineNumber]; + // Если строка не содержит команд - пропускаем. + if (line.isEmpty()) return; + String[] parts = DirectiveConverter.split(line); + + // Конвертируем директивы в соответствующие им идентификаторы. + final int length = parts.length; + final int[] lexicIds = new int[length]; + for (int i = 0; i < length; i++) { + lexicIds[i] = DirectiveConverter.convert(parts[i].trim()); + } + + // Добавляем полученную строку в таблицу. + lexicTable.addLexicLine(lineNumber+1, lexicIds); + } + + private void analyzeVariables() { + // Добавляем переменные в таблицу. + for (int i = 0; i < lexicTable.getSize(); i++) { + LexicLine line = lexicTable.getLexicAt(i); + addVariableToTable(line); + } + // Сопоставляем типы переменных. + for (int i = 0; i < lexicTable.getSize(); i++) { + LexicLine line = lexicTable.getLexicAt(i); + line = assignVariableTypes(line); + lexicTable.updateLexicAt(i, line); + } + } + + private void addVariableToTable(LexicLine lexicLine) { + if (lexicLine.line[0] != ID.VAR) return; + if (lexicLine.line.length != 3) return; + + String line = lines[lexicLine.lineNumber - 1]; + // Если строка не содержит команд - пропускаем. + if (line.isEmpty()) return; + String[] parts = DirectiveConverter.split(line); + if (parts.length != 3) return; + + String varName = parts[0].trim(); + int typeId = lexicLine.line[1]; + String value = parts[2].trim(); + + varTable.addVariable(varName, typeId, value); + } + + private LexicLine assignVariableTypes(LexicLine lexicLine) { + // Для переменных назначаем их тип. + int[] lexicIds = lexicLine.line; + + for (int i = 0; i < lexicIds.length; i++) { + if (lexicIds[i] == ID.VAR) { + // Назначаем тип из таблицы переменных. + String line = lines[lexicLine.lineNumber - 1]; + if (line.isEmpty()) continue; + String[] parts = DirectiveConverter.split(line); + if (parts.length != lexicIds.length) continue; + + lexicIds[i] = varTable.getTypeOfVariable(parts[i]); + } + } + lexicLine.line = lexicIds; + + return lexicLine; + } + + + +} diff --git a/src/com/annimon/asm/ListingGenerateHelper.java b/src/com/annimon/asm/ListingGenerateHelper.java index c8d61ca..cd4dc45 100644 --- a/src/com/annimon/asm/ListingGenerateHelper.java +++ b/src/com/annimon/asm/ListingGenerateHelper.java @@ -1,107 +1,107 @@ -package com.annimon.asm; - -import com.annimon.asm.directives.ID; - -/** - * - * @author aNNiMON - */ -public class ListingGenerateHelper { - - private static final String[] SEGMENT_REGISTERS = { - "es", "cs", "ss", "ds" - }; - - /** - * Конвертировать число в строку в HEX формате. - * @param value число - * @return строковое значение числа в HEX. - */ - public static String toHexString(int value) { - String str = Integer.toString(value, 16).toUpperCase(); - if (str.length() == 1) str = "0" + str; - else if (str.length() == 3) str = "0" + str; - return str; - } - - /** - * Записать слово в Little Endian формате. - * @param value число 2 байта. - * @return строка "LL HH" - */ - public static String toLittleEndianString(short value) { - return toHexString(value & 0xFF) + " " + - toHexString((value >> 8) & 0xFF); - } - - /** - * Сконвертировать текст в слово и записать его в Little Endian формате. - * @param text строка с числом. - * @return строка "LL HH" либо "XX" в зависимости от размера. - */ - public static String toLittleEndianString(String text) { - Integer value = DirectiveConverter.parseInteger(text); - if (value == null) return ""; - - if ( (-128 <= value.intValue()) && (value.intValue() <= 255) ) { - return toHexString(value); - } - - return toLittleEndianString(value.shortValue()); - } - - /** - * Проверка, является ли операнд регистром или памятью (r/m). - * @param id тип операнда. - * @return true - операнд регистр или память. - */ - public static boolean isRegisterOrMemory(int id) { - boolean isMemory = ( (id == ID.VAR_BYTE) || (id == ID.VAR_WORD) ); - return (isRegister(id) || isMemory); - } - - /** - * Проверка, является ли операнд регистром. - * @param id тип операнда. - * @return true - операнд регистр. - */ - public static boolean isRegister(int id) { - return ( (id == ID.REGISTER_BYTE) || (id == ID.REGISTER_WORD) ); - } - - /** - * Получить код регистра. - * @param register строковое значение регистра. - * @return код регистра (3 бита). - */ - public static byte getRegisterCode(String register) { - String reg = register.toLowerCase(); - - switch (reg) { - case "ax": case "al": return 0b000; - case "cx": case "cl": return 0b001; - case "dx": case "dl": return 0b010; - case "bx": case "bl": return 0b011; - case "sp": case "ah": return 0b100; - case "bp": case "ch": return 0b101; - case "si": case "dh": return 0b110; - case "di": case "bh": return 0b111; - } - - return 0; - } - - /** - * Получить код сегментного регистра. - * @param register строковое значение регистра. - * @return код сегментного регистра, либо -1, если регистр не сегментный. - */ - public static byte getSegmentRegisterCode(String register) { - String reg = register.toLowerCase(); - for (byte i = 0; i < SEGMENT_REGISTERS.length; i++) { - if (reg.equals(SEGMENT_REGISTERS[i])) return i; - } - return -1; - } - -} +package com.annimon.asm; + +import com.annimon.asm.directives.ID; + +/** + * + * @author aNNiMON + */ +public final class ListingGenerateHelper { + + private static final String[] SEGMENT_REGISTERS = { + "es", "cs", "ss", "ds" + }; + + /** + * Конвертировать число в строку в HEX формате. + * @param value число + * @return строковое значение числа в HEX. + */ + public static String toHexString(int value) { + String str = Integer.toString(value, 16).toUpperCase(); + if (str.length() == 1) str = "0" + str; + else if (str.length() == 3) str = "0" + str; + return str; + } + + /** + * Записать слово в Little Endian формате. + * @param value число 2 байта. + * @return строка "LL HH" + */ + public static String toLittleEndianString(short value) { + return toHexString(value & 0xFF) + " " + + toHexString((value >> 8) & 0xFF); + } + + /** + * Сконвертировать текст в слово и записать его в Little Endian формате. + * @param text строка с числом. + * @return строка "LL HH" либо "XX" в зависимости от размера. + */ + public static String toLittleEndianString(String text) { + final Integer value = DirectiveConverter.parseInteger(text); + if (value == null) return ""; + + if ( (-128 <= value) && (value <= 255) ) { + return toHexString(value); + } + + return toLittleEndianString(value.shortValue()); + } + + /** + * Проверка, является ли операнд регистром или памятью (r/m). + * @param id тип операнда. + * @return true - операнд регистр или память. + */ + public static boolean isRegisterOrMemory(int id) { + boolean isMemory = ( (id == ID.VAR_BYTE) || (id == ID.VAR_WORD) ); + return (isRegister(id) || isMemory); + } + + /** + * Проверка, является ли операнд регистром. + * @param id тип операнда. + * @return true - операнд регистр. + */ + public static boolean isRegister(int id) { + return ( (id == ID.REGISTER_BYTE) || (id == ID.REGISTER_WORD) ); + } + + /** + * Получить код регистра. + * @param register строковое значение регистра. + * @return код регистра (3 бита). + */ + public static byte getRegisterCode(String register) { + final String reg = register.toLowerCase(); + + switch (reg) { + case "ax": case "al": return 0b000; + case "cx": case "cl": return 0b001; + case "dx": case "dl": return 0b010; + case "bx": case "bl": return 0b011; + case "sp": case "ah": return 0b100; + case "bp": case "ch": return 0b101; + case "si": case "dh": return 0b110; + case "di": case "bh": return 0b111; + } + + return 0; + } + + /** + * Получить код сегментного регистра. + * @param register строковое значение регистра. + * @return код сегментного регистра, либо -1, если регистр не сегментный. + */ + public static byte getSegmentRegisterCode(String register) { + final String reg = register.toLowerCase(); + for (byte i = 0; i < SEGMENT_REGISTERS.length; i++) { + if (reg.equals(SEGMENT_REGISTERS[i])) return i; + } + return -1; + } + +} diff --git a/src/com/annimon/asm/ListingGenerator.java b/src/com/annimon/asm/ListingGenerator.java index 01a339e..ed1407f 100644 --- a/src/com/annimon/asm/ListingGenerator.java +++ b/src/com/annimon/asm/ListingGenerator.java @@ -1,63 +1,63 @@ -package com.annimon.asm; - -import com.annimon.asm.directives.Add; -import com.annimon.asm.directives.ID; -import com.annimon.asm.directives.IListingGenerator; -import com.annimon.asm.directives.Idiv; -import com.annimon.asm.directives.Mul; -import com.annimon.asm.directives.Pop; -import com.annimon.asm.directives.Push; -import com.annimon.asm.directives.Variable; - -/** - * Генерирование листинга. - * @author aNNiMON - */ -public class ListingGenerator { - - private static final IListingGenerator[] DIRECTIVES = { - new Variable(), - new Add(), new Mul(), new Pop(), new Push(), new Idiv() - }; - - private LexicTable lexicTable; - private VarTable varTable; - private String[] lines; - - public ListingGenerator(LexicTable lexicTable, VarTable varTable, String[] lines) { - this.lexicTable = lexicTable; - this.varTable = varTable; - this.lines = lines; - } - - public String generate() { - StringBuilder text = new StringBuilder(); - short offset = VarTable.getOffset(); - - for (int i = 0; i < lexicTable.getSize(); i++) { - LexicLine line = lexicTable.getLexicAt(i); - String[] parts = DirectiveConverter.split(lines[line.lineNumber - 1]); - - String strLine = generateLine(line.lineNumber, line.line, parts).trim(); - // Вывод адреса для всех директив, кроме переменных. - if ( (line.line[0] != ID.VAR_BYTE) && (line.line[0] != ID.VAR_WORD) ) { - text.append(ListingGenerateHelper.toHexString(offset)).append(" "); - int lineSize = strLine.split(" ").length; - offset += lineSize; - } - text.append(strLine); - text.append(System.lineSeparator()); - } - - return text.toString(); - } - - private String generateLine(int lineNumber, int[] lexic, String[] parts) { - for (int i = 0; i < DIRECTIVES.length; i++) { - String text = DIRECTIVES[i].generate(lineNumber, lexic, parts, varTable); - if (!text.isEmpty()) return text; - } - return ""; - } - -} +package com.annimon.asm; + +import com.annimon.asm.directives.Add; +import com.annimon.asm.directives.ID; +import com.annimon.asm.directives.IListingGenerator; +import com.annimon.asm.directives.Idiv; +import com.annimon.asm.directives.Mul; +import com.annimon.asm.directives.Pop; +import com.annimon.asm.directives.Push; +import com.annimon.asm.directives.Variable; + +/** + * Генерирование листинга. + * @author aNNiMON + */ +public final class ListingGenerator { + + private static final IListingGenerator[] DIRECTIVES = { + new Variable(), + new Add(), new Mul(), new Pop(), new Push(), new Idiv() + }; + + private final LexicTable lexicTable; + private final VarTable varTable; + private final String[] lines; + + public ListingGenerator(LexicTable lexicTable, VarTable varTable, String[] lines) { + this.lexicTable = lexicTable; + this.varTable = varTable; + this.lines = lines; + } + + public String generate() { + final StringBuilder text = new StringBuilder(); + short offset = VarTable.getOffset(); + + for (int i = 0; i < lexicTable.getSize(); i++) { + LexicLine line = lexicTable.getLexicAt(i); + String[] parts = DirectiveConverter.split(lines[line.lineNumber - 1]); + + String strLine = generateLine(line.lineNumber, line.line, parts).trim(); + // Вывод адреса для всех директив, кроме переменных. + if ( (line.line[0] != ID.VAR_BYTE) && (line.line[0] != ID.VAR_WORD) ) { + text.append(ListingGenerateHelper.toHexString(offset)).append(" "); + int lineSize = strLine.split(" ").length; + offset += lineSize; + } + text.append(strLine); + text.append(System.lineSeparator()); + } + + return text.toString(); + } + + private String generateLine(int lineNumber, int[] lexic, String[] parts) { + for (IListingGenerator dir : DIRECTIVES) { + String text = dir.generate(lineNumber, lexic, parts, varTable); + if (!text.isEmpty()) return text; + } + return ""; + } + +} diff --git a/src/com/annimon/asm/Main.java b/src/com/annimon/asm/Main.java index cac71a4..25b2036 100644 --- a/src/com/annimon/asm/Main.java +++ b/src/com/annimon/asm/Main.java @@ -1,22 +1,22 @@ -package com.annimon.asm; - -import javax.swing.JFrame; - -/** - * @author aNNiMON - */ -public class Main extends JFrame { - - public static void main(String[] args) { - new Main().setVisible(true); - } - - public Main() { - super("Assembler analyzer"); - setDefaultCloseOperation(EXIT_ON_CLOSE); - - add(new AnalyzerPanel()); - pack(); - } - -} +package com.annimon.asm; + +import javax.swing.JFrame; + +/** + * @author aNNiMON + */ +public final class Main extends JFrame { + + public static void main(String[] args) { + new Main().setVisible(true); + } + + public Main() { + super("Assembler analyzer"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + + add(new AnalyzerPanel()); + pack(); + } + +} diff --git a/src/com/annimon/asm/SyntaxAnalyzer.java b/src/com/annimon/asm/SyntaxAnalyzer.java index d274dd9..fb3ee9b 100644 --- a/src/com/annimon/asm/SyntaxAnalyzer.java +++ b/src/com/annimon/asm/SyntaxAnalyzer.java @@ -1,44 +1,44 @@ -package com.annimon.asm; - -import com.annimon.asm.directives.Add; -import com.annimon.asm.directives.Mul; -import com.annimon.asm.directives.Pop; -import com.annimon.asm.directives.Push; -import com.annimon.asm.directives.ISyntaxChecker; -import com.annimon.asm.directives.Idiv; -import com.annimon.asm.directives.Variable; -import com.annimon.asm.exceptions.ExceptionWithLineNumber; - -/** - * Синтаксический анализатор. - * @author aNNiMON - */ -public class SyntaxAnalyzer { - - private static final ISyntaxChecker[] DIRECTIVES = { - new Add(), new Mul(), new Push(), new Pop(), new Idiv(), - new Variable() - }; - - private LexicTable lexicTable; - - public SyntaxAnalyzer(LexicTable lexicTable) { - this.lexicTable = lexicTable; - } - - public void analyze() throws ExceptionWithLineNumber { - for (int i = 0; i < lexicTable.getSize(); i++) { - LexicLine line = lexicTable.getLexicAt(i); - analyzeLine(line.lineNumber, line.line); - } - } - - private void analyzeLine(int lineNumber, int[] lexic) throws ExceptionWithLineNumber { - for (int i = 0; i < DIRECTIVES.length; i++) { - if (DIRECTIVES[i].check(lineNumber, lexic)) { - return; - } - } - } - -} +package com.annimon.asm; + +import com.annimon.asm.directives.Add; +import com.annimon.asm.directives.Mul; +import com.annimon.asm.directives.Pop; +import com.annimon.asm.directives.Push; +import com.annimon.asm.directives.ISyntaxChecker; +import com.annimon.asm.directives.Idiv; +import com.annimon.asm.directives.Variable; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; + +/** + * Синтаксический анализатор. + * @author aNNiMON + */ +public final class SyntaxAnalyzer { + + private static final ISyntaxChecker[] DIRECTIVES = { + new Add(), new Mul(), new Push(), new Pop(), new Idiv(), + new Variable() + }; + + private final LexicTable lexicTable; + + public SyntaxAnalyzer(LexicTable lexicTable) { + this.lexicTable = lexicTable; + } + + public void analyze() throws ExceptionWithLineNumber { + for (int i = 0; i < lexicTable.getSize(); i++) { + LexicLine line = lexicTable.getLexicAt(i); + analyzeLine(line.lineNumber, line.line); + } + } + + private void analyzeLine(int lineNumber, int[] lexic) throws ExceptionWithLineNumber { + for (ISyntaxChecker dir : DIRECTIVES) { + if (dir.check(lineNumber, lexic)) { + return; + } + } + } + +} diff --git a/src/com/annimon/asm/Var.java b/src/com/annimon/asm/Var.java index 2d74a30..a658a6c 100644 --- a/src/com/annimon/asm/Var.java +++ b/src/com/annimon/asm/Var.java @@ -1,25 +1,25 @@ -package com.annimon.asm; - -/** - * Класс переменной. - * @author aNNiMON - */ -public class Var { - - String name; - int type; - String value; - short addr; - - public Var(String name, int type, String value, short addr) { - this.name = name; - this.type = type; - this.value = value; - this.addr = addr; - } - - public short getAddress() { - return addr; - } - -} +package com.annimon.asm; + +/** + * Класс переменной. + * @author aNNiMON + */ +public final class Var { + + String name; + int type; + String value; + short addr; + + public Var(String name, int type, String value, short addr) { + this.name = name; + this.type = type; + this.value = value; + this.addr = addr; + } + + public short getAddress() { + return addr; + } + +} diff --git a/src/com/annimon/asm/VarTable.java b/src/com/annimon/asm/VarTable.java index bf7df67..1bd5db9 100644 --- a/src/com/annimon/asm/VarTable.java +++ b/src/com/annimon/asm/VarTable.java @@ -1,52 +1,52 @@ -package com.annimon.asm; - -import com.annimon.asm.directives.ID; -import java.util.ArrayList; - -/** - * Таблица переменных. - * @author aNNiMON - */ -public class VarTable { - - private ArrayList variables; - private static short offset; - - public VarTable() { - variables = new ArrayList<>(); - offset = 0x103; - } - - public static short getOffset() { - return offset; - } - - public void addVariable(String name, int type, String value) { - addVariable(name, type, value, offset); - int size = (type == ID.DW) ? 2 : 1; - offset += size; - } - - public void addVariable(String name, int type, String value, short address) { - variables.add(new Var(name, type, value, address)); - } - - public int getTypeOfVariable(String name) { - for (Var var : variables) { - if (var.name.equalsIgnoreCase(name)) { - if (var.type == ID.DB) return ID.VAR_BYTE; - else if (var.type == ID.DW) return ID.VAR_WORD; - } - } - return ID.VAR; - } - - public short getAddressOfVariable(String name) { - for (Var var : variables) { - if (var.name.equalsIgnoreCase(name)) { - return var.getAddress(); - } - } - return ID.VAR; - } -} +package com.annimon.asm; + +import com.annimon.asm.directives.ID; +import java.util.ArrayList; + +/** + * Таблица переменных. + * @author aNNiMON + */ +public final class VarTable { + + private static short offset; + private final ArrayList variables; + + public VarTable() { + variables = new ArrayList<>(); + offset = 0x103; + } + + public static short getOffset() { + return offset; + } + + public void addVariable(String name, int type, String value) { + addVariable(name, type, value, offset); + int size = (type == ID.DW) ? 2 : 1; + offset += size; + } + + public void addVariable(String name, int type, String value, short address) { + variables.add(new Var(name, type, value, address)); + } + + public int getTypeOfVariable(String name) { + for (Var var : variables) { + if (var.name.equalsIgnoreCase(name)) { + if (var.type == ID.DB) return ID.VAR_BYTE; + else if (var.type == ID.DW) return ID.VAR_WORD; + } + } + return ID.VAR; + } + + public short getAddressOfVariable(String name) { + for (Var var : variables) { + if (var.name.equalsIgnoreCase(name)) { + return var.getAddress(); + } + } + return ID.VAR; + } +} diff --git a/src/com/annimon/asm/directives/Add.java b/src/com/annimon/asm/directives/Add.java index 7bda4eb..3c90813 100644 --- a/src/com/annimon/asm/directives/Add.java +++ b/src/com/annimon/asm/directives/Add.java @@ -12,7 +12,7 @@ import com.annimon.asm.exceptions.WrongArgumentException; * * @author aNNiMON */ -public class Add extends Directive implements ISyntaxChecker, IListingGenerator { +public final class Add extends Directive implements ISyntaxChecker, IListingGenerator { public Add() { super("add", ID.ADD); diff --git a/src/com/annimon/asm/directives/ByteRegister.java b/src/com/annimon/asm/directives/ByteRegister.java index e18e091..2a6c15c 100644 --- a/src/com/annimon/asm/directives/ByteRegister.java +++ b/src/com/annimon/asm/directives/ByteRegister.java @@ -4,7 +4,7 @@ package com.annimon.asm.directives; * * @author aNNiMON */ -public class ByteRegister extends Register { +public final class ByteRegister extends Register { @Override public int getId() { diff --git a/src/com/annimon/asm/directives/ByteValue.java b/src/com/annimon/asm/directives/ByteValue.java index 5a505c7..bd10ef2 100644 --- a/src/com/annimon/asm/directives/ByteValue.java +++ b/src/com/annimon/asm/directives/ByteValue.java @@ -4,7 +4,7 @@ package com.annimon.asm.directives; * * @author aNNiMON */ -public class ByteValue extends NumericValue { +public final class ByteValue extends NumericValue { @Override public int getId() { diff --git a/src/com/annimon/asm/directives/Comma.java b/src/com/annimon/asm/directives/Comma.java index d06fbde..f326803 100644 --- a/src/com/annimon/asm/directives/Comma.java +++ b/src/com/annimon/asm/directives/Comma.java @@ -1,13 +1,13 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public class Comma extends Directive { - - public Comma() { - super(",", ID.COMMA); - } - -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public final class Comma extends Directive { + + public Comma() { + super(",", ID.COMMA); + } + +} diff --git a/src/com/annimon/asm/directives/DB.java b/src/com/annimon/asm/directives/DB.java index 363666b..d067e8a 100644 --- a/src/com/annimon/asm/directives/DB.java +++ b/src/com/annimon/asm/directives/DB.java @@ -1,13 +1,13 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public class DB extends Directive { - - public DB() { - super("db", ID.DB); - } - -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public final class DB extends Directive { + + public DB() { + super("db", ID.DB); + } + +} diff --git a/src/com/annimon/asm/directives/DW.java b/src/com/annimon/asm/directives/DW.java index 3e347a1..00ca680 100644 --- a/src/com/annimon/asm/directives/DW.java +++ b/src/com/annimon/asm/directives/DW.java @@ -1,13 +1,13 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public class DW extends Directive { - - public DW() { - super("dw", ID.DW); - } - -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public final class DW extends Directive { + + public DW() { + super("dw", ID.DW); + } + +} diff --git a/src/com/annimon/asm/directives/Idiv.java b/src/com/annimon/asm/directives/Idiv.java index 9383b1c..37ec5b2 100644 --- a/src/com/annimon/asm/directives/Idiv.java +++ b/src/com/annimon/asm/directives/Idiv.java @@ -1,77 +1,77 @@ -package com.annimon.asm.directives; - -import com.annimon.asm.ListingGenerateHelper; -import com.annimon.asm.VarTable; -import com.annimon.asm.exceptions.ExceptionWithLineNumber; -import com.annimon.asm.exceptions.FewArgumentsException; -import com.annimon.asm.exceptions.TooManyArgumentsException; -import com.annimon.asm.exceptions.WrongArgumentException; - -/** - * - * @author aNNiMON - */ -public class Idiv extends Directive implements ISyntaxChecker, IListingGenerator { - - public Idiv() { - super("idiv", ID.IDIV); - } - - @Override - public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { - if (ids[0] != getId()) return false; - - if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); - else if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1); - - if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) && - (ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) { - throw new WrongArgumentException(lineNumber); - } - return true; - } - - @Override - public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { - if (ids[0] != getId()) return ""; - - // MUL r/m 1111011w | mod111r/m - StringBuilder sb = new StringBuilder(); - int val = 0b1111011_0; - if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { - val |= 1; - } - - String varaddr = " "; - if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { - short offset = vars.getAddressOfVariable(strs[1]); - varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; - } - - // mod - int modrm = 0b00; - if (ListingGenerateHelper.isRegister(ids[1])) { - // Если операнд - регистр, то mod = 11 - modrm |= 0b11; - } - modrm <<= 6; - - // r/m - if (modrm == 0) modrm = 0b110; - else { - // Если mod != 11, то r/m - id регистра. - modrm |= ListingGenerateHelper.getRegisterCode(strs[1]); - } - - // reg - 111 - byte regID = 0b111; - regID <<= 3; - modrm |= regID; - - sb.append(ListingGenerateHelper.toHexString(val)) - .append(' ') - .append(ListingGenerateHelper.toHexString(modrm)) - .append(varaddr); - return sb.toString(); - } -} +package com.annimon.asm.directives; + +import com.annimon.asm.ListingGenerateHelper; +import com.annimon.asm.VarTable; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import com.annimon.asm.exceptions.FewArgumentsException; +import com.annimon.asm.exceptions.TooManyArgumentsException; +import com.annimon.asm.exceptions.WrongArgumentException; + +/** + * + * @author aNNiMON + */ +public final class Idiv extends Directive implements ISyntaxChecker, IListingGenerator { + + public Idiv() { + super("idiv", ID.IDIV); + } + + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] != getId()) return false; + + if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); + else if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1); + + if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) && + (ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) { + throw new WrongArgumentException(lineNumber); + } + return true; + } + + @Override + public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { + if (ids[0] != getId()) return ""; + + // MUL r/m 1111011w | mod111r/m + int val = 0b1111011_0; + if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { + val |= 1; + } + + String varaddr = " "; + if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { + short offset = vars.getAddressOfVariable(strs[1]); + varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; + } + + // mod + int modrm = 0b00; + if (ListingGenerateHelper.isRegister(ids[1])) { + // Если операнд - регистр, то mod = 11 + modrm |= 0b11; + } + modrm <<= 6; + + // r/m + if (modrm == 0) modrm = 0b110; + else { + // Если mod != 11, то r/m - id регистра. + modrm |= ListingGenerateHelper.getRegisterCode(strs[1]); + } + + // reg - 111 + byte regID = 0b111; + regID <<= 3; + modrm |= regID; + + final StringBuilder sb = new StringBuilder(); + sb.append(ListingGenerateHelper.toHexString(val)) + .append(' ') + .append(ListingGenerateHelper.toHexString(modrm)) + .append(varaddr); + return sb.toString(); + } +} diff --git a/src/com/annimon/asm/directives/InfinityValue.java b/src/com/annimon/asm/directives/InfinityValue.java index d565a0c..4cd17de 100644 --- a/src/com/annimon/asm/directives/InfinityValue.java +++ b/src/com/annimon/asm/directives/InfinityValue.java @@ -4,7 +4,7 @@ package com.annimon.asm.directives; * Неопределённое значение (?) * @author aNNiMON */ -public class InfinityValue extends NumericValue { +public final class InfinityValue extends NumericValue { @Override public int getId() { diff --git a/src/com/annimon/asm/directives/Mul.java b/src/com/annimon/asm/directives/Mul.java index 33bf9ce..fcaa71c 100644 --- a/src/com/annimon/asm/directives/Mul.java +++ b/src/com/annimon/asm/directives/Mul.java @@ -1,77 +1,77 @@ -package com.annimon.asm.directives; - -import com.annimon.asm.ListingGenerateHelper; -import com.annimon.asm.VarTable; -import com.annimon.asm.exceptions.ExceptionWithLineNumber; -import com.annimon.asm.exceptions.FewArgumentsException; -import com.annimon.asm.exceptions.TooManyArgumentsException; -import com.annimon.asm.exceptions.WrongArgumentException; - -/** - * - * @author aNNiMON - */ -public class Mul extends Directive implements ISyntaxChecker, IListingGenerator { - - public Mul() { - super("mul", ID.MUL); - } - - @Override - public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { - if (ids[0] != getId()) return false; - - if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); - else if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1); - - if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) && - (ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) { - throw new WrongArgumentException(lineNumber); - } - return true; - } - - @Override - public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { - if (ids[0] != getId()) return ""; - - // MUL r/m 1111011w | mod100r/m - StringBuilder sb = new StringBuilder(); - int val = 0b1111011_0; - if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { - val |= 1; - } - - String varaddr = " "; - if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { - short offset = vars.getAddressOfVariable(strs[1]); - varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; - } - - // mod - int modrm = 0b00; - if (ListingGenerateHelper.isRegister(ids[1])) { - // Если операнд - регистр, то mod = 11 - modrm |= 0b11; - } - modrm <<= 6; - - // r/m - if (modrm == 0) modrm = 0b110; - else { - // Если mod != 11, то r/m - id регистра. - modrm |= ListingGenerateHelper.getRegisterCode(strs[1]); - } - - // reg - 100 - byte regID = 0b100; - regID <<= 3; - modrm |= regID; - - sb.append(ListingGenerateHelper.toHexString(val)) - .append(' ') - .append(ListingGenerateHelper.toHexString(modrm)) - .append(varaddr); - return sb.toString(); - } -} +package com.annimon.asm.directives; + +import com.annimon.asm.ListingGenerateHelper; +import com.annimon.asm.VarTable; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import com.annimon.asm.exceptions.FewArgumentsException; +import com.annimon.asm.exceptions.TooManyArgumentsException; +import com.annimon.asm.exceptions.WrongArgumentException; + +/** + * + * @author aNNiMON + */ +public final class Mul extends Directive implements ISyntaxChecker, IListingGenerator { + + public Mul() { + super("mul", ID.MUL); + } + + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] != getId()) return false; + + if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); + else if (ids.length > 2) throw new TooManyArgumentsException(lineNumber, 1); + + if ( (ids[1] != ID.REGISTER_BYTE) && (ids[1] != ID.REGISTER_WORD) && + (ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) { + throw new WrongArgumentException(lineNumber); + } + return true; + } + + @Override + public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { + if (ids[0] != getId()) return ""; + + // MUL r/m 1111011w | mod100r/m + int val = 0b1111011_0; + if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { + val |= 1; + } + + String varaddr = " "; + if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { + short offset = vars.getAddressOfVariable(strs[1]); + varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; + } + + // mod + int modrm = 0b00; + if (ListingGenerateHelper.isRegister(ids[1])) { + // Если операнд - регистр, то mod = 11 + modrm |= 0b11; + } + modrm <<= 6; + + // r/m + if (modrm == 0) modrm = 0b110; + else { + // Если mod != 11, то r/m - id регистра. + modrm |= ListingGenerateHelper.getRegisterCode(strs[1]); + } + + // reg - 100 + byte regID = 0b100; + regID <<= 3; + modrm |= regID; + + final StringBuilder sb = new StringBuilder(); + sb.append(ListingGenerateHelper.toHexString(val)) + .append(' ') + .append(ListingGenerateHelper.toHexString(modrm)) + .append(varaddr); + return sb.toString(); + } +} diff --git a/src/com/annimon/asm/directives/Pop.java b/src/com/annimon/asm/directives/Pop.java index 2312cd8..59bf4be 100644 --- a/src/com/annimon/asm/directives/Pop.java +++ b/src/com/annimon/asm/directives/Pop.java @@ -1,64 +1,64 @@ -package com.annimon.asm.directives; - -import com.annimon.asm.ListingGenerateHelper; -import com.annimon.asm.VarTable; -import com.annimon.asm.exceptions.ExceptionWithLineNumber; -import com.annimon.asm.exceptions.FewArgumentsException; -import com.annimon.asm.exceptions.WrongArgumentException; - -/** - * - * @author aNNiMON - */ -public class Pop extends Directive implements ISyntaxChecker, IListingGenerator { - - public Pop() { - super("pop", ID.POP); - } - - @Override - public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { - if (ids[0] != getId()) return false; - - if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); - for (int i = 1; i < ids.length; i++) { - if ( (ids[i] != ID.REGISTER_WORD) && - (ids[i] != ID.VAR_WORD)) { - throw new WrongArgumentException(lineNumber); - } - } - return true; - } - - @Override - public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { - if (ids[0] != getId()) return ""; - - StringBuilder sb = new StringBuilder(); - - if (ids[1] == ID.REGISTER_WORD) { - byte segmentID = ListingGenerateHelper.getSegmentRegisterCode(strs[1]); - if (segmentID != -1) { - //seg (только cs, ds, ss, es) 00seg111 - byte val = (byte) (0b00_000_111 | (segmentID << 3)); - sb.append(ListingGenerateHelper.toHexString(val)); - } else { - // reg16/32 01011reg - byte regID = ListingGenerateHelper.getRegisterCode(strs[1]); - byte val = (byte) (0b01011_000 | regID); - sb.append(ListingGenerateHelper.toHexString(val)); - } - } else if (ids[1] == ID.VAR_WORD) { - //r/m16/32 10001111 | mod110r/m - short offset = vars.getAddressOfVariable(strs[1]); - - sb.append(ListingGenerateHelper.toHexString(0b10001111)) - .append(' ') - .append(ListingGenerateHelper.toHexString(0b00_000_110)) - .append(' ') - .append(ListingGenerateHelper.toLittleEndianString(offset)); - } - - return sb.toString(); - } -} +package com.annimon.asm.directives; + +import com.annimon.asm.ListingGenerateHelper; +import com.annimon.asm.VarTable; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import com.annimon.asm.exceptions.FewArgumentsException; +import com.annimon.asm.exceptions.WrongArgumentException; + +/** + * + * @author aNNiMON + */ +public final class Pop extends Directive implements ISyntaxChecker, IListingGenerator { + + public Pop() { + super("pop", ID.POP); + } + + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] != getId()) return false; + + if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); + for (int i = 1; i < ids.length; i++) { + if ( (ids[i] != ID.REGISTER_WORD) && + (ids[i] != ID.VAR_WORD)) { + throw new WrongArgumentException(lineNumber); + } + } + return true; + } + + @Override + public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { + if (ids[0] != getId()) return ""; + + StringBuilder sb = new StringBuilder(); + + if (ids[1] == ID.REGISTER_WORD) { + byte segmentID = ListingGenerateHelper.getSegmentRegisterCode(strs[1]); + if (segmentID != -1) { + //seg (только cs, ds, ss, es) 00seg111 + byte val = (byte) (0b00_000_111 | (segmentID << 3)); + sb.append(ListingGenerateHelper.toHexString(val)); + } else { + // reg16/32 01011reg + byte regID = ListingGenerateHelper.getRegisterCode(strs[1]); + byte val = (byte) (0b01011_000 | regID); + sb.append(ListingGenerateHelper.toHexString(val)); + } + } else if (ids[1] == ID.VAR_WORD) { + //r/m16/32 10001111 | mod110r/m + short offset = vars.getAddressOfVariable(strs[1]); + + sb.append(ListingGenerateHelper.toHexString(0b10001111)) + .append(' ') + .append(ListingGenerateHelper.toHexString(0b00_000_110)) + .append(' ') + .append(ListingGenerateHelper.toLittleEndianString(offset)); + } + + return sb.toString(); + } +} diff --git a/src/com/annimon/asm/directives/Push.java b/src/com/annimon/asm/directives/Push.java index 888bfa6..26dd408 100644 --- a/src/com/annimon/asm/directives/Push.java +++ b/src/com/annimon/asm/directives/Push.java @@ -1,65 +1,65 @@ -package com.annimon.asm.directives; - -import com.annimon.asm.ListingGenerateHelper; -import com.annimon.asm.VarTable; -import com.annimon.asm.exceptions.ExceptionWithLineNumber; -import com.annimon.asm.exceptions.FewArgumentsException; -import com.annimon.asm.exceptions.WrongArgumentException; - -/** - * - * @author aNNiMON - */ -public class Push extends Directive implements ISyntaxChecker, IListingGenerator { - - public Push() { - super("push", ID.PUSH); - } - - @Override - public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { - if (ids[0] != getId()) return false; - - if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); - for (int i = 1; i < ids.length; i++) { - if ( (ids[i] != ID.REGISTER_WORD) && - (ids[i] != ID.VAR_WORD)) { - throw new WrongArgumentException(lineNumber); - } - } - return true; - - } - - @Override - public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { - if (ids[0] != getId()) return ""; - - StringBuilder sb = new StringBuilder(); - - if (ids[1] == ID.REGISTER_WORD) { - byte segmentID = ListingGenerateHelper.getSegmentRegisterCode(strs[1]); - if (segmentID != -1) { - //seg (только cs, ds, ss, es) 00seg110 - byte val = (byte) (0b00_000_110 | (segmentID << 3)); - sb.append(ListingGenerateHelper.toHexString(val)); - } else { - // reg16/32 01010reg - byte regID = ListingGenerateHelper.getRegisterCode(strs[1]); - byte val = (byte) (0b01010_000 | regID); - sb.append(ListingGenerateHelper.toHexString(val)); - } - } else if (ids[1] == ID.VAR_WORD) { - // r/m16/32 11111111 | mod110r/m - short offset = vars.getAddressOfVariable(strs[1]); - - sb.append(ListingGenerateHelper.toHexString(0b11111111)) - .append(' ') - .append(ListingGenerateHelper.toHexString(0b00_110_110)) - .append(' ') - .append(ListingGenerateHelper.toLittleEndianString(offset)); - } - - return sb.toString(); - } -} +package com.annimon.asm.directives; + +import com.annimon.asm.ListingGenerateHelper; +import com.annimon.asm.VarTable; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import com.annimon.asm.exceptions.FewArgumentsException; +import com.annimon.asm.exceptions.WrongArgumentException; + +/** + * + * @author aNNiMON + */ +public final class Push extends Directive implements ISyntaxChecker, IListingGenerator { + + public Push() { + super("push", ID.PUSH); + } + + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] != getId()) return false; + + if (ids.length < 2) throw new FewArgumentsException(lineNumber, 1); + for (int i = 1; i < ids.length; i++) { + if ( (ids[i] != ID.REGISTER_WORD) && + (ids[i] != ID.VAR_WORD)) { + throw new WrongArgumentException(lineNumber); + } + } + return true; + + } + + @Override + public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { + if (ids[0] != getId()) return ""; + + StringBuilder sb = new StringBuilder(); + + if (ids[1] == ID.REGISTER_WORD) { + byte segmentID = ListingGenerateHelper.getSegmentRegisterCode(strs[1]); + if (segmentID != -1) { + //seg (только cs, ds, ss, es) 00seg110 + byte val = (byte) (0b00_000_110 | (segmentID << 3)); + sb.append(ListingGenerateHelper.toHexString(val)); + } else { + // reg16/32 01010reg + byte regID = ListingGenerateHelper.getRegisterCode(strs[1]); + byte val = (byte) (0b01010_000 | regID); + sb.append(ListingGenerateHelper.toHexString(val)); + } + } else if (ids[1] == ID.VAR_WORD) { + // r/m16/32 11111111 | mod110r/m + short offset = vars.getAddressOfVariable(strs[1]); + + sb.append(ListingGenerateHelper.toHexString(0b11111111)) + .append(' ') + .append(ListingGenerateHelper.toHexString(0b00_110_110)) + .append(' ') + .append(ListingGenerateHelper.toLittleEndianString(offset)); + } + + return sb.toString(); + } +} diff --git a/src/com/annimon/asm/directives/Variable.java b/src/com/annimon/asm/directives/Variable.java index 5ed3214..dcf1c20 100644 --- a/src/com/annimon/asm/directives/Variable.java +++ b/src/com/annimon/asm/directives/Variable.java @@ -1,61 +1,61 @@ -package com.annimon.asm.directives; - -import com.annimon.asm.ListingGenerateHelper; -import com.annimon.asm.VarTable; -import com.annimon.asm.exceptions.ExceptionWithLineNumber; -import com.annimon.asm.exceptions.FewArgumentsException; -import com.annimon.asm.exceptions.TooManyArgumentsException; -import com.annimon.asm.exceptions.WrongArgumentException; -import java.util.regex.Pattern; - -/** - * - * @author aNNiMON - */ -public class Variable extends Directive implements ISyntaxChecker, IListingGenerator { - - public Variable() { - super("", ID.VAR); - } - - @Override - public boolean isDirective(String text) { - if (Pattern.matches(Pattern.compile("^[^0-9]*[\\w.@_$]").pattern(), text)) { - return true; - } - return false; - } - - @Override - public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { - if (ids[0] != getId()) return false; - - if (ids.length < 3) throw new FewArgumentsException(lineNumber, 2); - else if (ids.length > 3) throw new TooManyArgumentsException(lineNumber, 2); - - boolean db = ( (ids[1] == ID.DB) && - ((ids[2] == ID.NUMBER_BYTE) || (ids[2] == ID.NUMBER_INFINITY)) ); - boolean dw = ( (ids[1] == ID.DW) && - ((ids[2] == ID.NUMBER_WORD) || (ids[2] == ID.NUMBER_INFINITY)) ); - if (!db && !dw) { - throw new WrongArgumentException(lineNumber); - } - return true; - } - - @Override - public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { - if ( (ids[0] != ID.VAR_BYTE) && (ids[0] != ID.VAR_WORD) ) return ""; - - StringBuilder sb = new StringBuilder(); - int offset = vars.getAddressOfVariable(strs[0]); - sb.append(ListingGenerateHelper.toHexString(offset)).append(" "); - - if (ids[2] == ID.NUMBER_INFINITY) { - sb.append("??"); - if (ids[1] == ID.DW) sb.append(" ??"); - } else sb.append( ListingGenerateHelper.toLittleEndianString(strs[2]) ); - - return sb.toString(); - } -} +package com.annimon.asm.directives; + +import com.annimon.asm.ListingGenerateHelper; +import com.annimon.asm.VarTable; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import com.annimon.asm.exceptions.FewArgumentsException; +import com.annimon.asm.exceptions.TooManyArgumentsException; +import com.annimon.asm.exceptions.WrongArgumentException; +import java.util.regex.Pattern; + +/** + * + * @author aNNiMON + */ +public final class Variable extends Directive implements ISyntaxChecker, IListingGenerator { + + public Variable() { + super("", ID.VAR); + } + + @Override + public boolean isDirective(String text) { + if (Pattern.matches(Pattern.compile("^[^0-9]*[\\w.@_$]").pattern(), text)) { + return true; + } + return false; + } + + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] != getId()) return false; + + if (ids.length < 3) throw new FewArgumentsException(lineNumber, 2); + else if (ids.length > 3) throw new TooManyArgumentsException(lineNumber, 2); + + boolean db = ( (ids[1] == ID.DB) && + ((ids[2] == ID.NUMBER_BYTE) || (ids[2] == ID.NUMBER_INFINITY)) ); + boolean dw = ( (ids[1] == ID.DW) && + ((ids[2] == ID.NUMBER_WORD) || (ids[2] == ID.NUMBER_INFINITY)) ); + if (!db && !dw) { + throw new WrongArgumentException(lineNumber); + } + return true; + } + + @Override + public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { + if ( (ids[0] != ID.VAR_BYTE) && (ids[0] != ID.VAR_WORD) ) return ""; + + StringBuilder sb = new StringBuilder(); + int offset = vars.getAddressOfVariable(strs[0]); + sb.append(ListingGenerateHelper.toHexString(offset)).append(" "); + + if (ids[2] == ID.NUMBER_INFINITY) { + sb.append("??"); + if (ids[1] == ID.DW) sb.append(" ??"); + } else sb.append( ListingGenerateHelper.toLittleEndianString(strs[2]) ); + + return sb.toString(); + } +} diff --git a/src/com/annimon/asm/directives/WordRegister.java b/src/com/annimon/asm/directives/WordRegister.java index af03c16..d6efbad 100644 --- a/src/com/annimon/asm/directives/WordRegister.java +++ b/src/com/annimon/asm/directives/WordRegister.java @@ -4,7 +4,7 @@ package com.annimon.asm.directives; * * @author aNNiMON */ -public class WordRegister extends Register { +public final class WordRegister extends Register { @Override public int getId() { diff --git a/src/com/annimon/asm/directives/WordValue.java b/src/com/annimon/asm/directives/WordValue.java index 6496c4c..ac7567a 100644 --- a/src/com/annimon/asm/directives/WordValue.java +++ b/src/com/annimon/asm/directives/WordValue.java @@ -4,7 +4,7 @@ package com.annimon.asm.directives; * * @author aNNiMON */ -public class WordValue extends NumericValue { +public final class WordValue extends NumericValue { @Override public int getId() { diff --git a/src/com/annimon/asm/exceptions/CommaExpectedException.java b/src/com/annimon/asm/exceptions/CommaExpectedException.java index c56b740..f38ca21 100644 --- a/src/com/annimon/asm/exceptions/CommaExpectedException.java +++ b/src/com/annimon/asm/exceptions/CommaExpectedException.java @@ -1,12 +1,12 @@ -package com.annimon.asm.exceptions; - -/** - * Класс ошибки пропущенной запятой. - * @author aNNiMON - */ -public class CommaExpectedException extends ExceptionWithLineNumber { - - public CommaExpectedException(int lineNumber) { - super("Comma expected", lineNumber); - } -} +package com.annimon.asm.exceptions; + +/** + * Класс ошибки пропущенной запятой. + * @author aNNiMON + */ +public final class CommaExpectedException extends ExceptionWithLineNumber { + + public CommaExpectedException(int lineNumber) { + super("Comma expected", lineNumber); + } +} diff --git a/src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java b/src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java index 5157e4e..2a90815 100644 --- a/src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java +++ b/src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java @@ -1,21 +1,21 @@ -package com.annimon.asm.exceptions; - -/** - * Базовый класс для ошибок с отображением номера ошибочной строки. - * @author aNNiMON - */ -public abstract class ExceptionWithLineNumber extends Exception { - - private int lineNumber; - - public ExceptionWithLineNumber(String message, int lineNumber) { - super(message); - this.lineNumber = lineNumber; - } - - @Override - public String getMessage() { - return super.getMessage() + " at line " + lineNumber; - } - -} +package com.annimon.asm.exceptions; + +/** + * Базовый класс для ошибок с отображением номера ошибочной строки. + * @author aNNiMON + */ +public abstract class ExceptionWithLineNumber extends Exception { + + private final int lineNumber; + + public ExceptionWithLineNumber(String message, int lineNumber) { + super(message); + this.lineNumber = lineNumber; + } + + @Override + public String getMessage() { + return super.getMessage() + " at line " + lineNumber; + } + +} diff --git a/src/com/annimon/asm/exceptions/FewArgumentsException.java b/src/com/annimon/asm/exceptions/FewArgumentsException.java index 0ad20fc..a2ab8a9 100644 --- a/src/com/annimon/asm/exceptions/FewArgumentsException.java +++ b/src/com/annimon/asm/exceptions/FewArgumentsException.java @@ -1,16 +1,16 @@ -package com.annimon.asm.exceptions; - -/** - * Класс ошибки, когда указано слишком мало аргументов команды, нежели ожидалось. - * @author aNNiMON - */ -public class FewArgumentsException extends ExceptionWithLineNumber { - - public FewArgumentsException(int lineNumber) { - super("Few arguments", lineNumber); - } - - public FewArgumentsException(int lineNumber, int necessaryArguments) { - super("Few arguments, need " + necessaryArguments + " args", lineNumber); - } -} +package com.annimon.asm.exceptions; + +/** + * Класс ошибки, когда указано слишком мало аргументов команды, нежели ожидалось. + * @author aNNiMON + */ +public final class FewArgumentsException extends ExceptionWithLineNumber { + + public FewArgumentsException(int lineNumber) { + super("Few arguments", lineNumber); + } + + public FewArgumentsException(int lineNumber, int necessaryArguments) { + super("Few arguments, need " + necessaryArguments + " args", lineNumber); + } +} diff --git a/src/com/annimon/asm/exceptions/TooManyArgumentsException.java b/src/com/annimon/asm/exceptions/TooManyArgumentsException.java index 1eea990..0eace26 100644 --- a/src/com/annimon/asm/exceptions/TooManyArgumentsException.java +++ b/src/com/annimon/asm/exceptions/TooManyArgumentsException.java @@ -1,16 +1,16 @@ -package com.annimon.asm.exceptions; - -/** - * Класс ошибки для превышенного количества аргументов команды. - * @author aNNiMON - */ -public class TooManyArgumentsException extends ExceptionWithLineNumber { - - public TooManyArgumentsException(int lineNumber) { - super("Too many arguments", lineNumber); - } - - public TooManyArgumentsException(int lineNumber, int necessaryArguments) { - super("Too many arguments, need " + necessaryArguments + " args", lineNumber); - } -} +package com.annimon.asm.exceptions; + +/** + * Класс ошибки для превышенного количества аргументов команды. + * @author aNNiMON + */ +public final class TooManyArgumentsException extends ExceptionWithLineNumber { + + public TooManyArgumentsException(int lineNumber) { + super("Too many arguments", lineNumber); + } + + public TooManyArgumentsException(int lineNumber, int necessaryArguments) { + super("Too many arguments, need " + necessaryArguments + " args", lineNumber); + } +} diff --git a/src/com/annimon/asm/exceptions/WrongArgumentException.java b/src/com/annimon/asm/exceptions/WrongArgumentException.java index 051882d..944cc92 100644 --- a/src/com/annimon/asm/exceptions/WrongArgumentException.java +++ b/src/com/annimon/asm/exceptions/WrongArgumentException.java @@ -1,12 +1,12 @@ -package com.annimon.asm.exceptions; - -/** - * Класс ошибки неверного аргумента, когда не совпадает ожидаемый тип. - * @author aNNiMON - */ -public class WrongArgumentException extends ExceptionWithLineNumber { - - public WrongArgumentException(int lineNumber) { - super("Wrong argument", lineNumber); - } -} +package com.annimon.asm.exceptions; + +/** + * Класс ошибки неверного аргумента, когда не совпадает ожидаемый тип. + * @author aNNiMON + */ +public final class WrongArgumentException extends ExceptionWithLineNumber { + + public WrongArgumentException(int lineNumber) { + super("Wrong argument", lineNumber); + } +}