spo/ass3/zbirnik/parsing/pregledovalnik.go
2026-01-15 15:46:38 +01:00

533 lines
15 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() {}
func (f format_F3_m) Temp() {}
func (f format_F4_m) Temp() {}
func (f format_D) Temp() {}
func (f format_D_n) Temp() {}
func (f format_M_i) Temp() {}
func (f format_M_r) 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 // 2
velikost int
n string
}
type format_F2_r struct {
oznaka string
opcode int
format int // 6
velikost int
r1 string
}
type format_F2_rn struct {
oznaka string
opcode int
format int // 2
velikost int
r1 string
n string
}
type format_F2_rr struct {
oznaka string
opcode int
format int // 2
velikost int
r1 string
r2 string
}
type format_F3_m struct {
oznaka string
opcode int
format int // 3
velikost int
naslov string
x bool
b bool
p bool
e bool
n bool
i bool
}
type format_F4_m struct {
oznaka string
opcode int
format int // 4
velikost int
naslov string
x bool
b bool
p bool
e bool
n bool
i bool
}
type format_D struct {
oznaka string
format int // 6
velikost int
}
type format_D_n struct {
oznaka string
format int // 7
velikost int
operand string
}
type format_M_r struct {
oznaka string
format int // 8
velikost int
operand string
}
type format_M_i struct {
oznaka string
format int // 9
velikost int
operand string
}
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 ")
val, ok := ukazna_tabela[mnemonik];
if !ok {
fmt.Println("Error: Opcode not found.")
return false
}
nov_ukaz.opcode = val
//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]+)[\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.n = strings.TrimRight(temp, ",")
} else {
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]+`)
val, ok := ukazna_tabela[strings.Trim(re_op.FindString(el), "\t ")]
if !ok {
fmt.Println("Error: Opcode not found.")
return false
}
nov_ukaz.opcode = val
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]+)[\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]+`)
val, ok := ukazna_tabela[strings.Trim(re_op.FindString(el), "\t ")]
if !ok {
fmt.Println("Error: Opcode not found.")
return false
}
nov_ukaz.opcode = val
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.n = strings.TrimRight(temp, ",")
} else {
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]+`)
val, ok := ukazna_tabela[strings.Trim(re_op.FindString(el), "\t ")]
if !ok {
fmt.Println("Error: Opcode not found.")
return false
}
nov_ukaz.opcode = val
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
}
func check_F3_m(el string, AST *[]ukaz) bool {
match_F3_m, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+[A-Za-z]+ ([A-Za-z]+|(#?|@?)[0-9+]+)(, X)?[\t ]*(\..*)?$\n`, el)
if err != nil {
fmt.Println("Error while matching string.")
}
if match_F3_m {
var nov_ukaz format_F3_m
nov_ukaz.format = 3
nov_ukaz.velikost = 3
if !(strings.HasPrefix(el, " ") || strings.HasPrefix(el, "\t")) {
re := regexp.MustCompile(`(?m)^[A-Za-z]+`)
nov_ukaz.oznaka = re.FindString(el)
} else {
nov_ukaz.oznaka = ""
}
re_op := regexp.MustCompile(`[\t ]+[A-Za-z]+`)
val, ok := ukazna_tabela[strings.Trim(re_op.FindString(el), "\t ")]
if !ok {
fmt.Println("Error: Opcode not found.")
return false
}
nov_ukaz.opcode = val
// naslov
re_par1 := regexp.MustCompile(`[\t ]+[A-Za-z]+ ([A-Za-z]+|(#?|@?)[0-9+]+)`)
nov_ukaz.naslov = strings.Split(strings.Trim(re_par1.FindString(el), "\t \n"), " ")[1]
if nov_ukaz.naslov[0] == '@' {
nov_ukaz.n = true
nov_ukaz.i = false
nov_ukaz.naslov = nov_ukaz.naslov[1:len(nov_ukaz.naslov)]
} else if nov_ukaz.naslov[0] == '#' {
nov_ukaz.n = false
nov_ukaz.i = true
nov_ukaz.naslov = nov_ukaz.naslov[1:len(nov_ukaz.naslov)]
} else {
//temp
nov_ukaz.n = false
nov_ukaz.i = false
}
// indeksno naslavljanje
re_x := regexp.MustCompile(`(, X)[\t ]*(\..*)?\n`)
if re_x.FindString(el) != "" {
nov_ukaz.x = true
} else {
nov_ukaz.x = false
}
nov_ukaz.e = false
//fmt.Println(el, nov_ukaz)
*AST = append(*AST, nov_ukaz)
return true
}
return false
}
func check_F4_m(el string, AST *[]ukaz) bool {
match_F4_m, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+\+[A-Za-z]+ ([A-Za-z]+|(#?|@?)[0-9+]+)(, X)?[\t ]*(\..*)?$\n`, el)
if err != nil {
fmt.Println("Error while matching string.")
}
if match_F4_m {
var nov_ukaz format_F4_m
nov_ukaz.format = 4
nov_ukaz.velikost = 4
if !(strings.HasPrefix(el, " ") || strings.HasPrefix(el, "\t")) {
re := regexp.MustCompile(`(?m)^[A-Za-z]+`)
nov_ukaz.oznaka = re.FindString(el)
} else {
nov_ukaz.oznaka = ""
}
re_op := regexp.MustCompile(`[\t ]+\+[A-Za-z]+`)
// skip "+"
val, ok := ukazna_tabela[strings.Trim(re_op.FindString(el), "\t +")]
if !ok {
fmt.Println("Error: Opcode not found.")
return false
}
nov_ukaz.opcode = val
// naslov
re_par1 := regexp.MustCompile(`[\t ]+\+[A-Za-z]+ ([A-Za-z]+|(#?|@?)[0-9+]+)`)
nov_ukaz.naslov = strings.Split(strings.Trim(re_par1.FindString(el), "\t \n"), " ")[1]
if nov_ukaz.naslov[0] == '@' {
nov_ukaz.n = true
nov_ukaz.i = false
nov_ukaz.naslov = nov_ukaz.naslov[1:len(nov_ukaz.naslov)]
} else if nov_ukaz.naslov[0] == '#' {
nov_ukaz.n = false
nov_ukaz.i = true
nov_ukaz.naslov = nov_ukaz.naslov[1:len(nov_ukaz.naslov)]
} else {
nov_ukaz.n = false
nov_ukaz.i = false
}
// indeksno naslavljanje
re_x := regexp.MustCompile(`(, X)[\t ]*(\..*)?\n`)
if re_x.FindString(el) != "" {
nov_ukaz.x = true
} else {
nov_ukaz.x = false
}
nov_ukaz.e = true
fmt.Println(el, nov_ukaz)
*AST = append(*AST, nov_ukaz)
return true
}
return false
}
func check_D(el string, AST *[]ukaz) {
match_D, err := regexp.MatchString(`(?m)^[A-Za-z_]*[\t ]+NOBASE[\t ]*(\..*)?$\n`, el)
if err != nil {
fmt.Println("Error while matching string.")
}
if match_D {
var nova_direktiva format_D
if !(strings.HasPrefix(el, " ") || strings.HasPrefix(el, "\t")) {
re := regexp.MustCompile(`(?m)^[A-Za-z]+`)
nov_direktiva.oznaka = re.FindString(el)
} else {
nov_direktiva.oznaka = ""
}
*AST = append(*AST, nova_direktiva)
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_D(el, &AST) {
continue
}
if check_F1(el, &AST) {
continue
}
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
}
// !!! direktivo START je treba preveriti pred F3, sicer jo bo dalo sem
if check_F3_m(el, &AST) {
continue
}
if check_F4_m(el, &AST) {
continue
}
}
}