diff --git a/bin/main b/bin/main index 1fbed0f..fb5a21b 100755 Binary files a/bin/main and b/bin/main differ diff --git a/pkg/linux_amd64/asl.a b/pkg/linux_amd64/asl.a index 29fd5aa..7038983 100644 Binary files a/pkg/linux_amd64/asl.a and b/pkg/linux_amd64/asl.a differ diff --git a/src/asl/parser.go b/src/asl/parser.go index 7b6520e..0ad4aad 100644 --- a/src/asl/parser.go +++ b/src/asl/parser.go @@ -1,317 +1,317 @@ package asl import ( - "strconv" + "strconv" ) const TAB = " " func Parse(token []Token) string { - initParser(token) - - for tokenIndex < len(token) { - parseBlock() - } - - return out + initParser(token) + + for tokenIndex < len(token) { + parseBlock() + } + + return out } func parseBlock() { - if accept("var") { - parseVar() - } else if accept("if") { - parseIf() - } else if accept("while") { - parseWhile() - } else if accept("switch") { - parseSwitch() - } else if accept("for") { - parseFor() - } else if accept("each") { - parseForeach() - } else if accept("func") { - parseFunction() - } else if accept("return") { - parseReturn() - } else if accept("sqf") { - parseSqf() - } else { - parseStatement() - } - - if !end() && !accept("}") { - parseBlock() - } + if accept("var") { + parseVar() + } else if accept("if") { + parseIf() + } else if accept("while") { + parseWhile() + } else if accept("switch") { + parseSwitch() + } else if accept("for") { + parseFor() + } else if accept("each") { + parseForeach() + } else if accept("func") { + parseFunction() + } else if accept("return") { + parseReturn() + } else if accept("sqf") { + parseSqf() + } else { + parseStatement() + } + + if !end() && !accept("}") { + parseBlock() + } } func parseVar() { - expect("var") - appendOut(get().token) - next() - - if accept("=") { - next() - appendOut(" = ") - parseExpression(true) - } - - appendOut(";\n") - expect(";") + expect("var") + appendOut(get().token) + next() + + if accept("=") { + next() + appendOut(" = ") + parseExpression(true) + } + + appendOut(";\n") + expect(";") } func parseIf() { - expect("if") - appendOut("if (") - parseExpression(true) - appendOut(") then {\n") - expect("{") - parseBlock() - expect("}") - - if accept("else") { - next() - expect("{") - appendOut("} else {\n") - parseBlock() - expect("}") - } - - appendOut("};\n") + expect("if") + appendOut("if (") + parseExpression(true) + appendOut(") then {\n") + expect("{") + parseBlock() + expect("}") + + if accept("else") { + next() + expect("{") + appendOut("} else {\n") + parseBlock() + expect("}") + } + + appendOut("};\n") } func parseWhile() { - expect("while") - appendOut("while {") - parseExpression(true) - appendOut("} do {\n") - expect("{") - parseBlock() - expect("}") - appendOut("};\n") + expect("while") + appendOut("while {") + parseExpression(true) + appendOut("} do {\n") + expect("{") + parseBlock() + expect("}") + appendOut("};\n") } func parseSwitch() { - expect("switch") - appendOut("switch (") - parseExpression(true) - appendOut(") do {\n") - expect("{") - parseSwitchBlock() - expect("}") - appendOut("};\n") + expect("switch") + appendOut("switch (") + parseExpression(true) + appendOut(") do {\n") + expect("{") + parseSwitchBlock() + expect("}") + appendOut("};\n") } func parseSwitchBlock() { - if accept("}") { - return - } - - if accept("case") { - expect("case") - appendOut("case ") - parseExpression(true) - expect(":") - appendOut(":\n") - - if !accept("case") && !accept("}") { - appendOut("{\n") - parseBlock() - appendOut("};\n") - } - } else if accept("default") { - expect("default") - expect(":") - appendOut("default:\n") - - if !accept("}") { - appendOut("{\n") - parseBlock() - appendOut("};\n") - } - } - - parseSwitchBlock() + if accept("}") { + return + } + + if accept("case") { + expect("case") + appendOut("case ") + parseExpression(true) + expect(":") + appendOut(":\n") + + if !accept("case") && !accept("}") { + appendOut("{\n") + parseBlock() + appendOut("};\n") + } + } else if accept("default") { + expect("default") + expect(":") + appendOut("default:\n") + + if !accept("}") { + appendOut("{\n") + parseBlock() + appendOut("};\n") + } + } + + parseSwitchBlock() } func parseFor() { - expect("for") - appendOut("for [{") - - // var in first assignment is optional - if accept("var") { - next() - } - - parseExpression(true) - expect(";") - appendOut("}, {") - parseExpression(true) - expect(";") - appendOut("}, {") - parseExpression(true) - expect(";") - appendOut("}] do {\n") - expect("{") - parseBlock() - expect("}") - appendOut("};\n") + expect("for") + appendOut("for [{") + + // var in first assignment is optional + if accept("var") { + next() + } + + parseExpression(true) + expect(";") + appendOut("}, {") + parseExpression(true) + expect(";") + appendOut("}, {") + parseExpression(true) + expect(";") + appendOut("}] do {\n") + expect("{") + parseBlock() + expect("}") + appendOut("};\n") } func parseForeach() { - expect("each") - expr := parseExpression(false) - expect("{") - appendOut("{\n") - parseBlock() - expect("}") - appendOut("} forEach ("+expr+");\n") + expect("each") + expr := parseExpression(false) + expect("{") + appendOut("{\n") + parseBlock() + expect("}") + appendOut("} forEach (" + expr + ");\n") } func parseFunction() { - expect("func") - appendOut(get().token+" = {\n") - next() - expect("(") - parseFunctionParameter() - expect(")") - expect("{") - parseBlock() - expect("}") - appendOut("};\n") + expect("func") + appendOut(get().token + " = {\n") + next() + expect("(") + parseFunctionParameter() + expect(")") + expect("{") + parseBlock() + expect("}") + appendOut("};\n") } func parseFunctionParameter() { - // empty parameter list - if accept("{") { - return; - } - - i := int64(0) - - for !accept(")") { - name := get().token - next() - appendOut(name+" = _this select "+strconv.FormatInt(i, 10)+";\n") - i++ - - if !accept(")") { - expect(",") - } - } + // empty parameter list + if accept("{") { + return + } + + i := int64(0) + + for !accept(")") { + name := get().token + next() + appendOut(name + " = _this select " + strconv.FormatInt(i, 10) + ";\n") + i++ + + if !accept(")") { + expect(",") + } + } } func parseReturn() { - expect("return") - appendOut("return ") - parseExpression(true) - expect(";") - appendOut(";\n") + expect("return") + appendOut("return ") + parseExpression(true) + expect(";") + appendOut(";\n") } func parseSqf() { - expect("sqf") - expect(":") - - for !accept("sqf") { - appendOut(get().token) - next() - } - - appendOut("\n") - expect("sqf") + expect("sqf") + expect(":") + + for !accept("sqf") { + appendOut(get().token) + next() + } + + appendOut("\n") + expect("sqf") } // Everything that does not start with a keyword. func parseStatement() { - // empty block - if accept("}") || accept("case") || accept("default") { - return - } - - // variable or function name - name := get().token - next() - - if accept("=") { - appendOut(name) - parseAssignment() - } else if name == "$" { - name = get().token - next() - parseBuildinFunctionCall(name); - } else { - parseFunctionCall() - appendOut(name+";\n") - } - - if !end() { - parseBlock() - } + // empty block + if accept("}") || accept("case") || accept("default") { + return + } + + // variable or function name + name := get().token + next() + + if accept("=") { + appendOut(name) + parseAssignment() + } else if name == "$" { + name = get().token + next() + parseBuildinFunctionCall(name) + } else { + parseFunctionCall() + appendOut(name + ";\n") + } + + if !end() { + parseBlock() + } } func parseAssignment() { - expect("=") - appendOut(" = "+get().token) - next() - expect(";") - appendOut(";\n") + expect("=") + appendOut(" = " + get().token) + next() + expect(";") + appendOut(";\n") } func parseFunctionCall() { - expect("(") - appendOut("[") - parseParameter() - expect(")") - expect(";") - appendOut("] call ") + expect("(") + appendOut("[") + parseParameter() + expect(")") + expect(";") + appendOut("] call ") } func parseBuildinFunctionCall(name string) { - expect("(") - appendOut("[") - parseParameter() - expect(")") - appendOut("] ") - expect("(") - appendOut(name+" [") - parseParameter() - expect(")") - expect(";") - appendOut("];\n") + expect("(") + appendOut("[") + parseParameter() + expect(")") + appendOut("] ") + expect("(") + appendOut(name + " [") + parseParameter() + expect(")") + expect(";") + appendOut("];\n") } func parseParameter() { - for !accept(")") { - parseExpression(true) - - if !accept(")") { - expect(",") - appendOut(", ") - } - } + for !accept(")") { + parseExpression(true) + + if !accept(")") { + expect(",") + appendOut(", ") + } + } } func parseExpression(out bool) string { - openingBrackets := 0 - output := "" - - for !accept(",") && !accept(":") && !accept(";") && !accept("{") && !accept("}") && (openingBrackets != 0 || !accept(")")) { - current := get().token - - if out { - appendOut(current) - } else { - output += current - } - - if accept("(") { - openingBrackets++ - } else if accept(")") { - openingBrackets-- - } - - next() - } - - return output + openingBrackets := 0 + output := "" + + for !accept(",") && !accept(":") && !accept(";") && !accept("{") && !accept("}") && (openingBrackets != 0 || !accept(")")) { + current := get().token + + if out { + appendOut(current) + } else { + output += current + } + + if accept("(") { + openingBrackets++ + } else if accept(")") { + openingBrackets-- + } + + next() + } + + return output } diff --git a/src/asl/parserHelper.go b/src/asl/parserHelper.go index 706c76d..5bdc5bc 100644 --- a/src/asl/parserHelper.go +++ b/src/asl/parserHelper.go @@ -6,48 +6,48 @@ var out string var offset int func initParser(token []Token) { - if len(token) == 0 { - panic("No tokens provided") - } - - tokens = token - tokenIndex = 0 - out = "" - offset = 0 + if len(token) == 0 { + panic("No tokens provided") + } + + tokens = token + tokenIndex = 0 + out = "" + offset = 0 } func accept(token string) bool { - return tokenIndex < len(tokens) && tokenEqual(token, get()) + return tokenIndex < len(tokens) && tokenEqual(token, get()) } func expect(token string) { - if !tokenEqual(token, get()) { - panic("Parse error, expected '"+token+"' but was '"+get().token+"'") - } - - next() + if !tokenEqual(token, get()) { + panic("Parse error, expected '" + token + "' but was '" + get().token + "'") + } + + next() } func next() { - tokenIndex++ + tokenIndex++ } func get() Token { - if tokenIndex >= len(tokens) { - panic("No more tokens") - } - - return tokens[tokenIndex] + if tokenIndex >= len(tokens) { + panic("No more tokens") + } + + return tokens[tokenIndex] } func end() bool { - return tokenIndex == len(tokens) + return tokenIndex == len(tokens) } func tokenEqual(a string, b Token) bool { - return a == b.token + return a == b.token } func appendOut(str string) { - out += str + out += str } diff --git a/src/asl/tokenizer.go b/src/asl/tokenizer.go index 0d37ce4..86459f5 100644 --- a/src/asl/tokenizer.go +++ b/src/asl/tokenizer.go @@ -1,140 +1,140 @@ package asl import ( - "strings" - "fmt" + "fmt" + "strings" ) -type Token struct{ - token string +type Token struct { + token string } var delimiter = []byte{ - '=', - ';', - '{', - '}', - '(', - ')', - '<', - '>', - '!', - ',', - ':', - '&', - '|', - '$'} + '=', + ';', + '{', + '}', + '(', + ')', + '<', + '>', + '!', + ',', + ':', + '&', + '|', + '$'} var keywords = []string{ - "var", - "if", - "while", - "switch", - "for", - "each", - "func", - "true", - "false", - "case", - "default", - "return", - "sqfstart", - "sqf"} + "var", + "if", + "while", + "switch", + "for", + "each", + "func", + "true", + "false", + "case", + "default", + "return", + "sqfstart", + "sqf"} var whitespace = []byte{' ', '\n', '\t'} func Tokenize(code []byte) []Token { - code = removeComments(code) - tokens := make([]Token, 0) - token := "" - - fmt.Println(string(code)) - - for i := range code { - c := code[i] - - if byteArrayContains(delimiter, c) { - if token != "" { - tokens = append(tokens, Token{token}) - } - - tokens = append(tokens, Token{string(c)}) - token = "" - } else if stringArrayContains(keywords, strings.ToLower(token)) { - tokens = append(tokens, Token{token}) - token = "" - } else if !byteArrayContains(whitespace, c) { - token += string(c) - } - } - - return tokens + code = removeComments(code) + tokens := make([]Token, 0) + token := "" + + fmt.Println(string(code)) + + for i := range code { + c := code[i] + + if byteArrayContains(delimiter, c) { + if token != "" { + tokens = append(tokens, Token{token}) + } + + tokens = append(tokens, Token{string(c)}) + token = "" + } else if stringArrayContains(keywords, strings.ToLower(token)) { + tokens = append(tokens, Token{token}) + token = "" + } else if !byteArrayContains(whitespace, c) { + token += string(c) + } + } + + return tokens } func removeComments(code []byte) []byte { - newcode := make([]byte, len(code)) - j := 0 - - for i := 0; i < len(code); i++ { - c := code[i] - - if c == '/' && nextChar(code, i) == '/' { - i = skipSingleLineComment(code, i+1) - continue - } else if c == '/' && nextChar(code, i) == '*' { - i = skipMultiLineComment(code, i+1) - continue - } + newcode := make([]byte, len(code)) + j := 0 - newcode[j] = c - j++ - } - - return newcode[:j] + for i := 0; i < len(code); i++ { + c := code[i] + + if c == '/' && nextChar(code, i) == '/' { + i = skipSingleLineComment(code, i+1) + continue + } else if c == '/' && nextChar(code, i) == '*' { + i = skipMultiLineComment(code, i+1) + continue + } + + newcode[j] = c + j++ + } + + return newcode[:j] } func nextChar(code []byte, i int) byte { - i++ - - if i < len(code) { - return code[i] - } - - return '0' + i++ + + if i < len(code) { + return code[i] + } + + return '0' } func skipSingleLineComment(code []byte, i int) int { - for i < len(code) && code[i] != '\n' { - i++ - } - - return i + for i < len(code) && code[i] != '\n' { + i++ + } + + return i } func skipMultiLineComment(code []byte, i int) int { - for i < len(code) && !(code[i] == '*' && nextChar(code, i) == '/') { - i++ - } - - return i+1 + for i < len(code) && !(code[i] == '*' && nextChar(code, i) == '/') { + i++ + } + + return i + 1 } func byteArrayContains(haystack []byte, needle byte) bool { - for i := range haystack { - if haystack[i] == needle { - return true; - } - } - - return false + for i := range haystack { + if haystack[i] == needle { + return true + } + } + + return false } func stringArrayContains(haystack []string, needle string) bool { - for i := range haystack { - if haystack[i] == needle { - return true; - } - } - - return false + for i := range haystack { + if haystack[i] == needle { + return true + } + } + + return false } diff --git a/src/main/asl.go b/src/main/asl.go index 59dbe20..41991fd 100644 --- a/src/main/asl.go +++ b/src/main/asl.go @@ -1,16 +1,16 @@ package main import ( - "io/ioutil" - "asl" - "fmt" + "asl" + "fmt" + "io/ioutil" ) -func main(){ - // read test file - code, _ := ioutil.ReadFile("in/simple.asl") - token := asl.Tokenize(code) - out := asl.Parse(token) - - fmt.Println(out) +func main() { + // read test file + code, _ := ioutil.ReadFile("in/simple.asl") + token := asl.Tokenize(code) + out := asl.Parse(token) + + fmt.Println(out) }