3
This commit is contained in:
parent
70a61f31de
commit
8eb17d757f
@ -1,7 +1,3 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.annimon.asm;
|
||||
|
||||
import com.annimon.asm.exceptions.ExceptionWithLineNumber;
|
||||
@ -27,7 +23,7 @@ import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.Utilities;
|
||||
|
||||
/**
|
||||
*
|
||||
* Îñíîâíàÿ ïàíåëü ïðèëîæåíèÿ.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public class AnalyzerPanel extends JPanel {
|
||||
@ -54,6 +50,7 @@ public class AnalyzerPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void caretUpdate(CaretEvent caretEvent) {
|
||||
// Âûâåñòè ïîçèöèþ êàðåòêè â lineNumberLabel.
|
||||
JTextComponent textComponent = (JTextComponent)caretEvent.getSource();
|
||||
|
||||
int pos = caretEvent.getDot();
|
||||
@ -80,23 +77,28 @@ public class AnalyzerPanel extends JPanel {
|
||||
@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(ex.getMessage());
|
||||
showMessageBox("Error", ex.getMessage(), true);
|
||||
return;
|
||||
}
|
||||
showMessageBox("Source is correct!");
|
||||
showMessageBox("Info","Source is correct!", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showMessageBox(String text) {
|
||||
JOptionPane.showMessageDialog(this, text);
|
||||
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 String getTextFromResource(String res) {
|
||||
|
@ -3,10 +3,10 @@ package com.annimon.asm;
|
||||
import com.annimon.asm.directives.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Êîíâåðòåð äèðåêòèâ.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public class DirectiveConvertor {
|
||||
public class DirectiveConverter {
|
||||
|
||||
private static final Directive[] DIRECTIVES = {
|
||||
new Comma(),
|
||||
@ -20,7 +20,7 @@ public class DirectiveConvertor {
|
||||
/**
|
||||
* Êîíâåðòèðîâàòü äèðåêòèâó â å¸ èäåíòèôèêàòîð.
|
||||
* @param text äèðåêòèâà (dw, push, 0 è ò.ä.)
|
||||
* @return èäåíòèôèêàòîð äèðåêòèâû
|
||||
* @return èäåíòèôèêàòîð äèðåêòèâû.
|
||||
*/
|
||||
public static int convert(String text) {
|
||||
for (int i = 0; i < DIRECTIVES.length; i++) {
|
@ -1,7 +1,3 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.annimon.asm;
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,3 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.annimon.asm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -29,8 +25,8 @@ public class LexicTable {
|
||||
return lexicLines.get(pos);
|
||||
}
|
||||
|
||||
public void updateLexicAt(LexicLine lexic, int pos) {
|
||||
lexicLines.set(pos, lexic);
|
||||
public void updateLexicAt(int pos, LexicLine line) {
|
||||
lexicLines.set(pos, line);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,48 +1,109 @@
|
||||
package com.annimon.asm;
|
||||
|
||||
import com.annimon.asm.exceptions.ExceptionWithLineNumber;
|
||||
import com.annimon.asm.directives.ID;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* Ëåêñè÷åñêèé àíàëèçàòîð.
|
||||
* @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 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 = 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());
|
||||
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 = 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 = split(line);
|
||||
if (parts.length != lexicIds.length) continue;
|
||||
|
||||
lexicIds[i] = varTable.getTypeOfVariable(parts[i]);
|
||||
}
|
||||
}
|
||||
lexicLine.line = lexicIds;
|
||||
|
||||
return lexicLine;
|
||||
}
|
||||
|
||||
private String[] split(String text) {
|
||||
ArrayList<String> parts = new ArrayList<String>();
|
||||
int length = text.length();
|
||||
|
@ -9,7 +9,7 @@ import com.annimon.asm.directives.Variable;
|
||||
import com.annimon.asm.exceptions.ExceptionWithLineNumber;
|
||||
|
||||
/**
|
||||
*
|
||||
* روٍْـيّو<EFBFBD>مّيوى ـٍـًوهـَِْ.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public class SyntaxAnalyzer {
|
||||
@ -19,7 +19,6 @@ public class SyntaxAnalyzer {
|
||||
new Variable()
|
||||
};
|
||||
|
||||
|
||||
private LexicTable lexicTable;
|
||||
|
||||
public SyntaxAnalyzer(LexicTable lexicTable) {
|
||||
|
27
src/com/annimon/asm/Var.java
Normal file
27
src/com/annimon/asm/Var.java
Normal file
@ -0,0 +1,27 @@
|
||||
package com.annimon.asm;
|
||||
|
||||
/**
|
||||
* Êëàññ ïåðåìåííîé.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public class Var {
|
||||
|
||||
String name;
|
||||
int type;
|
||||
String value;
|
||||
|
||||
public Var(String name, int type, String value) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
31
src/com/annimon/asm/VarTable.java
Normal file
31
src/com/annimon/asm/VarTable.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.annimon.asm;
|
||||
|
||||
import com.annimon.asm.directives.ID;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Òàáëèöà ïåðåìåííûõ.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public class VarTable {
|
||||
|
||||
private ArrayList<Var> variables;
|
||||
|
||||
public VarTable() {
|
||||
variables = new ArrayList<Var>();
|
||||
}
|
||||
|
||||
public void addVariable(String name, int type, String value) {
|
||||
variables.add(new Var(name, type, value));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -31,12 +31,14 @@ public class Add extends Directive implements SyntaxChecker {
|
||||
ID.REGISTER_WORD, ID.REGISTER_BYTE,
|
||||
|
||||
// Ðåãèñòð - Ïàìÿòü
|
||||
ID.REGISTER_BYTE, ID.VAR,
|
||||
ID.REGISTER_WORD, ID.VAR,
|
||||
ID.REGISTER_BYTE, ID.VAR_BYTE,
|
||||
ID.REGISTER_WORD, ID.VAR_WORD,
|
||||
ID.REGISTER_WORD, ID.VAR_BYTE,
|
||||
|
||||
// Ïàìÿòü - Ðåãèñòð
|
||||
ID.VAR, ID.REGISTER_BYTE,
|
||||
ID.VAR, ID.REGISTER_WORD,
|
||||
ID.VAR_BYTE, ID.REGISTER_BYTE,
|
||||
ID.VAR_WORD, ID.REGISTER_WORD,
|
||||
ID.VAR_WORD, ID.REGISTER_BYTE,
|
||||
|
||||
// Ðåãèñòð - Çíà÷åíèå
|
||||
ID.REGISTER_BYTE, ID.NUMBER_BYTE,
|
||||
@ -44,8 +46,9 @@ public class Add extends Directive implements SyntaxChecker {
|
||||
ID.REGISTER_WORD, ID.NUMBER_BYTE,
|
||||
|
||||
// Ïàìÿòü - Çíà÷åíèå
|
||||
ID.VAR, ID.NUMBER_BYTE,
|
||||
ID.VAR, ID.NUMBER_WORD,
|
||||
ID.VAR_BYTE, ID.NUMBER_BYTE,
|
||||
ID.VAR_WORD, ID.NUMBER_WORD,
|
||||
ID.VAR_WORD, ID.NUMBER_BYTE,
|
||||
};
|
||||
|
||||
boolean correct = false;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.annimon.asm.directives;
|
||||
|
||||
/**
|
||||
*
|
||||
* Базовый класс директив.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public abstract class Directive {
|
||||
@ -22,7 +22,11 @@ public abstract class Directive {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Проверка на соответствие директиву тексту.
|
||||
* @param text строка директивы, которую нужно проверить.
|
||||
* @return результат совпадения.
|
||||
*/
|
||||
public boolean isDirective(String text) {
|
||||
return text.equalsIgnoreCase(name);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package com.annimon.asm.directives;
|
||||
|
||||
/**
|
||||
*
|
||||
* Ñïèñîê èäåíòèôèêàòîðîâ äèðåêòèâ.
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public class ID {
|
||||
public interface ID {
|
||||
|
||||
public static final int
|
||||
NULL = -1,
|
||||
|
@ -22,7 +22,7 @@ public class Mul extends Directive implements SyntaxChecker {
|
||||
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)) {
|
||||
(ids[1] != ID.VAR_BYTE) && (ids[1] != ID.VAR_WORD) ) {
|
||||
throw new WrongArgumentException(lineNumber);
|
||||
}
|
||||
return true;
|
||||
|
@ -20,7 +20,7 @@ public class Pop extends Directive implements SyntaxChecker {
|
||||
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)) {
|
||||
(ids[i] != ID.VAR_WORD)) {
|
||||
throw new WrongArgumentException(lineNumber);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class Push extends Directive implements SyntaxChecker {
|
||||
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)) {
|
||||
(ids[i] != ID.VAR_WORD)) {
|
||||
throw new WrongArgumentException(lineNumber);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public class Variable extends Directive implements SyntaxChecker {
|
||||
|
||||
@Override
|
||||
public boolean isDirective(String text) {
|
||||
if (Pattern.matches(Pattern.compile("^[^1-9]+[\\w.@_$]").pattern(), text)) {
|
||||
if (Pattern.matches(Pattern.compile("^[^0-9]*[\\w.@_$]").pattern(), text)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user