mirror of
https://github.com/Kugelschieber/asl.git
synced 2026-01-18 12:00:25 +00:00
Added compiler context.
This commit is contained in:
@@ -6,350 +6,350 @@ import (
|
|||||||
|
|
||||||
// Parses tokens, validates code to a specific degree
|
// Parses tokens, validates code to a specific degree
|
||||||
// and writes SQF code into desired location.
|
// and writes SQF code into desired location.
|
||||||
func Parse(token []Token, prettyPrinting bool) string {
|
func (c *Compiler) Parse(token []Token, prettyPrinting bool) string {
|
||||||
if !initParser(token, prettyPrinting) {
|
if !c.initParser(token, prettyPrinting) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
for tokenIndex < len(token) {
|
for c.tokenIndex < len(token) {
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return c.out
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBlock() {
|
func (c *Compiler) parseBlock() {
|
||||||
if accept("var") {
|
if c.accept("var") {
|
||||||
parseVar()
|
c.parseVar()
|
||||||
} else if accept("if") {
|
} else if c.accept("if") {
|
||||||
parseIf()
|
c.parseIf()
|
||||||
} else if accept("while") {
|
} else if c.accept("while") {
|
||||||
parseWhile()
|
c.parseWhile()
|
||||||
} else if accept("switch") {
|
} else if c.accept("switch") {
|
||||||
parseSwitch()
|
c.parseSwitch()
|
||||||
} else if accept("for") {
|
} else if c.accept("for") {
|
||||||
parseFor()
|
c.parseFor()
|
||||||
} else if accept("foreach") {
|
} else if c.accept("foreach") {
|
||||||
parseForeach()
|
c.parseForeach()
|
||||||
} else if accept("func") {
|
} else if c.accept("func") {
|
||||||
parseFunction()
|
c.parseFunction()
|
||||||
} else if accept("return") {
|
} else if c.accept("return") {
|
||||||
parseReturn()
|
c.parseReturn()
|
||||||
} else if accept("try") {
|
} else if c.accept("try") {
|
||||||
parseTryCatch()
|
c.parseTryCatch()
|
||||||
} else if accept("exitwith") {
|
} else if c.accept("exitwith") {
|
||||||
parseExitWith()
|
c.parseExitWith()
|
||||||
} else if accept("waituntil") {
|
} else if c.accept("waituntil") {
|
||||||
parseWaitUntil()
|
c.parseWaitUntil()
|
||||||
} else if accept("case") || accept("default") {
|
} else if c.accept("case") || c.accept("default") {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
parseStatement()
|
c.parseStatement()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !end() && !accept("}") {
|
if !c.end() && !c.accept("}") {
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseVar() {
|
func (c *Compiler) parseVar() {
|
||||||
expect("var")
|
c.expect("var")
|
||||||
appendOut(get().token, false)
|
c.appendOut(c.get().token, false)
|
||||||
next()
|
c.next()
|
||||||
|
|
||||||
if accept("=") {
|
if c.accept("=") {
|
||||||
next()
|
c.next()
|
||||||
appendOut(" = ", false)
|
c.appendOut(" = ", false)
|
||||||
|
|
||||||
if accept("[") {
|
if c.accept("[") {
|
||||||
parseArray()
|
c.parseArray()
|
||||||
} else {
|
} else {
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(";")
|
c.expect(";")
|
||||||
appendOut(";", true)
|
c.appendOut(";", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseArray() {
|
func (c *Compiler) parseArray() {
|
||||||
expect("[")
|
c.expect("[")
|
||||||
appendOut("[", false)
|
c.appendOut("[", false)
|
||||||
|
|
||||||
if !accept("]") {
|
if !c.accept("]") {
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
|
|
||||||
for accept(",") {
|
for c.accept(",") {
|
||||||
next()
|
c.next()
|
||||||
appendOut(",", false)
|
c.appendOut(",", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect("]")
|
c.expect("]")
|
||||||
appendOut("]", false)
|
c.appendOut("]", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseIf() {
|
func (c *Compiler) parseIf() {
|
||||||
expect("if")
|
c.expect("if")
|
||||||
appendOut("if (", false)
|
c.appendOut("if (", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
appendOut(") then {", true)
|
c.appendOut(") then {", true)
|
||||||
expect("{")
|
c.expect("{")
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
|
|
||||||
if accept("else") {
|
if c.accept("else") {
|
||||||
next()
|
c.next()
|
||||||
expect("{")
|
c.expect("{")
|
||||||
appendOut("} else {", true)
|
c.appendOut("} else {", true)
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseWhile() {
|
func (c *Compiler) parseWhile() {
|
||||||
expect("while")
|
c.expect("while")
|
||||||
appendOut("while {", false)
|
c.appendOut("while {", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
appendOut("} do {", true)
|
c.appendOut("} do {", true)
|
||||||
expect("{")
|
c.expect("{")
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
appendOut("};", false)
|
c.appendOut("};", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSwitch() {
|
func (c *Compiler) parseSwitch() {
|
||||||
expect("switch")
|
c.expect("switch")
|
||||||
appendOut("switch (", false)
|
c.appendOut("switch (", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
appendOut(") do {", true)
|
c.appendOut(") do {", true)
|
||||||
expect("{")
|
c.expect("{")
|
||||||
parseSwitchBlock()
|
c.parseSwitchBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSwitchBlock() {
|
func (c *Compiler) parseSwitchBlock() {
|
||||||
if accept("}") {
|
if c.accept("}") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if accept("case") {
|
if c.accept("case") {
|
||||||
next()
|
c.next()
|
||||||
appendOut("case ", false)
|
c.appendOut("case ", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
expect(":")
|
c.expect(":")
|
||||||
appendOut(":", true)
|
c.appendOut(":", true)
|
||||||
|
|
||||||
if !accept("case") && !accept("}") && !accept("default") {
|
if !c.accept("case") && !c.accept("}") && !c.accept("default") {
|
||||||
appendOut("{", true)
|
c.appendOut("{", true)
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
} else if accept("default") {
|
} else if c.accept("default") {
|
||||||
next()
|
c.next()
|
||||||
expect(":")
|
c.expect(":")
|
||||||
appendOut("default:", true)
|
c.appendOut("default:", true)
|
||||||
|
|
||||||
if !accept("}") {
|
if !c.accept("}") {
|
||||||
appendOut("{", true)
|
c.appendOut("{", true)
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parseSwitchBlock()
|
c.parseSwitchBlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFor() {
|
func (c *Compiler) parseFor() {
|
||||||
expect("for")
|
c.expect("for")
|
||||||
appendOut("for [{", false)
|
c.appendOut("for [{", false)
|
||||||
|
|
||||||
// var in first assignment is optional
|
// var in first assignment is optional
|
||||||
if accept("var") {
|
if c.accept("var") {
|
||||||
next()
|
c.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
expect(";")
|
c.expect(";")
|
||||||
appendOut("}, {", false)
|
c.appendOut("}, {", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
expect(";")
|
c.expect(";")
|
||||||
appendOut("}, {", false)
|
c.appendOut("}, {", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
appendOut("}] do {", true)
|
c.appendOut("}] do {", true)
|
||||||
expect("{")
|
c.expect("{")
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseForeach() {
|
func (c *Compiler) parseForeach() {
|
||||||
expect("foreach")
|
c.expect("foreach")
|
||||||
expr := parseExpression(false)
|
expr := c.parseExpression(false)
|
||||||
expect("{")
|
c.expect("{")
|
||||||
appendOut("{", true)
|
c.appendOut("{", true)
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
appendOut("} forEach ("+expr+");", true)
|
c.appendOut("} forEach ("+expr+");", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFunction() {
|
func (c *Compiler) parseFunction() {
|
||||||
expect("func")
|
c.expect("func")
|
||||||
appendOut(get().token+" = {", true)
|
c.appendOut(c.get().token+" = {", true)
|
||||||
next()
|
c.next()
|
||||||
expect("(")
|
c.expect("(")
|
||||||
parseFunctionParameter()
|
c.parseFunctionParameter()
|
||||||
expect(")")
|
c.expect(")")
|
||||||
expect("{")
|
c.expect("{")
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFunctionParameter() {
|
func (c *Compiler) parseFunctionParameter() {
|
||||||
// empty parameter list
|
// empty parameter list
|
||||||
if accept("{") {
|
if c.accept("{") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
appendOut("params [", false)
|
c.appendOut("params [", false)
|
||||||
|
|
||||||
for !accept(")") {
|
for !c.accept(")") {
|
||||||
name := get().token
|
name := c.get().token
|
||||||
next()
|
c.next()
|
||||||
|
|
||||||
if accept("=") {
|
if c.accept("=") {
|
||||||
next()
|
c.next()
|
||||||
value := get().token
|
value := c.get().token
|
||||||
next()
|
c.next()
|
||||||
appendOut("[\""+name+"\","+value+"]", false)
|
c.appendOut("[\""+name+"\","+value+"]", false)
|
||||||
} else {
|
} else {
|
||||||
appendOut("\""+name+"\"", false)
|
c.appendOut("\""+name+"\"", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !accept(")") {
|
if !c.accept(")") {
|
||||||
expect(",")
|
c.expect(",")
|
||||||
appendOut(",", false)
|
c.appendOut(",", false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appendOut("];", true)
|
c.appendOut("];", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseReturn() {
|
func (c *Compiler) parseReturn() {
|
||||||
expect("return")
|
c.expect("return")
|
||||||
appendOut("return ", false)
|
c.appendOut("return ", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
expect(";")
|
c.expect(";")
|
||||||
appendOut(";", true)
|
c.appendOut(";", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTryCatch() {
|
func (c *Compiler) parseTryCatch() {
|
||||||
expect("try")
|
c.expect("try")
|
||||||
expect("{")
|
c.expect("{")
|
||||||
appendOut("try {", true)
|
c.appendOut("try {", true)
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
expect("catch")
|
c.expect("catch")
|
||||||
expect("{")
|
c.expect("{")
|
||||||
appendOut("} catch {", true)
|
c.appendOut("} catch {", true)
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseExitWith() {
|
func (c *Compiler) parseExitWith() {
|
||||||
expect("exitwith")
|
c.expect("exitwith")
|
||||||
expect("{")
|
c.expect("{")
|
||||||
appendOut("if (true) exitWith {", true)
|
c.appendOut("if (true) exitWith {", true)
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
expect("}")
|
c.expect("}")
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseWaitUntil() {
|
func (c *Compiler) parseWaitUntil() {
|
||||||
expect("waituntil")
|
c.expect("waituntil")
|
||||||
expect("(")
|
c.expect("(")
|
||||||
appendOut("waitUntil {", false)
|
c.appendOut("waitUntil {", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
|
|
||||||
if accept(";") {
|
if c.accept(";") {
|
||||||
next()
|
c.next()
|
||||||
appendOut(";", false)
|
c.appendOut(";", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(")")
|
c.expect(")")
|
||||||
expect(";")
|
c.expect(";")
|
||||||
appendOut("};", true)
|
c.appendOut("};", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseInlineCode() string {
|
func (c *Compiler) parseInlineCode() string {
|
||||||
expect("code")
|
c.expect("code")
|
||||||
expect("(")
|
c.expect("(")
|
||||||
|
|
||||||
code := get().token
|
code := c.get().token
|
||||||
next()
|
c.next()
|
||||||
output := "{}"
|
output := "{}"
|
||||||
|
|
||||||
if len(code) > 2 {
|
if len(code) > 2 {
|
||||||
output = "{"+Parse(Tokenize([]byte(code[1:len(code)-1])), pretty)+"}"
|
//output = "{"+Parse(Tokenize([]byte(code[1:len(code)-1])), pretty)+"}"
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(")")
|
c.expect(")")
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything that does not start with a keyword.
|
// Everything that does not start with a keyword.
|
||||||
func parseStatement() {
|
func (c *Compiler) parseStatement() {
|
||||||
// empty block
|
// empty block
|
||||||
if accept("}") || accept("case") || accept("default") {
|
if c.accept("}") || c.accept("case") || c.accept("default") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// variable or function name
|
// variable or function name
|
||||||
name := get().token
|
name := c.get().token
|
||||||
next()
|
c.next()
|
||||||
|
|
||||||
if accept("=") {
|
if c.accept("=") {
|
||||||
appendOut(name, false)
|
c.appendOut(name, false)
|
||||||
parseAssignment()
|
c.parseAssignment()
|
||||||
} else {
|
} else {
|
||||||
parseFunctionCall(true, name)
|
c.parseFunctionCall(true, name)
|
||||||
expect(";")
|
c.expect(";")
|
||||||
appendOut(";", true)
|
c.appendOut(";", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !end() {
|
if !c.end() {
|
||||||
parseBlock()
|
c.parseBlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAssignment() {
|
func (c *Compiler) parseAssignment() {
|
||||||
expect("=")
|
c.expect("=")
|
||||||
appendOut(" = ", false)
|
c.appendOut(" = ", false)
|
||||||
parseExpression(true)
|
c.parseExpression(true)
|
||||||
expect(";")
|
c.expect(";")
|
||||||
appendOut(";", true)
|
c.appendOut(";", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFunctionCall(out bool, name string) string {
|
func (c *Compiler) parseFunctionCall(out bool, name string) string {
|
||||||
output := ""
|
output := ""
|
||||||
|
|
||||||
expect("(")
|
c.expect("(")
|
||||||
leftParams, leftParamCount := parseParameter(false)
|
leftParams, leftParamCount := c.parseParameter(false)
|
||||||
expect(")")
|
c.expect(")")
|
||||||
|
|
||||||
if accept("(") {
|
if c.accept("(") {
|
||||||
// buildin function
|
// buildin function
|
||||||
next()
|
c.next()
|
||||||
rightParams, rightParamCount := parseParameter(false)
|
rightParams, rightParamCount := c.parseParameter(false)
|
||||||
expect(")")
|
c.expect(")")
|
||||||
|
|
||||||
if leftParamCount > 1 {
|
if leftParamCount > 1 {
|
||||||
leftParams = "[" + leftParams + "]"
|
leftParams = "[" + leftParams + "]"
|
||||||
@@ -369,143 +369,143 @@ func parseFunctionCall(out bool, name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if out {
|
if out {
|
||||||
appendOut(output, false)
|
c.appendOut(output, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseParameter(out bool) (string, int) {
|
func (c *Compiler) parseParameter(out bool) (string, int) {
|
||||||
output := ""
|
output := ""
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
for !accept(")") {
|
for !c.accept(")") {
|
||||||
output += parseExpression(out)
|
output += c.parseExpression(out)
|
||||||
count++
|
count++
|
||||||
|
|
||||||
if !accept(")") {
|
if !c.accept(")") {
|
||||||
expect(",")
|
c.expect(",")
|
||||||
output += ", "
|
output += ", "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if out {
|
if out {
|
||||||
appendOut(output, false)
|
c.appendOut(output, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output, count
|
return output, count
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseExpression(out bool) string {
|
func (c *Compiler) parseExpression(out bool) string {
|
||||||
output := parseArith()
|
output := c.parseArith()
|
||||||
|
|
||||||
for accept("<") || accept(">") || accept("&") || accept("|") || accept("=") || accept("!") {
|
for c.accept("<") || c.accept(">") || c.accept("&") || c.accept("|") || c.accept("=") || c.accept("!") {
|
||||||
if accept("<") {
|
if c.accept("<") {
|
||||||
output += "<"
|
output += "<"
|
||||||
next()
|
c.next()
|
||||||
} else if accept(">") {
|
} else if c.accept(">") {
|
||||||
output += ">"
|
output += ">"
|
||||||
next()
|
c.next()
|
||||||
} else if accept("&") {
|
} else if c.accept("&") {
|
||||||
next()
|
c.next()
|
||||||
expect("&")
|
c.expect("&")
|
||||||
output += "&&"
|
output += "&&"
|
||||||
} else if accept("|") {
|
} else if c.accept("|") {
|
||||||
next()
|
c.next()
|
||||||
expect("|")
|
c.expect("|")
|
||||||
output += "||"
|
output += "||"
|
||||||
} else if accept("=") {
|
} else if c.accept("=") {
|
||||||
output += "="
|
output += "="
|
||||||
next()
|
c.next()
|
||||||
} else {
|
} else {
|
||||||
next()
|
c.next()
|
||||||
expect("=")
|
c.expect("=")
|
||||||
output += "!="
|
output += "!="
|
||||||
}
|
}
|
||||||
|
|
||||||
if accept("=") {
|
if c.accept("=") {
|
||||||
output += "="
|
output += "="
|
||||||
next()
|
c.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
output += parseExpression(false)
|
output += c.parseExpression(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if out {
|
if out {
|
||||||
appendOut(output, false)
|
c.appendOut(output, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseIdentifier() string {
|
func (c *Compiler) parseIdentifier() string {
|
||||||
output := ""
|
output := ""
|
||||||
|
|
||||||
if accept("code") {
|
if c.accept("code") {
|
||||||
output += parseInlineCode()
|
output += c.parseInlineCode()
|
||||||
} else if seek("(") && !accept("!") && !accept("-") {
|
} else if c.seek("(") && !c.accept("!") && !c.accept("-") {
|
||||||
name := get().token
|
name := c.get().token
|
||||||
next()
|
c.next()
|
||||||
output = "(" + parseFunctionCall(false, name) + ")"
|
output = "(" + c.parseFunctionCall(false, name) + ")"
|
||||||
} else if seek("[") {
|
} else if c.seek("[") {
|
||||||
output += "("+get().token
|
output += "("+c.get().token
|
||||||
next()
|
c.next()
|
||||||
expect("[")
|
c.expect("[")
|
||||||
output += " select ("+parseExpression(false)+"))"
|
output += " select ("+c.parseExpression(false)+"))"
|
||||||
expect("]")
|
c.expect("]")
|
||||||
} else if accept("!") || accept("-") {
|
} else if c.accept("!") || c.accept("-") {
|
||||||
output = get().token
|
output = c.get().token
|
||||||
next()
|
c.next()
|
||||||
output += parseTerm()
|
output += c.parseTerm()
|
||||||
} else {
|
} else {
|
||||||
output = get().token
|
output = c.get().token
|
||||||
next()
|
c.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTerm() string {
|
func (c *Compiler) parseTerm() string {
|
||||||
if accept("(") {
|
if c.accept("(") {
|
||||||
expect("(")
|
c.expect("(")
|
||||||
output := "(" + parseExpression(false) + ")"
|
output := "(" + c.parseExpression(false) + ")"
|
||||||
expect(")")
|
c.expect(")")
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseIdentifier()
|
return c.parseIdentifier()
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFactor() string {
|
func (c *Compiler) parseFactor() string {
|
||||||
output := parseTerm()
|
output := c.parseTerm()
|
||||||
|
|
||||||
for accept("*") || accept("/") { // TODO: modulo?
|
for c.accept("*") || c.accept("/") { // TODO: modulo?
|
||||||
if accept("*") {
|
if c.accept("*") {
|
||||||
output += "*"
|
output += "*"
|
||||||
} else {
|
} else {
|
||||||
output += "/"
|
output += "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
c.next()
|
||||||
output += parseExpression(false)
|
output += c.parseExpression(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseArith() string {
|
func (c *Compiler) parseArith() string {
|
||||||
output := parseFactor()
|
output := c.parseFactor()
|
||||||
|
|
||||||
for accept("+") || accept("-") {
|
for c.accept("+") || c.accept("-") {
|
||||||
if accept("+") {
|
if c.accept("+") {
|
||||||
output += "+"
|
output += "+"
|
||||||
} else {
|
} else {
|
||||||
output += "-"
|
output += "-"
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
c.next()
|
||||||
output += parseExpression(false)
|
output += c.parseExpression(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|||||||
@@ -1,81 +1,83 @@
|
|||||||
package asl
|
package asl
|
||||||
|
|
||||||
var tokens []Token
|
type Compiler struct {
|
||||||
var tokenIndex int
|
tokens []Token
|
||||||
var out string
|
tokenIndex int
|
||||||
var offset int
|
out string
|
||||||
var pretty bool
|
offset int
|
||||||
|
pretty bool
|
||||||
|
}
|
||||||
|
|
||||||
// Initilizes the parser.
|
// Initilizes the parser.
|
||||||
func initParser(token []Token, prettyPrinting bool) bool {
|
func (c *Compiler) initParser(token []Token, prettyPrinting bool) bool {
|
||||||
if len(token) == 0 {
|
if len(token) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens = token
|
c.tokens = token
|
||||||
tokenIndex = 0
|
c.tokenIndex = 0
|
||||||
out = ""
|
c.out = ""
|
||||||
offset = 0
|
c.offset = 0
|
||||||
pretty = prettyPrinting
|
c.pretty = prettyPrinting
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true, if current token matches expected one.
|
// Returns true, if current token matches expected one.
|
||||||
// Does not throw parse errors and checks if token is available.
|
// Does not throw parse errors and checks if token is available.
|
||||||
func accept(token string) bool {
|
func (c *Compiler) accept(token string) bool {
|
||||||
return tokenIndex < len(tokens) && tokenEqual(token, get())
|
return c.tokenIndex < len(c.tokens) && c.tokenEqual(token, c.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hard version of "accept".
|
// Hard version of "accept".
|
||||||
// Throws if current token does not match expected one.
|
// Throws if current token does not match expected one.
|
||||||
func expect(token string) {
|
func (c *Compiler) expect(token string) {
|
||||||
if !tokenEqual(token, get()) {
|
if !c.tokenEqual(token, c.get()) {
|
||||||
panic("Parse error, expected '" + token + "' but was '" + get().token + "'")
|
panic("Parse error, expected '" + token + "' but was '" + c.get().token + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
c.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true, if the next token matches expected one.
|
// Returns true, if the next token matches expected one.
|
||||||
// Does not throw parse errors and checks if token is available.
|
// Does not throw parse errors and checks if token is available.
|
||||||
func seek(token string) bool {
|
func (c *Compiler) seek(token string) bool {
|
||||||
if tokenIndex+1 >= len(tokens) {
|
if c.tokenIndex+1 >= len(c.tokens) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokenEqual(token, tokens[tokenIndex+1])
|
return c.tokenEqual(token, c.tokens[c.tokenIndex+1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increases token counter, so that the next token is compared.
|
// Increases token counter, so that the next token is compared.
|
||||||
func next() {
|
func (c *Compiler) next() {
|
||||||
tokenIndex++
|
c.tokenIndex++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns current token or throws, if no more tokens are available.
|
// Returns current token or throws, if no more tokens are available.
|
||||||
func get() Token {
|
func (c *Compiler) get() Token {
|
||||||
if tokenIndex >= len(tokens) {
|
if c.tokenIndex >= len(c.tokens) {
|
||||||
panic("No more tokens")
|
panic("No more tokens")
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens[tokenIndex]
|
return c.tokens[c.tokenIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the end of input code was reached.
|
// Returns true if the end of input code was reached.
|
||||||
func end() bool {
|
func (c *Compiler) end() bool {
|
||||||
return tokenIndex == len(tokens)
|
return c.tokenIndex == len(c.tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if two strings match.
|
// Checks if two strings match.
|
||||||
func tokenEqual(a string, b Token) bool {
|
func (c *Compiler) tokenEqual(a string, b Token) bool {
|
||||||
return a == b.token
|
return a == b.token
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends the output string to current SQF code output.
|
// Appends the output string to current SQF code output.
|
||||||
func appendOut(str string, newLine bool) {
|
func (c *Compiler) appendOut(str string, newLine bool) {
|
||||||
out += str
|
c.out += str
|
||||||
|
|
||||||
if newLine && pretty {
|
if newLine && c.pretty {
|
||||||
out += "\r\n"
|
c.out += "\r\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,8 +155,9 @@ func getCompiled(t *testing.T, file string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tokens := asl.Tokenize(code)
|
tokens := asl.Tokenize(code)
|
||||||
|
compiler := asl.Compiler{}
|
||||||
|
|
||||||
return asl.Parse(tokens, true)
|
return compiler.Parse(tokens, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func equal(t *testing.T, got, want string) {
|
func equal(t *testing.T, got, want string) {
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ func compile(path string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
token := asl.Tokenize(code)
|
token := asl.Tokenize(code)
|
||||||
sqf := asl.Parse(token, pretty)
|
compiler := asl.Compiler{}
|
||||||
|
sqf := compiler.Parse(token, pretty)
|
||||||
|
|
||||||
os.MkdirAll(filepath.FromSlash(path+PathSeparator+aslFiles[i].out), 0777)
|
os.MkdirAll(filepath.FromSlash(path+PathSeparator+aslFiles[i].out), 0777)
|
||||||
err = ioutil.WriteFile(out, []byte(sqf), 0666)
|
err = ioutil.WriteFile(out, []byte(sqf), 0666)
|
||||||
|
|||||||
Reference in New Issue
Block a user