Start supporting numbers and strings

This commit is contained in:
2023-02-25 16:45:54 +00:00
parent cbae1c4629
commit 636101f1fa
15 changed files with 379 additions and 37 deletions

7
src/comment.go Normal file
View File

@@ -0,0 +1,7 @@
package main
var commentCompile = makeRegex("( *)//.*")
func isComment(code UNPARSEcode) bool {
return commentCompile.MatchString(code.code)
}

102
src/import.go Normal file
View File

@@ -0,0 +1,102 @@
package main
import (
"bufio"
"errors"
"log"
"os"
"path/filepath"
)
func FileExists(filename string) bool {
if _, err := os.Stat(filename); err == nil {
return true
} else if errors.Is(err, os.ErrNotExist) {
return false
} else {
return false
}
}
func readFile(path string) []UNPARSEcode {
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
return nil
}
defer file.Close()
scanner := bufio.NewScanner(file)
// optionally, resize scanner's capacity for lines over 64K, see next example
output := []UNPARSEcode{}
line := 1
for scanner.Scan() {
output = append(output, UNPARSEcode{scanner.Text(), line})
line++
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
return nil
}
return output
}
func importMod(realpath string, origin string, main bool) string {
extention := filepath.Ext(realpath)
path := realpath
if extention == "" {
path += ".ar"
}
ex, err := os.Getwd()
if err != nil {
return err.Error()
}
executable, err := os.Executable()
if err != nil {
return err.Error()
}
executable = filepath.Dir(executable)
isABS := filepath.IsAbs(path)
var pathsToTest []string
if isABS {
pathsToTest = []string{
filepath.Join(path),
filepath.Join(realpath, "init.ar"),
}
} else {
pathsToTest = []string{
filepath.Join(origin, realpath, "init.ar"),
filepath.Join(origin, path),
filepath.Join(origin, "modules", path),
filepath.Join(origin, "modules", realpath, "init.ar"),
filepath.Join(ex, path),
filepath.Join(ex, "modules", realpath, "init.ar"),
filepath.Join(ex, "modules", path),
filepath.Join(executable, "modules", realpath, "init.ar"),
filepath.Join(executable, "modules", path),
}
}
var p string
var found bool
for _, p = range pathsToTest {
if FileExists(p) {
found = true
break
}
}
if !found {
return "File does not exist: " + realpath
}
codelines := readFile(p)
translated, translationerr := translate(codelines)
if translationerr != "" {
return translationerr
}
run(translated)
return ""
}

View File

@@ -1,8 +1,23 @@
package main
import "fmt"
import (
"os"
)
// args without the program path
var Args = os.Args[1:]
func main() {
translate("")
fmt.Println("hello world")
ex, e := os.Getwd()
if e != nil {
panic(e)
}
if len(Args) == 0 {
panic("No file specified")
}
err := importMod(Args[0], ex, true)
if err != "" {
panic(err)
}
}

View File

@@ -6,6 +6,8 @@ import (
"strings"
)
var numberCompile = makeRegex("( *)((\\-)?(([0-9]*(\\.[0-9]+)?)(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)|(0b[10]+(.[10]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)|(0x[a-fA-F0-9]+(.[a-fA-F0-9]+)?)|(0o[0-7]+(.[0-7]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?))( *)")
// a number type
type number = *big.Rat
@@ -19,6 +21,10 @@ func stringToNumber(str string) (*big.Rat, bool) {
return newNumber().SetString(str)
}
func isNumber(code UNPARSEcode) bool {
return numberCompile.MatchString(code.code)
}
// converts a number type to a string
func numberToString(num number, fraction int) string {
if fraction != 0 {
@@ -72,3 +78,12 @@ var subscript = map[byte]string{
'8': "₈",
'9': "₉",
}
// returns translateNumber, success, error
func parseNumber(code UNPARSEcode) (translateNumber, bool, string) {
output, _ := newNumber().SetString(code.code)
return translateNumber{
number: output,
line: code.line,
}, true, ""
}

14
src/regex.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import (
"log"
"regexp"
)
func makeRegex(str string) *regexp.Regexp {
Compile, err := regexp.Compile("^(" + str + ")$")
if err != nil {
log.Fatal(err)
}
return Compile
}

24
src/run.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import "fmt"
func runLine(line any) (any, string) {
switch line.(type) {
case translateNumber:
return (numberToString(line.(translateNumber).number, 0)), ""
case translateString:
return (line.(translateString).str), ""
}
return nil, "Error: invalid code on line " + fmt.Sprint(line.(translateNumber).line) + ": " + line.(translateNumber).code
}
// returns error
func run(translated []any) (any, string) {
for _, val := range translated {
_, err := runLine(val)
if err != "" {
return nil, err
}
}
return nil, ""
}

42
src/string.go Normal file
View File

@@ -0,0 +1,42 @@
package main
import (
"fmt"
"strconv"
"strings"
)
var stringCompile = makeRegex("(( *)\"((\\\\([a-z\\\"'`]))|[^\\\"])*\"( *))|(( *)'((\\\\([a-z\\'\"`]))|[^\\'])*'( *))")
func isString(code UNPARSEcode) bool {
return stringCompile.MatchString(code.code)
}
func unquoted(
str string,
) (string, error) {
str = strings.Trim(str, " ")
if str[0] == '\'' {
str = strings.Replace(str, "\\\"", "\"", -1)
str = strings.Replace(str, "\"", "\\\"", -1)
}
str = str[1 : len(str)-1]
str = strings.Replace(str, "\\'", "'", -1)
str = "\"" + str + "\""
return strconv.Unquote(str)
}
// returns translateString, success, error
func parseString(code UNPARSEcode) (translateString, bool, string) {
trim := strings.Trim(code.code, " ")
unquoted, err := unquoted(trim)
if err != nil {
return translateString{}, false, "Syntax Error: invalid string on line " + fmt.Sprint(code.line) + ": " + code.code
}
return translateString{
str: unquoted,
line: code.line,
}, true, ""
}

View File

@@ -2,9 +2,42 @@ package main
import (
"fmt"
"log"
)
func translate(code string) {
output, _ := newNumber().SetString("3.1415")
fmt.Println(numberToString(output, 0))
// returns (translateNumber | translateString), success, error
func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine bool) (any, bool, string) {
if isLine {
if isComment(code) {
return nil, true, ""
}
}
if isNumber(code) {
return parseNumber(code)
} else if isString(code) {
return parseString(code)
}
if isLine {
return nil, false, "Syntax Error: invalid code on line " + fmt.Sprint(code.line) + ": " + code.code
}
return nil, false, ""
}
// returns [](translateNumber | translateString), error
func translate(codelines []UNPARSEcode) ([]any, string) {
translated := []any{}
for i, code := range codelines {
val, _, err := translateVal(code, i, codelines, true)
if err != "" {
log.Fatal(err)
return nil, err
}
if val == nil {
continue
}
translated = append(translated, val)
}
return translated, ""
}

18
src/types.go Normal file
View File

@@ -0,0 +1,18 @@
package main
type UNPARSEcode struct {
code string
line int
}
type translateNumber struct {
number
code string
line int
}
type translateString struct {
str string
code string
line int
}