339 lines
9.3 KiB
Go
339 lines
9.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var ukazna_tabela = map[string]int{
|
|
"ADD": 0x18,
|
|
"ADDF": 0x58,
|
|
"ADDR": 0x90,
|
|
"AND": 0x40,
|
|
"CLEAR": 0xB4,
|
|
"COMP": 0x28,
|
|
"COMPF": 0x88,
|
|
"COMPR": 0xA0,
|
|
"DIV": 0x24,
|
|
"DIVF": 0x64,
|
|
"DIVR": 0x9C,
|
|
"FIX": 0xC4,
|
|
"FLOAT": 0xC0,
|
|
"HIO": 0xF4,
|
|
"J": 0x3C,
|
|
"JEQ": 0x30,
|
|
"JGT": 0x34,
|
|
"JLT": 0x38,
|
|
"JSUB": 0x48,
|
|
"LDA": 0x00,
|
|
"LDB": 0x68,
|
|
"LDCH": 0x50,
|
|
"LDF": 0x70,
|
|
"LDL": 0x08,
|
|
"LDS": 0x6C,
|
|
"LDT": 0x74,
|
|
"LDX": 0x04,
|
|
"LPS": 0xD0,
|
|
"MUL": 0x20,
|
|
"MULF": 0x60,
|
|
"MULR": 0x98,
|
|
"NORM": 0xC8,
|
|
"OR": 0x44,
|
|
"RD": 0xD4,
|
|
"RMO": 0xAC,
|
|
"RSUB": 0x4C,
|
|
"SHIFTL": 0xA4,
|
|
"SHIFTR": 0xA8,
|
|
"SIO": 0xF0,
|
|
"SSK": 0xEC,
|
|
"STA": 0x0C,
|
|
"STB": 0x78,
|
|
"STCH": 0x54,
|
|
"STF": 0x80,
|
|
"STI": 0xD4,
|
|
"STL": 0x14,
|
|
"STS": 0x74,
|
|
"STSW": 0xE8,
|
|
"STT": 0x84,
|
|
"STX": 0x10,
|
|
"SUB": 0x1C,
|
|
"SUBF": 0x5C,
|
|
"SUBR": 0x94,
|
|
"SVC": 0xB0,
|
|
"TD": 0xE0,
|
|
"TIO": 0xF8,
|
|
"TIX": 0x2C,
|
|
"TIXR": 0xB8,
|
|
"WD": 0xDC,
|
|
}
|
|
|
|
type ukaz interface {
|
|
Temp()
|
|
}
|
|
|
|
func (f format_F1) Temp() {}
|
|
func (f format_F2_n) Temp() {}
|
|
func (f format_F2_r) Temp() {}
|
|
func (f format_F2_rn) Temp() {}
|
|
func (f format_F2_rr) Temp() {}
|
|
|
|
|
|
var register string = `A|X|L|B|S|T|F`
|
|
|
|
type format_F1 struct {
|
|
oznaka string
|
|
opcode int
|
|
format int // F1 - 1, F2 - 2, F3 - 3, F4 - 4, SIC - 5
|
|
velikost int //v bajtih
|
|
}
|
|
|
|
type format_F2_n struct {
|
|
oznaka string
|
|
opcode int
|
|
format int
|
|
velikost int
|
|
n string
|
|
x bool // indeksno naslavljanje
|
|
}
|
|
|
|
type format_F2_r struct {
|
|
oznaka string
|
|
opcode int
|
|
format int
|
|
velikost int
|
|
r1 string
|
|
}
|
|
|
|
type format_F2_rn struct {
|
|
oznaka string
|
|
opcode int
|
|
format int
|
|
velikost int
|
|
r1 string
|
|
n string
|
|
x bool
|
|
}
|
|
|
|
type format_F2_rr struct {
|
|
oznaka string
|
|
opcode int
|
|
format int
|
|
velikost int
|
|
r1 string
|
|
r2 string
|
|
}
|
|
|
|
type format_F3 struct {
|
|
oznaka string
|
|
opcode int
|
|
format int
|
|
velikost int
|
|
}
|
|
|
|
type format_F3_m struct {
|
|
oznaka string
|
|
opcode int
|
|
format int
|
|
velikost int
|
|
naslov string
|
|
x bool
|
|
}
|
|
|
|
func remove_comments_and_empty_lines(el string) bool {
|
|
match_pure_comment, err := regexp.MatchString(`(?m)^[\t ]*\..*$\n`, el)
|
|
if err != nil {
|
|
fmt.Println("Error while matching string.")
|
|
}
|
|
if match_pure_comment {
|
|
return true
|
|
}
|
|
match_empty, err := regexp.MatchString(`(?m)^[\t ]*$\n`, el)
|
|
if err != nil {
|
|
fmt.Println("Error while matching string.")
|
|
}
|
|
if match_empty {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func check_F1(el string, AST *[]ukaz) bool {
|
|
match_F1, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+[A-Za-z]+[\t ]*(\..*)?$\n`, el)
|
|
if err != nil {
|
|
fmt.Println("Error while matching string.")
|
|
}
|
|
if match_F1 {
|
|
var nov_ukaz format_F1
|
|
nov_ukaz.format = 1
|
|
nov_ukaz.velikost = 1
|
|
pattern := regexp.MustCompile(`[\t ]+[A-Za-z]+`)
|
|
mnemonik := strings.Trim(pattern.FindString(el), "\t ")
|
|
nov_ukaz.opcode = ukazna_tabela[mnemonik];
|
|
//fmt.Println("F1: ", mnemonik, nov_ukaz.opcode)
|
|
*AST = append(*AST, nov_ukaz)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func check_F2_n(el string, AST *[]ukaz) bool {
|
|
match_F2_n, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+SVC ((#?|@?)[0-9]+)(, X)?[\t ]*(\..*)?$\n`, el)
|
|
if err != nil {
|
|
fmt.Println("Error while matching string.")
|
|
}
|
|
if match_F2_n {
|
|
var nov_ukaz format_F2_n
|
|
nov_ukaz.format = 2
|
|
nov_ukaz.velikost = 2
|
|
nov_ukaz.opcode = 10
|
|
if !(strings.HasPrefix(el, " ") || strings.HasPrefix(el, "\t")) {
|
|
re := regexp.MustCompile(`(?m)^[A-Z-a-z_]+`)
|
|
nov_ukaz.oznaka = re.FindString(el)
|
|
} else {
|
|
nov_ukaz.oznaka = ""
|
|
}
|
|
re_par := regexp.MustCompile(`[\t ]+(#?|@?)[0-9]+,?`)
|
|
temp := strings.Trim(re_par.FindString(el), "\t ")
|
|
if temp[len(temp) - 1] == ',' {
|
|
nov_ukaz.x = true
|
|
nov_ukaz.n = strings.TrimRight(temp, ",")
|
|
} else {
|
|
nov_ukaz.x = false
|
|
nov_ukaz.n = temp
|
|
}
|
|
//fmt.Println("F2_n ", el[:len(el) - 1], nov_ukaz)
|
|
*AST = append(*AST, nov_ukaz)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func check_F2_r(el string, AST *[]ukaz) bool {
|
|
match_F2_r, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+[A-Za-z]+ (`+register+`)[\t ]*(\..*)?$\n`, el)
|
|
if err != nil {
|
|
fmt.Println("Error while matching string.")
|
|
}
|
|
if match_F2_r {
|
|
var nov_ukaz format_F2_r
|
|
nov_ukaz.format = 2
|
|
nov_ukaz.velikost = 2
|
|
if !(strings.HasPrefix(el, " ") || strings.HasPrefix(el, "\t")) {
|
|
re := regexp.MustCompile(`(?m)^[A-Z-a-z_]+`)
|
|
nov_ukaz.oznaka = re.FindString(el)
|
|
} else {
|
|
nov_ukaz.oznaka = ""
|
|
}
|
|
re_op := regexp.MustCompile(`[\t ]+[A-Za-z]+`)
|
|
nov_ukaz.opcode = ukazna_tabela[strings.Trim(re_op.FindString(el), "\t ")]
|
|
re_par := regexp.MustCompile(`[\t ]+[A-Za-z]+ (`+register+`)`)
|
|
nov_ukaz.r1 = strings.Split(strings.Trim(re_par.FindString(el), "\t \n"), " ")[1]
|
|
//fmt.Println(nov_ukaz)
|
|
*AST = append(*AST, nov_ukaz)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func check_F2_rn(el string, AST *[]ukaz) bool {
|
|
match_F2_rn, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+[A-Za-z]+ (`+register+`), ((#?|@?)[0-9]+)(, X)?[\t ]*(\..*)?$\n`, el)
|
|
if err != nil {
|
|
fmt.Println("Error while matching string.")
|
|
}
|
|
if match_F2_rn {
|
|
var nov_ukaz format_F2_rn
|
|
nov_ukaz.format = 2
|
|
nov_ukaz.velikost = 2
|
|
if !(strings.HasPrefix(el, " ") || strings.HasPrefix(el, "\t")) {
|
|
re := regexp.MustCompile(`(?m)^[A-Z-a-z_]+`)
|
|
nov_ukaz.oznaka = re.FindString(el)
|
|
} else {
|
|
nov_ukaz.oznaka = ""
|
|
}
|
|
re_op := regexp.MustCompile(`[\t ]+[A-Za-z]+`)
|
|
nov_ukaz.opcode = ukazna_tabela[strings.Trim(re_op.FindString(el), "\t ")]
|
|
re_par1 := regexp.MustCompile(`[\t ]+[A-Za-z]+ (`+register+`)`)
|
|
nov_ukaz.r1 = strings.Split(strings.Trim(re_par1.FindString(el), "\t \n"), " ")[1]
|
|
re_par2 := regexp.MustCompile(`(`+register+`), ((#?|@?)[0-9]+),?`)
|
|
temp := strings.Split(re_par2.FindString(el), " ")[1]
|
|
if temp[len(temp) - 1] == ',' {
|
|
nov_ukaz.x = true
|
|
nov_ukaz.n = strings.TrimRight(temp, ",")
|
|
} else {
|
|
nov_ukaz.x = false
|
|
nov_ukaz.n = temp
|
|
}
|
|
//fmt.Println("F2_rn: ", el[:len(el) - 1], nov_ukaz)
|
|
*AST = append(*AST, nov_ukaz)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func check_F2_rr(el string, AST *[]ukaz) bool {
|
|
match_F2_rr, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+[A-Za-z]+ (`+register+`), (`+register+`)[\t ]*(\..*)?$\n`, el)
|
|
if err != nil {
|
|
fmt.Println("Error while matching string.")
|
|
}
|
|
if match_F2_rr {
|
|
var nov_ukaz format_F2_rr
|
|
nov_ukaz.format = 2
|
|
nov_ukaz.velikost = 2
|
|
if !(strings.HasPrefix(el, " ") || strings.HasPrefix(el, "\t")) {
|
|
re := regexp.MustCompile(`(?m)^[A-Z-a-z_]+`)
|
|
nov_ukaz.oznaka = re.FindString(el)
|
|
} else {
|
|
nov_ukaz.oznaka = ""
|
|
}
|
|
re_op := regexp.MustCompile(`[\t ]+[A-Za-z]+`)
|
|
nov_ukaz.opcode = ukazna_tabela[strings.Trim(re_op.FindString(el), "\t ")]
|
|
re_par1 := regexp.MustCompile(`[\t ]+[A-Za-z]+ (`+register+`)`)
|
|
nov_ukaz.r1 = strings.Split(strings.Trim(re_par1.FindString(el), "\t \n"), " ")[1]
|
|
re_par2 := regexp.MustCompile(`(`+register+`), (`+register+`)`)
|
|
nov_ukaz.r2 = strings.Split(re_par2.FindString(el), " ")[1]
|
|
//fmt.Println("F2_rr: ", nov_ukaz)
|
|
*AST = append(*AST, nov_ukaz)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Pregledovalnik bere vhodne vrstice in jih razgradi na posamezne enote.
|
|
// Razpoznane elemente okvalificira (oznaka / mnemonik / operand / komentar)
|
|
// //<zbirniski stavek> ::== [<oznaka stavka>] <ločilo> <mnemonik> <ločilo> {<operand> <ločilo>} [<komentar>]
|
|
func main() {
|
|
inputbyte, err := os.ReadFile("input_invalid.asm")
|
|
if err != nil {
|
|
fmt.Println("Error reading input file: ", err)
|
|
return
|
|
}
|
|
|
|
input := string(inputbyte)
|
|
pattern := regexp.MustCompile(`.*\n`)
|
|
matches := pattern.FindAllString(input, -1)
|
|
var AST []ukaz
|
|
|
|
for _, el := range matches {
|
|
if remove_comments_and_empty_lines(el) {
|
|
continue
|
|
}
|
|
if check_F1(el, &AST) {
|
|
continue
|
|
}
|
|
// TODO !!! odstrani # in @ in x naslalvljaje od F2 formata, saj nima bitov, da to podpre
|
|
if check_F2_n(el, &AST) {
|
|
continue
|
|
}
|
|
if check_F2_r(el, &AST) {
|
|
continue
|
|
}
|
|
if check_F2_rn(el, &AST) {
|
|
continue
|
|
}
|
|
if check_F2_rr(el, &AST) {
|
|
continue
|
|
}
|
|
//match_F2, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+[A-Za-z_]+[\t ](((`+register+`), (`+register+`))|((`+register+`), (#?|@?)[0-9]+)|(`+register+`))[\t ]*(\..*)?$\n`, el)
|
|
}
|
|
}
|