2022-08-15 12:04:57 -06:00
|
|
|
package parser
|
|
|
|
|
|
|
|
import "fmt"
|
2022-08-17 11:50:33 -06:00
|
|
|
import "sort"
|
2022-08-15 12:04:57 -06:00
|
|
|
|
|
|
|
func doIndent (indent int, input ...string) (output string) {
|
|
|
|
for index := 0; index < indent; index ++ {
|
|
|
|
output += "\t"
|
|
|
|
}
|
|
|
|
for _, inputSection := range input {
|
|
|
|
output += inputSection
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-08-17 11:50:33 -06:00
|
|
|
func sortMapKeysAlphabetically[KEY_TYPE any] (
|
|
|
|
unsortedMap map[string] KEY_TYPE,
|
|
|
|
) (
|
|
|
|
sortedKeys []string,
|
|
|
|
) {
|
|
|
|
sortedKeys = make([]string, len(unsortedMap))
|
|
|
|
index := 0
|
|
|
|
for key, _ := range unsortedMap {
|
|
|
|
sortedKeys[index] = key
|
|
|
|
index ++
|
|
|
|
}
|
|
|
|
sort.Strings(sortedKeys)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-08-15 12:04:57 -06:00
|
|
|
func (tree *SyntaxTree) ToString (indent int) (output string) {
|
|
|
|
output += doIndent(indent, ":arf\n")
|
|
|
|
|
|
|
|
if tree.author != "" {
|
|
|
|
output += doIndent(indent, "author \"", tree.author, "\"\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
if tree.license != "" {
|
|
|
|
output += doIndent(indent, "license \"", tree.license, "\"\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, require := range tree.requires {
|
|
|
|
output += doIndent(indent, "require \"", require, "\"\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
output += doIndent(indent, "---\n")
|
|
|
|
|
2022-08-18 15:45:34 -06:00
|
|
|
typeSectionKeys := sortMapKeysAlphabetically(tree.typeSections)
|
|
|
|
for _, name := range typeSectionKeys {
|
|
|
|
output += tree.typeSections[name].ToString(indent)
|
|
|
|
}
|
|
|
|
|
2022-08-20 11:42:09 -06:00
|
|
|
objtSectionKeys := sortMapKeysAlphabetically(tree.objtSections)
|
|
|
|
for _, name := range objtSectionKeys {
|
|
|
|
output += tree.objtSections[name].ToString(indent)
|
|
|
|
}
|
|
|
|
|
2022-08-21 00:40:04 -06:00
|
|
|
enumSectionKeys := sortMapKeysAlphabetically(tree.enumSections)
|
|
|
|
for _, name := range enumSectionKeys {
|
|
|
|
output += tree.enumSections[name].ToString(indent)
|
|
|
|
}
|
|
|
|
|
2022-08-23 20:25:21 -06:00
|
|
|
faceSectionKeys := sortMapKeysAlphabetically(tree.faceSections)
|
|
|
|
for _, name := range faceSectionKeys {
|
|
|
|
output += tree.faceSections[name].ToString(indent)
|
|
|
|
}
|
|
|
|
|
2022-08-17 11:50:33 -06:00
|
|
|
dataSectionKeys := sortMapKeysAlphabetically(tree.dataSections)
|
|
|
|
for _, name := range dataSectionKeys {
|
|
|
|
output += tree.dataSections[name].ToString(indent)
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
2022-09-02 00:36:14 -06:00
|
|
|
|
|
|
|
funcSectionKeys := sortMapKeysAlphabetically(tree.funcSections)
|
|
|
|
for _, name := range funcSectionKeys {
|
|
|
|
output += tree.funcSections[name].ToString(indent)
|
|
|
|
}
|
2022-08-15 12:04:57 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-02 22:01:01 -06:00
|
|
|
func (identifier Identifier) ToString () (output string) {
|
2022-08-15 12:04:57 -06:00
|
|
|
for index, trailItem := range identifier.trail {
|
|
|
|
if index > 0 {
|
|
|
|
output += "."
|
|
|
|
}
|
|
|
|
|
2022-08-15 15:05:57 -06:00
|
|
|
output += trailItem
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (what *Type) ToString () (output string) {
|
|
|
|
if what.kind == TypeKindBasic {
|
|
|
|
output += what.name.ToString()
|
|
|
|
} else {
|
|
|
|
output += "{"
|
|
|
|
output += what.points.ToString()
|
2022-08-16 18:53:27 -06:00
|
|
|
|
|
|
|
if what.kind == TypeKindArray {
|
|
|
|
output += " "
|
|
|
|
if what.length == 0 {
|
|
|
|
output += ".."
|
|
|
|
} else {
|
|
|
|
output += fmt.Sprint(what.length)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-15 12:04:57 -06:00
|
|
|
output += "}"
|
|
|
|
}
|
|
|
|
|
|
|
|
if what.mutable {
|
|
|
|
output += ":mut"
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-02 22:01:01 -06:00
|
|
|
func (declaration Declaration) ToString () (output string) {
|
2022-08-15 12:04:57 -06:00
|
|
|
output += declaration.name + ":"
|
|
|
|
output += declaration.what.ToString()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-02 22:01:01 -06:00
|
|
|
func (attributes ObjectInitializationValues) ToString (
|
2022-08-16 22:49:49 -06:00
|
|
|
indent int,
|
2022-08-15 12:04:57 -06:00
|
|
|
) (
|
|
|
|
output string,
|
|
|
|
) {
|
2022-08-17 11:50:33 -06:00
|
|
|
for _, name := range sortMapKeysAlphabetically(attributes.attributes) {
|
|
|
|
value := attributes.attributes[name]
|
|
|
|
|
2022-08-17 17:40:16 -06:00
|
|
|
output += doIndent(indent, ".", name)
|
2022-08-16 22:49:49 -06:00
|
|
|
if value.kind == ArgumentKindObjectInitializationValues {
|
2022-08-16 21:45:25 -06:00
|
|
|
output += "\n"
|
|
|
|
output += value.ToString(indent + 1, true)
|
|
|
|
} else {
|
2022-08-17 17:40:16 -06:00
|
|
|
output += " " + value.ToString(0, false) + "\n"
|
2022-08-16 21:45:25 -06:00
|
|
|
}
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-02 22:01:01 -06:00
|
|
|
func (values ArrayInitializationValues) ToString (
|
2022-08-16 22:49:49 -06:00
|
|
|
indent int,
|
|
|
|
) (
|
|
|
|
output string,
|
|
|
|
) {
|
|
|
|
for _, value := range values.values {
|
|
|
|
output += value.ToString(indent, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-02 22:01:01 -06:00
|
|
|
func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
|
2022-09-02 21:38:30 -06:00
|
|
|
if ownLine {
|
|
|
|
output += doIndent(indent)
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
|
|
|
|
2022-09-02 21:38:30 -06:00
|
|
|
output += "[" + phrase.command.ToString(0, false)
|
|
|
|
for _, argument := range phrase.arguments {
|
|
|
|
output += " " + argument.ToString(0, false)
|
|
|
|
}
|
2022-08-15 12:04:57 -06:00
|
|
|
output += "]"
|
|
|
|
|
|
|
|
if len(phrase.returnsTo) > 0 {
|
|
|
|
output += " ->"
|
|
|
|
for _, returnItem := range phrase.returnsTo {
|
|
|
|
output += " " + returnItem.ToString(0, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-02 21:38:30 -06:00
|
|
|
if ownLine {
|
2022-08-15 12:04:57 -06:00
|
|
|
output += "\n"
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (argument *Argument) ToString (indent int, breakLine bool) (output string) {
|
|
|
|
if !breakLine { indent = 0 }
|
2022-08-16 23:07:12 -06:00
|
|
|
if argument.kind == ArgumentKindNil {
|
|
|
|
output += "NIL-ARGUMENT"
|
2022-08-16 22:13:14 -06:00
|
|
|
if breakLine { output += "\n" }
|
|
|
|
return
|
|
|
|
}
|
2022-08-15 12:04:57 -06:00
|
|
|
|
2022-08-16 13:50:34 -06:00
|
|
|
switch argument.kind {
|
2022-08-15 12:04:57 -06:00
|
|
|
case ArgumentKindPhrase:
|
2022-09-02 22:01:01 -06:00
|
|
|
output += argument.value.(Phrase).ToString (
|
2022-08-15 12:04:57 -06:00
|
|
|
indent,
|
2022-08-16 22:49:49 -06:00
|
|
|
breakLine)
|
2022-08-15 12:04:57 -06:00
|
|
|
|
2022-08-16 22:49:49 -06:00
|
|
|
case ArgumentKindObjectInitializationValues:
|
2022-08-16 21:45:25 -06:00
|
|
|
// this should only appear in contexts where breakLine is true
|
2022-09-02 22:01:01 -06:00
|
|
|
output += argument.value.(ObjectInitializationValues).
|
2022-08-16 23:04:52 -06:00
|
|
|
ToString(indent)
|
2022-08-16 22:49:49 -06:00
|
|
|
|
|
|
|
case ArgumentKindArrayInitializationValues:
|
|
|
|
// this should only appear in contexts where breakLine is true
|
2022-09-02 22:01:01 -06:00
|
|
|
output += argument.value.(ArrayInitializationValues).
|
2022-08-16 23:04:52 -06:00
|
|
|
ToString(indent)
|
2022-08-15 12:04:57 -06:00
|
|
|
|
|
|
|
case ArgumentKindIdentifier:
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
2022-09-02 22:01:01 -06:00
|
|
|
argument.value.(Identifier).ToString())
|
2022-08-16 23:04:52 -06:00
|
|
|
if breakLine { output += "\n" }
|
2022-08-15 12:04:57 -06:00
|
|
|
|
|
|
|
case ArgumentKindDeclaration:
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
2022-09-02 22:01:01 -06:00
|
|
|
argument.value.(Declaration).ToString())
|
2022-08-16 23:04:52 -06:00
|
|
|
if breakLine { output += "\n" }
|
2022-08-15 12:04:57 -06:00
|
|
|
|
|
|
|
case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat:
|
|
|
|
output += doIndent(indent, fmt.Sprint(argument.value))
|
2022-08-16 23:04:52 -06:00
|
|
|
if breakLine { output += "\n" }
|
2022-08-15 12:04:57 -06:00
|
|
|
|
|
|
|
case ArgumentKindString:
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"\"" + argument.value.(string) + "\"")
|
2022-08-16 23:04:52 -06:00
|
|
|
if breakLine { output += "\n" }
|
2022-08-15 12:04:57 -06:00
|
|
|
|
|
|
|
case ArgumentKindRune:
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"'" + string(argument.value.(rune)) + "'")
|
2022-08-16 23:04:52 -06:00
|
|
|
if breakLine { output += "\n" }
|
2022-08-15 12:04:57 -06:00
|
|
|
|
|
|
|
case ArgumentKindOperator:
|
|
|
|
// TODO
|
2022-08-16 18:53:27 -06:00
|
|
|
// also when parsing this argument kind, don't do it in the
|
|
|
|
// argument parsing function. do it specifically when parsing a
|
|
|
|
// phrase command.
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
2022-08-16 14:37:20 -06:00
|
|
|
|
2022-08-15 12:04:57 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (section *DataSection) ToString (indent int) (output string) {
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"data ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
|
|
|
section.what.ToString())
|
2022-08-15 12:23:53 -06:00
|
|
|
|
2022-08-16 22:49:49 -06:00
|
|
|
isComplexInitialization :=
|
|
|
|
section.value.kind == ArgumentKindObjectInitializationValues ||
|
|
|
|
section.value.kind == ArgumentKindArrayInitializationValues
|
|
|
|
|
|
|
|
if section.value.value == nil {
|
2022-08-16 14:37:20 -06:00
|
|
|
output += "\n"
|
2022-08-16 22:49:49 -06:00
|
|
|
} else if isComplexInitialization {
|
2022-08-16 14:37:20 -06:00
|
|
|
output += "\n"
|
2022-08-16 22:49:49 -06:00
|
|
|
output += section.value.ToString(indent + 1, true)
|
2022-08-16 14:37:20 -06:00
|
|
|
} else {
|
2022-08-16 22:49:49 -06:00
|
|
|
output += " " + section.value.ToString(0, false)
|
2022-08-16 14:37:20 -06:00
|
|
|
output += "\n"
|
|
|
|
}
|
2022-08-15 12:04:57 -06:00
|
|
|
return
|
|
|
|
}
|
2022-08-18 15:45:34 -06:00
|
|
|
|
|
|
|
func (section *TypeSection) ToString (indent int) (output string) {
|
2022-08-20 10:40:44 -06:00
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"type ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
|
|
|
section.inherits.ToString())
|
|
|
|
|
|
|
|
isComplexInitialization :=
|
|
|
|
section.defaultValue.kind == ArgumentKindObjectInitializationValues ||
|
|
|
|
section.defaultValue.kind == ArgumentKindArrayInitializationValues
|
|
|
|
|
|
|
|
if section.defaultValue.value == nil {
|
|
|
|
output += "\n"
|
|
|
|
} else if isComplexInitialization {
|
|
|
|
output += "\n"
|
|
|
|
output += section.defaultValue.ToString(indent + 1, true)
|
|
|
|
} else {
|
|
|
|
output += " " + section.defaultValue.ToString(0, false)
|
|
|
|
output += "\n"
|
|
|
|
}
|
2022-08-18 21:38:32 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-08-20 11:42:09 -06:00
|
|
|
func (member ObjtMember) ToString (indent int) (output string) {
|
2022-08-19 01:03:36 -06:00
|
|
|
output += doIndent(indent)
|
2022-08-18 15:45:34 -06:00
|
|
|
|
2022-08-20 10:40:44 -06:00
|
|
|
output += member.permission.ToString() + " "
|
|
|
|
output += member.name + ":"
|
|
|
|
output += member.what.ToString()
|
2022-08-24 16:22:47 -06:00
|
|
|
|
|
|
|
if member.bitWidth > 0 {
|
2022-08-24 16:37:44 -06:00
|
|
|
output += fmt.Sprint(" & ", member.bitWidth)
|
2022-08-24 16:22:47 -06:00
|
|
|
}
|
2022-08-18 21:38:32 -06:00
|
|
|
|
2022-08-19 00:36:56 -06:00
|
|
|
isComplexInitialization :=
|
2022-08-20 10:40:44 -06:00
|
|
|
member.defaultValue.kind == ArgumentKindObjectInitializationValues ||
|
|
|
|
member.defaultValue.kind == ArgumentKindArrayInitializationValues
|
2022-08-19 00:36:56 -06:00
|
|
|
|
2022-08-20 10:40:44 -06:00
|
|
|
if member.defaultValue.value == nil {
|
2022-08-19 01:03:36 -06:00
|
|
|
output += "\n"
|
2022-08-19 00:36:56 -06:00
|
|
|
} else if isComplexInitialization {
|
|
|
|
output += "\n"
|
2022-08-20 10:40:44 -06:00
|
|
|
output += member.defaultValue.ToString(indent + 1, true)
|
2022-08-18 15:45:34 -06:00
|
|
|
} else {
|
2022-08-20 10:40:44 -06:00
|
|
|
output += " " + member.defaultValue.ToString(0, false)
|
|
|
|
output += "\n"
|
2022-08-18 15:45:34 -06:00
|
|
|
}
|
2022-08-18 21:38:32 -06:00
|
|
|
|
2022-08-18 15:45:34 -06:00
|
|
|
return
|
|
|
|
}
|
2022-08-20 10:40:44 -06:00
|
|
|
|
|
|
|
func (section *ObjtSection) ToString (indent int) (output string) {
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"objt ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
|
|
|
section.inherits.ToString(), "\n")
|
|
|
|
|
2022-08-24 18:09:57 -06:00
|
|
|
for _, member := range section.members {
|
|
|
|
output += member.ToString(indent + 1)
|
2022-08-20 10:40:44 -06:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-08-21 00:40:04 -06:00
|
|
|
func (section *EnumSection) ToString (indent int) (output string) {
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"enum ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
|
|
|
section.what.ToString(), "\n")
|
|
|
|
|
2022-08-23 23:16:44 -06:00
|
|
|
for _, member := range section.members {
|
|
|
|
output += doIndent(indent + 1, member.name)
|
2022-08-21 00:40:04 -06:00
|
|
|
|
|
|
|
isComplexInitialization :=
|
2022-08-23 23:16:44 -06:00
|
|
|
member.value.kind == ArgumentKindObjectInitializationValues ||
|
|
|
|
member.value.kind == ArgumentKindArrayInitializationValues
|
2022-08-21 00:40:04 -06:00
|
|
|
|
2022-08-23 23:16:44 -06:00
|
|
|
if member.value.value == nil {
|
2022-08-21 00:40:04 -06:00
|
|
|
output += "\n"
|
|
|
|
} else if isComplexInitialization {
|
|
|
|
output += "\n"
|
2022-08-23 23:16:44 -06:00
|
|
|
output += member.value.ToString(indent + 2, true)
|
2022-08-21 00:40:04 -06:00
|
|
|
} else {
|
2022-08-23 23:16:44 -06:00
|
|
|
output += " " + member.value.ToString(0, false)
|
2022-08-21 00:40:04 -06:00
|
|
|
output += "\n"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2022-08-23 11:54:44 -06:00
|
|
|
|
|
|
|
func (section *FaceSection) ToString (indent int) (output string) {
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"face ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
2022-08-24 16:57:07 -06:00
|
|
|
section.inherits.ToString(), "\n")
|
2022-08-23 11:54:44 -06:00
|
|
|
|
|
|
|
for _, name := range sortMapKeysAlphabetically(section.behaviors) {
|
|
|
|
behavior := section.behaviors[name]
|
|
|
|
output += behavior.ToString(indent + 1)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (behavior *FaceBehavior) ToString (indent int) (output string) {
|
|
|
|
output += doIndent(indent, behavior.name, "\n")
|
|
|
|
|
|
|
|
for _, inputItem := range behavior.inputs {
|
2022-08-23 22:53:42 -06:00
|
|
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
2022-08-23 11:54:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, outputItem := range behavior.outputs {
|
2022-08-23 22:53:42 -06:00
|
|
|
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
2022-08-23 11:54:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2022-09-02 00:36:14 -06:00
|
|
|
|
2022-09-02 21:38:30 -06:00
|
|
|
func (block Block) ToString (indent int) (output string) {
|
|
|
|
for _, phrase := range block {
|
|
|
|
output += phrase.ToString(indent, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-02 00:36:14 -06:00
|
|
|
func (section *FuncSection) ToString (indent int) (output string) {
|
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"func ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, "\n")
|
|
|
|
|
|
|
|
if section.receiver != nil {
|
|
|
|
output += doIndent (
|
|
|
|
indent + 1,
|
|
|
|
"@ ", section.receiver.ToString(), "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, inputItem := range section.inputs {
|
|
|
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, outputItem := range section.outputs {
|
|
|
|
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
output += doIndent(indent + 1, "---\n")
|
|
|
|
|
|
|
|
if section.external {
|
|
|
|
output += doIndent(indent + 1, "external\n")
|
|
|
|
}
|
|
|
|
|
2022-09-02 21:38:30 -06:00
|
|
|
output += section.root.ToString(indent + 1)
|
2022-09-02 00:36:14 -06:00
|
|
|
return
|
|
|
|
}
|