From 70a61f31dea7a4baa21c02cdc443d96b54f34010 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 15 Nov 2018 18:47:44 +0200 Subject: [PATCH] 2 --- src/com/annimon/asm/AnalyzerPanel.java | 9 ++- src/com/annimon/asm/SyntaxAnalyzer.java | 19 ++++++- src/com/annimon/asm/directives/Add.java | 56 +++++++++++++++++-- .../annimon/asm/directives/ByteRegister.java | 4 -- src/com/annimon/asm/directives/ByteValue.java | 4 -- src/com/annimon/asm/directives/Comma.java | 4 -- src/com/annimon/asm/directives/DB.java | 4 -- src/com/annimon/asm/directives/DW.java | 4 -- src/com/annimon/asm/directives/Directive.java | 4 -- src/com/annimon/asm/directives/ID.java | 4 -- .../annimon/asm/directives/InfinityValue.java | 4 -- src/com/annimon/asm/directives/Mul.java | 25 +++++++-- .../annimon/asm/directives/NumericValue.java | 10 ++-- src/com/annimon/asm/directives/Pop.java | 24 ++++++-- src/com/annimon/asm/directives/Push.java | 25 +++++++-- src/com/annimon/asm/directives/Register.java | 4 -- .../annimon/asm/directives/SyntaxChecker.java | 20 +++++++ src/com/annimon/asm/directives/Variable.java | 34 +++++++++-- .../annimon/asm/directives/WordRegister.java | 7 +-- src/com/annimon/asm/directives/WordValue.java | 4 -- .../exceptions/CommaExpectedException.java | 16 ++++++ .../asm/exceptions/FewArgumentsException.java | 20 +++++++ .../asm/exceptions/SyntaxException.java | 16 ++++++ .../exceptions/TooManyArgumentsException.java | 20 +++++++ .../exceptions/WrongArgumentException.java | 16 ++++++ src/test.asm | 3 +- 26 files changed, 280 insertions(+), 80 deletions(-) create mode 100644 src/com/annimon/asm/directives/SyntaxChecker.java create mode 100644 src/com/annimon/asm/exceptions/CommaExpectedException.java create mode 100644 src/com/annimon/asm/exceptions/FewArgumentsException.java create mode 100644 src/com/annimon/asm/exceptions/SyntaxException.java create mode 100644 src/com/annimon/asm/exceptions/TooManyArgumentsException.java create mode 100644 src/com/annimon/asm/exceptions/WrongArgumentException.java diff --git a/src/com/annimon/asm/AnalyzerPanel.java b/src/com/annimon/asm/AnalyzerPanel.java index b59608d..62ebc16 100644 --- a/src/com/annimon/asm/AnalyzerPanel.java +++ b/src/com/annimon/asm/AnalyzerPanel.java @@ -16,6 +16,7 @@ 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; @@ -86,12 +87,18 @@ public class AnalyzerPanel extends JPanel { try { syn.analyze(); } catch (ExceptionWithLineNumber ex) { - System.out.println(ex.getMessage()); + showMessageBox(ex.getMessage()); + return; } + showMessageBox("Source is correct!"); } }); } + private void showMessageBox(String text) { + JOptionPane.showMessageDialog(this, text); + } + private String getTextFromResource(String res) { try { InputStream is = getClass().getResourceAsStream(res); diff --git a/src/com/annimon/asm/SyntaxAnalyzer.java b/src/com/annimon/asm/SyntaxAnalyzer.java index 38081b4..91d78b6 100644 --- a/src/com/annimon/asm/SyntaxAnalyzer.java +++ b/src/com/annimon/asm/SyntaxAnalyzer.java @@ -1,6 +1,11 @@ package com.annimon.asm; -import com.annimon.asm.directives.ID; +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.SyntaxChecker; +import com.annimon.asm.directives.Variable; import com.annimon.asm.exceptions.ExceptionWithLineNumber; /** @@ -9,6 +14,12 @@ import com.annimon.asm.exceptions.ExceptionWithLineNumber; */ public class SyntaxAnalyzer { + private static final SyntaxChecker[] DIRECTIVES = { + new Add(), new Mul(), new Push(), new Pop(), + new Variable() + }; + + private LexicTable lexicTable; public SyntaxAnalyzer(LexicTable lexicTable) { @@ -23,8 +34,10 @@ public class SyntaxAnalyzer { } private void analyzeLine(int lineNumber, int[] lexic) throws ExceptionWithLineNumber { - if (lexic[0] == ID.VAR) { - + for (int i = 0; i < DIRECTIVES.length; i++) { + if (DIRECTIVES[i].check(lineNumber, lexic)) { + return; + } } } diff --git a/src/com/annimon/asm/directives/Add.java b/src/com/annimon/asm/directives/Add.java index f2aece0..2d12bc5 100644 --- a/src/com/annimon/asm/directives/Add.java +++ b/src/com/annimon/asm/directives/Add.java @@ -1,17 +1,63 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; +import com.annimon.asm.exceptions.CommaExpectedException; +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 Add extends Directive { +public class Add extends Directive implements SyntaxChecker { public Add() { super("add", ID.ADD); } + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] == getId()) { + if (ids.length < 4) throw new FewArgumentsException(lineNumber); + else if (ids.length > 4) throw new TooManyArgumentsException(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, + ID.REGISTER_WORD, ID.VAR, + + // Память - Регистр + ID.VAR, ID.REGISTER_BYTE, + ID.VAR, ID.REGISTER_WORD, + + // Регистр - Значение + ID.REGISTER_BYTE, ID.NUMBER_BYTE, + ID.REGISTER_WORD, ID.NUMBER_WORD, + ID.REGISTER_WORD, ID.NUMBER_BYTE, + + // Память - Значение + ID.VAR, ID.NUMBER_BYTE, + ID.VAR, ID.NUMBER_WORD, + }; + + boolean correct = false; + for(int i = 0; i < pairs.length; i += 2) { + if ( (ids[1] == pairs[i]) && (ids[3] == pairs[i+1]) ) { + correct = true; + break; + } + } + if (!correct) throw new WrongArgumentException(lineNumber); + return true; + } + return false; + } } diff --git a/src/com/annimon/asm/directives/ByteRegister.java b/src/com/annimon/asm/directives/ByteRegister.java index 2952159..9a6ee3c 100644 --- a/src/com/annimon/asm/directives/ByteRegister.java +++ b/src/com/annimon/asm/directives/ByteRegister.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/ByteValue.java b/src/com/annimon/asm/directives/ByteValue.java index 952a306..6120548 100644 --- a/src/com/annimon/asm/directives/ByteValue.java +++ b/src/com/annimon/asm/directives/ByteValue.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/Comma.java b/src/com/annimon/asm/directives/Comma.java index b6b2ec5..8fefb20 100644 --- a/src/com/annimon/asm/directives/Comma.java +++ b/src/com/annimon/asm/directives/Comma.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/DB.java b/src/com/annimon/asm/directives/DB.java index cf965ca..6e63cfb 100644 --- a/src/com/annimon/asm/directives/DB.java +++ b/src/com/annimon/asm/directives/DB.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/DW.java b/src/com/annimon/asm/directives/DW.java index f20416c..c635fd2 100644 --- a/src/com/annimon/asm/directives/DW.java +++ b/src/com/annimon/asm/directives/DW.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/Directive.java b/src/com/annimon/asm/directives/Directive.java index d248300..bb9c56b 100644 --- a/src/com/annimon/asm/directives/Directive.java +++ b/src/com/annimon/asm/directives/Directive.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/ID.java b/src/com/annimon/asm/directives/ID.java index 626950b..de360a5 100644 --- a/src/com/annimon/asm/directives/ID.java +++ b/src/com/annimon/asm/directives/ID.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/InfinityValue.java b/src/com/annimon/asm/directives/InfinityValue.java index d9d1514..9120d43 100644 --- a/src/com/annimon/asm/directives/InfinityValue.java +++ b/src/com/annimon/asm/directives/InfinityValue.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/Mul.java b/src/com/annimon/asm/directives/Mul.java index bc47611..3a64c6a 100644 --- a/src/com/annimon/asm/directives/Mul.java +++ b/src/com/annimon/asm/directives/Mul.java @@ -1,17 +1,32 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; +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 { +public class Mul extends Directive implements SyntaxChecker { public Mul() { super("mul", ID.MUL); } + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] == getId()) { + 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)) { + throw new WrongArgumentException(lineNumber); + } + return true; + } + return false; + } } diff --git a/src/com/annimon/asm/directives/NumericValue.java b/src/com/annimon/asm/directives/NumericValue.java index 9a7e6cd..523f502 100644 --- a/src/com/annimon/asm/directives/NumericValue.java +++ b/src/com/annimon/asm/directives/NumericValue.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** @@ -27,6 +23,12 @@ public abstract class NumericValue extends Directive { private Integer parse(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); diff --git a/src/com/annimon/asm/directives/Pop.java b/src/com/annimon/asm/directives/Pop.java index 4aedd94..092d2ab 100644 --- a/src/com/annimon/asm/directives/Pop.java +++ b/src/com/annimon/asm/directives/Pop.java @@ -1,17 +1,31 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; +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 { +public class Pop extends Directive implements SyntaxChecker { public Pop() { super("pop", ID.POP); } + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] == getId()) { + 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)) { + throw new WrongArgumentException(lineNumber); + } + } + return true; + } + return false; + } } diff --git a/src/com/annimon/asm/directives/Push.java b/src/com/annimon/asm/directives/Push.java index 63eea09..57b372e 100644 --- a/src/com/annimon/asm/directives/Push.java +++ b/src/com/annimon/asm/directives/Push.java @@ -1,17 +1,32 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; +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 { +public class Push extends Directive implements SyntaxChecker { public Push() { super("push", ID.PUSH); } + + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] == getId()) { + 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)) { + throw new WrongArgumentException(lineNumber); + } + } + return true; + } + return false; + } } diff --git a/src/com/annimon/asm/directives/Register.java b/src/com/annimon/asm/directives/Register.java index 02b8186..b4d0c5c 100644 --- a/src/com/annimon/asm/directives/Register.java +++ b/src/com/annimon/asm/directives/Register.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/directives/SyntaxChecker.java b/src/com/annimon/asm/directives/SyntaxChecker.java new file mode 100644 index 0000000..872a78e --- /dev/null +++ b/src/com/annimon/asm/directives/SyntaxChecker.java @@ -0,0 +1,20 @@ +package com.annimon.asm.directives; + +import com.annimon.asm.exceptions.ExceptionWithLineNumber; + +/** + * Проверка синтаксиса. + * @author aNNiMON + */ +public interface SyntaxChecker { + + /** + * Проверить синтаксис. + * @param lineNumber номер строки. + * @param ids последовательность идентификаторов в строке. + * @return правильность последовательности директив. + * @throws ExceptionWithLineNumber + */ + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber; + +} diff --git a/src/com/annimon/asm/directives/Variable.java b/src/com/annimon/asm/directives/Variable.java index 50b1fbd..1d1cc34 100644 --- a/src/com/annimon/asm/directives/Variable.java +++ b/src/com/annimon/asm/directives/Variable.java @@ -1,14 +1,16 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; +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 { +public class Variable extends Directive implements SyntaxChecker { public Variable() { super("", ID.VAR); @@ -16,7 +18,27 @@ public class Variable extends Directive { @Override public boolean isDirective(String text) { - return true; + if (Pattern.matches(Pattern.compile("^[^1-9]+[\\w.@_$]").pattern(), text)) { + return true; + } + return false; } + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] == getId()) { + 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; + } + return false; + } } diff --git a/src/com/annimon/asm/directives/WordRegister.java b/src/com/annimon/asm/directives/WordRegister.java index 93ff828..264d6c1 100644 --- a/src/com/annimon/asm/directives/WordRegister.java +++ b/src/com/annimon/asm/directives/WordRegister.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** @@ -23,7 +19,8 @@ public class WordRegister extends Register { protected String[] getRegisterNames() { return new String[] { "ax", "bx", "cx", "dx", - "cs", "ds", "ss", "es" + "cs", "ds", "ss", "es", + "sp", "bp", "si", "di" }; } diff --git a/src/com/annimon/asm/directives/WordValue.java b/src/com/annimon/asm/directives/WordValue.java index f7e6709..39acf25 100644 --- a/src/com/annimon/asm/directives/WordValue.java +++ b/src/com/annimon/asm/directives/WordValue.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package com.annimon.asm.directives; /** diff --git a/src/com/annimon/asm/exceptions/CommaExpectedException.java b/src/com/annimon/asm/exceptions/CommaExpectedException.java new file mode 100644 index 0000000..1ea5ebc --- /dev/null +++ b/src/com/annimon/asm/exceptions/CommaExpectedException.java @@ -0,0 +1,16 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.exceptions; + +/** + * + * @author aNNiMON + */ +public class CommaExpectedException extends ExceptionWithLineNumber { + + public CommaExpectedException(int lineNumber) { + super("Comma expected", lineNumber); + } +} diff --git a/src/com/annimon/asm/exceptions/FewArgumentsException.java b/src/com/annimon/asm/exceptions/FewArgumentsException.java new file mode 100644 index 0000000..b368a51 --- /dev/null +++ b/src/com/annimon/asm/exceptions/FewArgumentsException.java @@ -0,0 +1,20 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +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); + } +} diff --git a/src/com/annimon/asm/exceptions/SyntaxException.java b/src/com/annimon/asm/exceptions/SyntaxException.java new file mode 100644 index 0000000..cc04ce2 --- /dev/null +++ b/src/com/annimon/asm/exceptions/SyntaxException.java @@ -0,0 +1,16 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.exceptions; + +/** + * + * @author aNNiMON + */ +public class SyntaxException extends ExceptionWithLineNumber { + + public SyntaxException(int lineNumber) { + super("Unknown syntax", lineNumber); + } +} diff --git a/src/com/annimon/asm/exceptions/TooManyArgumentsException.java b/src/com/annimon/asm/exceptions/TooManyArgumentsException.java new file mode 100644 index 0000000..b14091f --- /dev/null +++ b/src/com/annimon/asm/exceptions/TooManyArgumentsException.java @@ -0,0 +1,20 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +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); + } +} diff --git a/src/com/annimon/asm/exceptions/WrongArgumentException.java b/src/com/annimon/asm/exceptions/WrongArgumentException.java new file mode 100644 index 0000000..25484cf --- /dev/null +++ b/src/com/annimon/asm/exceptions/WrongArgumentException.java @@ -0,0 +1,16 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.exceptions; + +/** + * + * @author aNNiMON + */ +public class WrongArgumentException extends ExceptionWithLineNumber { + + public WrongArgumentException(int lineNumber) { + super("Wrong argument", lineNumber); + } +} diff --git a/src/test.asm b/src/test.asm index 5775a69..96f936a 100644 --- a/src/test.asm +++ b/src/test.asm @@ -2,7 +2,8 @@ num1 db 12 num2 dw 2000 num3 dw ? -add num1, num2 +add num1, 400 +add si, num2 push num2 mul num1 pop ax \ No newline at end of file