This commit is contained in:
Victor 2018-11-15 18:47:44 +02:00
parent c8fe680339
commit 70a61f31de
26 changed files with 280 additions and 80 deletions

View File

@ -16,6 +16,7 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTextPane; import javax.swing.JTextPane;
@ -86,12 +87,18 @@ public class AnalyzerPanel extends JPanel {
try { try {
syn.analyze(); syn.analyze();
} catch (ExceptionWithLineNumber ex) { } 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) { private String getTextFromResource(String res) {
try { try {
InputStream is = getClass().getResourceAsStream(res); InputStream is = getClass().getResourceAsStream(res);

View File

@ -1,6 +1,11 @@
package com.annimon.asm; 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; import com.annimon.asm.exceptions.ExceptionWithLineNumber;
/** /**
@ -9,6 +14,12 @@ import com.annimon.asm.exceptions.ExceptionWithLineNumber;
*/ */
public class SyntaxAnalyzer { public class SyntaxAnalyzer {
private static final SyntaxChecker[] DIRECTIVES = {
new Add(), new Mul(), new Push(), new Pop(),
new Variable()
};
private LexicTable lexicTable; private LexicTable lexicTable;
public SyntaxAnalyzer(LexicTable lexicTable) { public SyntaxAnalyzer(LexicTable lexicTable) {
@ -23,8 +34,10 @@ public class SyntaxAnalyzer {
} }
private void analyzeLine(int lineNumber, int[] lexic) throws ExceptionWithLineNumber { 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;
}
} }
} }

View File

@ -1,17 +1,63 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; 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 * @author aNNiMON
*/ */
public class Add extends Directive { public class Add extends Directive implements SyntaxChecker {
public Add() { public Add() {
super("add", ID.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;
}
} }

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -1,17 +1,32 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; 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 * @author aNNiMON
*/ */
public class Mul extends Directive { public class Mul extends Directive implements SyntaxChecker {
public Mul() { public Mul() {
super("mul", ID.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;
}
} }

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**
@ -27,6 +23,12 @@ public abstract class NumericValue extends Directive {
private Integer parse(String text) { private Integer parse(String text) {
int value; int value;
if (text.toLowerCase().endsWith("h")) { 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); String hex = text.substring(0, text.length() - 1);
try { try {
value = Integer.parseInt(hex, 16); value = Integer.parseInt(hex, 16);

View File

@ -1,17 +1,31 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; 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 * @author aNNiMON
*/ */
public class Pop extends Directive { public class Pop extends Directive implements SyntaxChecker {
public Pop() { public Pop() {
super("pop", ID.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;
}
} }

View File

@ -1,17 +1,32 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; 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 * @author aNNiMON
*/ */
public class Push extends Directive { public class Push extends Directive implements SyntaxChecker {
public Push() { public Push() {
super("push", ID.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;
}
} }

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -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;
}

View File

@ -1,14 +1,16 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; 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 * @author aNNiMON
*/ */
public class Variable extends Directive { public class Variable extends Directive implements SyntaxChecker {
public Variable() { public Variable() {
super("", ID.VAR); super("", ID.VAR);
@ -16,7 +18,27 @@ public class Variable extends Directive {
@Override @Override
public boolean isDirective(String text) { public boolean isDirective(String text) {
if (Pattern.matches(Pattern.compile("^[^1-9]+[\\w.@_$]").pattern(), text)) {
return true; 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;
}
} }

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**
@ -23,7 +19,8 @@ public class WordRegister extends Register {
protected String[] getRegisterNames() { protected String[] getRegisterNames() {
return new String[] { return new String[] {
"ax", "bx", "cx", "dx", "ax", "bx", "cx", "dx",
"cs", "ds", "ss", "es" "cs", "ds", "ss", "es",
"sp", "bp", "si", "di"
}; };
} }

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.annimon.asm.directives; package com.annimon.asm.directives;
/** /**

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -2,7 +2,8 @@ num1 db 12
num2 dw 2000 num2 dw 2000
num3 dw ? num3 dw ?
add num1, num2 add num1, 400
add si, num2
push num2 push num2
mul num1 mul num1
pop ax pop ax