From c8fe68033962956cabc073172b0732c0e90bbc71 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 15 Nov 2018 18:47:32 +0200 Subject: [PATCH] 1 --- build.xml | 74 + nbproject/build-impl.xml | 1411 +++++++++++++++++ nbproject/genfiles.properties | 8 + nbproject/private/config.properties | 0 nbproject/private/private.properties | 6 + nbproject/private/private.xml | 4 + nbproject/project.properties | 73 + nbproject/project.xml | 15 + src/com/annimon/asm/AnalyzerPanel.java | 111 ++ src/com/annimon/asm/DirectiveConvertor.java | 34 + src/com/annimon/asm/LexicLine.java | 20 + src/com/annimon/asm/LexicTable.java | 51 + src/com/annimon/asm/LexicalAnalyzer.java | 75 + src/com/annimon/asm/Main.java | 22 + src/com/annimon/asm/SyntaxAnalyzer.java | 31 + src/com/annimon/asm/directives/Add.java | 17 + .../annimon/asm/directives/ByteRegister.java | 32 + src/com/annimon/asm/directives/ByteValue.java | 31 + src/com/annimon/asm/directives/Comma.java | 17 + src/com/annimon/asm/directives/DB.java | 17 + src/com/annimon/asm/directives/DW.java | 17 + src/com/annimon/asm/directives/Directive.java | 33 + src/com/annimon/asm/directives/ID.java | 36 + .../annimon/asm/directives/InfinityValue.java | 31 + src/com/annimon/asm/directives/Mul.java | 17 + .../annimon/asm/directives/NumericValue.java | 45 + src/com/annimon/asm/directives/Pop.java | 17 + src/com/annimon/asm/directives/Push.java | 17 + src/com/annimon/asm/directives/Register.java | 29 + src/com/annimon/asm/directives/Variable.java | 22 + .../annimon/asm/directives/WordRegister.java | 30 + src/com/annimon/asm/directives/WordValue.java | 31 + .../exceptions/ExceptionWithLineNumber.java | 30 + src/test.asm | 8 + 34 files changed, 2412 insertions(+) create mode 100644 build.xml create mode 100644 nbproject/build-impl.xml create mode 100644 nbproject/genfiles.properties create mode 100644 nbproject/private/config.properties create mode 100644 nbproject/private/private.properties create mode 100644 nbproject/private/private.xml create mode 100644 nbproject/project.properties create mode 100644 nbproject/project.xml create mode 100644 src/com/annimon/asm/AnalyzerPanel.java create mode 100644 src/com/annimon/asm/DirectiveConvertor.java create mode 100644 src/com/annimon/asm/LexicLine.java create mode 100644 src/com/annimon/asm/LexicTable.java create mode 100644 src/com/annimon/asm/LexicalAnalyzer.java create mode 100644 src/com/annimon/asm/Main.java create mode 100644 src/com/annimon/asm/SyntaxAnalyzer.java create mode 100644 src/com/annimon/asm/directives/Add.java create mode 100644 src/com/annimon/asm/directives/ByteRegister.java create mode 100644 src/com/annimon/asm/directives/ByteValue.java create mode 100644 src/com/annimon/asm/directives/Comma.java create mode 100644 src/com/annimon/asm/directives/DB.java create mode 100644 src/com/annimon/asm/directives/DW.java create mode 100644 src/com/annimon/asm/directives/Directive.java create mode 100644 src/com/annimon/asm/directives/ID.java create mode 100644 src/com/annimon/asm/directives/InfinityValue.java create mode 100644 src/com/annimon/asm/directives/Mul.java create mode 100644 src/com/annimon/asm/directives/NumericValue.java create mode 100644 src/com/annimon/asm/directives/Pop.java create mode 100644 src/com/annimon/asm/directives/Push.java create mode 100644 src/com/annimon/asm/directives/Register.java create mode 100644 src/com/annimon/asm/directives/Variable.java create mode 100644 src/com/annimon/asm/directives/WordRegister.java create mode 100644 src/com/annimon/asm/directives/WordValue.java create mode 100644 src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java create mode 100644 src/test.asm diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..a5fa8bd --- /dev/null +++ b/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + Builds, tests, and runs the project AsmAnalyzer. + + + diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml new file mode 100644 index 0000000..2c449fb --- /dev/null +++ b/nbproject/build-impl.xml @@ -0,0 +1,1411 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties new file mode 100644 index 0000000..1ec44ee --- /dev/null +++ b/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=2439a656 +build.xml.script.CRC32=1475b172 +build.xml.stylesheet.CRC32=28e38971@1.56.0.46 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=2439a656 +nbproject/build-impl.xml.script.CRC32=44145888 +nbproject/build-impl.xml.stylesheet.CRC32=c6d2a60f@1.56.0.46 diff --git a/nbproject/private/config.properties b/nbproject/private/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/nbproject/private/private.properties b/nbproject/private/private.properties new file mode 100644 index 0000000..fbbfe24 --- /dev/null +++ b/nbproject/private/private.properties @@ -0,0 +1,6 @@ +compile.on.save=true +do.depend=false +do.jar=true +javac.debug=true +javadoc.preview=true +user.properties.file=C:\\Users\\aNNiMON\\AppData\\Roaming\\NetBeans\\dev\\build.properties diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml new file mode 100644 index 0000000..4750962 --- /dev/null +++ b/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..6b9e8b1 --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,73 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=AsmAnalyzer +application.vendor=aNNiMON +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/AsmAnalyzer.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.6 +javac.target=1.6 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=com.annimon.asm.Main +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=windows-1251 +src.dir=src +test.src.dir=test diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..4cb08a2 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + AsmAnalyzer + + + + + + + + + diff --git a/src/com/annimon/asm/AnalyzerPanel.java b/src/com/annimon/asm/AnalyzerPanel.java new file mode 100644 index 0000000..b59608d --- /dev/null +++ b/src/com/annimon/asm/AnalyzerPanel.java @@ -0,0 +1,111 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +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.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); + } + + private void initTextPane() { + textPane = new JTextPane(); + textPane.setPreferredSize(new Dimension(300, 300)); + textPane.addCaretListener(new CaretListener() { + + @Override + public void caretUpdate(CaretEvent caretEvent) { + 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) { + System.out.println(ex.getMessage()); + } + } + }); + } + + 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/DirectiveConvertor.java b/src/com/annimon/asm/DirectiveConvertor.java new file mode 100644 index 0000000..e583dc7 --- /dev/null +++ b/src/com/annimon/asm/DirectiveConvertor.java @@ -0,0 +1,34 @@ +package com.annimon.asm; + +import com.annimon.asm.directives.*; + +/** + * + * @author aNNiMON + */ +public class DirectiveConvertor { + + 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 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; + } +} diff --git a/src/com/annimon/asm/LexicLine.java b/src/com/annimon/asm/LexicLine.java new file mode 100644 index 0000000..36949f7 --- /dev/null +++ b/src/com/annimon/asm/LexicLine.java @@ -0,0 +1,20 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +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; + } +} diff --git a/src/com/annimon/asm/LexicTable.java b/src/com/annimon/asm/LexicTable.java new file mode 100644 index 0000000..3d7d946 --- /dev/null +++ b/src/com/annimon/asm/LexicTable.java @@ -0,0 +1,51 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +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(LexicLine lexic, int pos) { + lexicLines.set(pos, lexic); + } + + @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(); + } + +} diff --git a/src/com/annimon/asm/LexicalAnalyzer.java b/src/com/annimon/asm/LexicalAnalyzer.java new file mode 100644 index 0000000..427f49f --- /dev/null +++ b/src/com/annimon/asm/LexicalAnalyzer.java @@ -0,0 +1,75 @@ +package com.annimon.asm; + +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import java.util.ArrayList; + +/** + * + * @author aNNiMON + */ +public class LexicalAnalyzer { + + private String[] lines; + private LexicTable lexicTable; + + public LexicalAnalyzer(String text) { + lines = text.split(System.lineSeparator()); + + lexicTable = new LexicTable(); + } + + public LexicTable getLexicTable() { + return lexicTable; + } + + public void analyze() { + for (int i = 0; i < lines.length; i++) { + analyzeLine(i); + } + System.out.println(lexicTable.toString()); + } + + private void analyzeLine(int lineNumber) { + String line = lines[lineNumber]; + if(line.isEmpty()) return; + String[] parts = split(line); + + int length = parts.length; + int[] lexicIds = new int[length]; + for (int i = 0; i < length; i++) { + lexicIds[i] = DirectiveConvertor.convert(parts[i].trim()); + } + + lexicTable.addLexicLine(lineNumber+1, lexicIds); + } + + private 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/Main.java b/src/com/annimon/asm/Main.java new file mode 100644 index 0000000..ee07d70 --- /dev/null +++ b/src/com/annimon/asm/Main.java @@ -0,0 +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(); + } + +} diff --git a/src/com/annimon/asm/SyntaxAnalyzer.java b/src/com/annimon/asm/SyntaxAnalyzer.java new file mode 100644 index 0000000..38081b4 --- /dev/null +++ b/src/com/annimon/asm/SyntaxAnalyzer.java @@ -0,0 +1,31 @@ +package com.annimon.asm; + +import com.annimon.asm.directives.ID; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; + +/** + * + * @author aNNiMON + */ +public class SyntaxAnalyzer { + + 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 { + if (lexic[0] == ID.VAR) { + + } + } + +} diff --git a/src/com/annimon/asm/directives/Add.java b/src/com/annimon/asm/directives/Add.java new file mode 100644 index 0000000..f2aece0 --- /dev/null +++ b/src/com/annimon/asm/directives/Add.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class Add extends Directive { + + public Add() { + super("add", ID.ADD); + } + +} diff --git a/src/com/annimon/asm/directives/ByteRegister.java b/src/com/annimon/asm/directives/ByteRegister.java new file mode 100644 index 0000000..2952159 --- /dev/null +++ b/src/com/annimon/asm/directives/ByteRegister.java @@ -0,0 +1,32 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class ByteRegister extends Register { + + public ByteRegister() { + super(); + } + + @Override + public int getId() { + return ID.REGISTER_BYTE; + } + + @Override + protected String[] getRegisterNames() { + return new String[] { + "ah", "al", + "bh", "bl", + "ch", "cl", + "dh", "dl", + }; + } + +} diff --git a/src/com/annimon/asm/directives/ByteValue.java b/src/com/annimon/asm/directives/ByteValue.java new file mode 100644 index 0000000..952a306 --- /dev/null +++ b/src/com/annimon/asm/directives/ByteValue.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class ByteValue extends NumericValue { + + public ByteValue() { + super(); + } + + @Override + public int getId() { + return ID.NUMBER_BYTE; + } + + @Override + protected boolean checkRange(Integer value) { + if (value == null) return false; + if ( (-128 <= value.intValue()) && (value.intValue() <= 255) ) { + return true; + } + return false; + } + +} diff --git a/src/com/annimon/asm/directives/Comma.java b/src/com/annimon/asm/directives/Comma.java new file mode 100644 index 0000000..b6b2ec5 --- /dev/null +++ b/src/com/annimon/asm/directives/Comma.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public 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 new file mode 100644 index 0000000..cf965ca --- /dev/null +++ b/src/com/annimon/asm/directives/DB.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public 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 new file mode 100644 index 0000000..f20416c --- /dev/null +++ b/src/com/annimon/asm/directives/DW.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class DW extends Directive { + + public DW() { + super("dw", ID.DW); + } + +} diff --git a/src/com/annimon/asm/directives/Directive.java b/src/com/annimon/asm/directives/Directive.java new file mode 100644 index 0000000..d248300 --- /dev/null +++ b/src/com/annimon/asm/directives/Directive.java @@ -0,0 +1,33 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public abstract class Directive { + + protected String name; + protected int id; + + protected Directive(String name, int id) { + this.name = name; + this.id = id; + } + + public String getName() { + return name; + } + + public int getId() { + return id; + } + + + public boolean isDirective(String text) { + return text.equalsIgnoreCase(name); + } +} diff --git a/src/com/annimon/asm/directives/ID.java b/src/com/annimon/asm/directives/ID.java new file mode 100644 index 0000000..626950b --- /dev/null +++ b/src/com/annimon/asm/directives/ID.java @@ -0,0 +1,36 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class ID { + + public static final int + NULL = -1, + + DB = 0, + DW = 1, + + COMMA = 5, + + ADD = 10, + MUL = 11, + PUSH = 12, + POP = 13, + + NUMBER_BYTE = 100, + NUMBER_WORD = 101, + NUMBER_INFINITY = 102, + + REGISTER_BYTE = 200, + REGISTER_WORD = 201, + + VAR = 500, + VAR_BYTE = 501, + VAR_WORD = 502; +} diff --git a/src/com/annimon/asm/directives/InfinityValue.java b/src/com/annimon/asm/directives/InfinityValue.java new file mode 100644 index 0000000..d9d1514 --- /dev/null +++ b/src/com/annimon/asm/directives/InfinityValue.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * Неопределённое значение (?) + * @author aNNiMON + */ +public class InfinityValue extends NumericValue { + + public InfinityValue() { + super(); + } + + @Override + public int getId() { + return ID.NUMBER_INFINITY; + } + + @Override + public boolean isDirective(String text) { + return text.equals("?"); + } + + @Override + protected boolean checkRange(Integer value) { + return true; + } +} diff --git a/src/com/annimon/asm/directives/Mul.java b/src/com/annimon/asm/directives/Mul.java new file mode 100644 index 0000000..bc47611 --- /dev/null +++ b/src/com/annimon/asm/directives/Mul.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class Mul extends Directive { + + public Mul() { + super("mul", ID.MUL); + } + +} diff --git a/src/com/annimon/asm/directives/NumericValue.java b/src/com/annimon/asm/directives/NumericValue.java new file mode 100644 index 0000000..9a7e6cd --- /dev/null +++ b/src/com/annimon/asm/directives/NumericValue.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public abstract class NumericValue extends Directive { + + public NumericValue() { + super("", ID.NULL); + } + + @Override + public boolean isDirective(String text) { + if (text == null) return false; + + Integer value = parse(text); + return checkRange(value); + } + + protected abstract boolean checkRange(Integer value); + + private Integer parse(String text) { + int value; + if (text.toLowerCase().endsWith("h")) { + String hex = text.substring(0, text.length() - 1); + try { + value = Integer.parseInt(hex, 16); + return value; + } catch (NumberFormatException numberFormatException) { + return null; + } + } + try { + value = Integer.parseInt(text); + return value; + } catch (NumberFormatException numberFormatException) { + return null; + } + } +} diff --git a/src/com/annimon/asm/directives/Pop.java b/src/com/annimon/asm/directives/Pop.java new file mode 100644 index 0000000..4aedd94 --- /dev/null +++ b/src/com/annimon/asm/directives/Pop.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class Pop extends Directive { + + public Pop() { + super("pop", ID.POP); + } + +} diff --git a/src/com/annimon/asm/directives/Push.java b/src/com/annimon/asm/directives/Push.java new file mode 100644 index 0000000..63eea09 --- /dev/null +++ b/src/com/annimon/asm/directives/Push.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class Push extends Directive { + + public Push() { + super("push", ID.PUSH); + } + +} diff --git a/src/com/annimon/asm/directives/Register.java b/src/com/annimon/asm/directives/Register.java new file mode 100644 index 0000000..02b8186 --- /dev/null +++ b/src/com/annimon/asm/directives/Register.java @@ -0,0 +1,29 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public abstract class Register extends Directive { + + public Register() { + super("", ID.NULL); + } + + @Override + public boolean isDirective(String text) { + String[] names = getRegisterNames(); + for (int i = 0; i < names.length; i++) { + if (text.equalsIgnoreCase(names[i])) { + return true; + } + } + return false; + } + + protected abstract String[] getRegisterNames(); +} diff --git a/src/com/annimon/asm/directives/Variable.java b/src/com/annimon/asm/directives/Variable.java new file mode 100644 index 0000000..50b1fbd --- /dev/null +++ b/src/com/annimon/asm/directives/Variable.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class Variable extends Directive { + + public Variable() { + super("", ID.VAR); + } + + @Override + public boolean isDirective(String text) { + return true; + } + +} diff --git a/src/com/annimon/asm/directives/WordRegister.java b/src/com/annimon/asm/directives/WordRegister.java new file mode 100644 index 0000000..93ff828 --- /dev/null +++ b/src/com/annimon/asm/directives/WordRegister.java @@ -0,0 +1,30 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class WordRegister extends Register { + + public WordRegister() { + super(); + } + + @Override + public int getId() { + return ID.REGISTER_WORD; + } + + @Override + protected String[] getRegisterNames() { + return new String[] { + "ax", "bx", "cx", "dx", + "cs", "ds", "ss", "es" + }; + } + +} diff --git a/src/com/annimon/asm/directives/WordValue.java b/src/com/annimon/asm/directives/WordValue.java new file mode 100644 index 0000000..f7e6709 --- /dev/null +++ b/src/com/annimon/asm/directives/WordValue.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class WordValue extends NumericValue { + + public WordValue() { + super(); + } + + @Override + public int getId() { + return ID.NUMBER_WORD; + } + + @Override + protected boolean checkRange(Integer value) { + if (value == null) return false; + if ( (-32768 <= value.intValue()) && (value.intValue() <= 65535) ) { + return true; + } + return false; + } + +} diff --git a/src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java b/src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java new file mode 100644 index 0000000..927abd8 --- /dev/null +++ b/src/com/annimon/asm/exceptions/ExceptionWithLineNumber.java @@ -0,0 +1,30 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.annimon.asm.exceptions; + +/** + * + * @author aNNiMON + */ +public abstract class ExceptionWithLineNumber extends Exception { + + private int lineNumber; + + public ExceptionWithLineNumber(int lineNumber) { + super(); + this.lineNumber = 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/test.asm b/src/test.asm new file mode 100644 index 0000000..5775a69 --- /dev/null +++ b/src/test.asm @@ -0,0 +1,8 @@ +num1 db 12 +num2 dw 2000 +num3 dw ? + +add num1, num2 +push num2 +mul num1 +pop ax \ No newline at end of file