2022-08-15 12:04:57 -06:00
|
|
|
package parser
|
|
|
|
|
|
|
|
import "fmt"
|
2022-08-17 11:50:33 -06:00
|
|
|
import "sort"
|
2022-09-03 09:43:02 -06:00
|
|
|
import "git.tebibyte.media/arf/arf/lexer"
|
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-09-04 17:55:47 -06:00
|
|
|
func (tree SyntaxTree) ToString (indent int) (output string) {
|
2022-08-15 12:04:57 -06:00
|
|
|
output += doIndent(indent, ":arf\n")
|
|
|
|
|
|
|
|
if tree.author != "" {
|
2022-10-04 15:13:08 -06:00
|
|
|
output += doIndent(indent, "author '", tree.author, "'\n")
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if tree.license != "" {
|
2022-10-04 15:13:08 -06:00
|
|
|
output += doIndent(indent, "license '", tree.license, "'\n")
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
|
|
|
|
2022-09-29 09:06:45 -06:00
|
|
|
for _, name := range sortMapKeysAlphabetically(tree.requires) {
|
|
|
|
require := tree.requires[name]
|
2022-10-04 15:13:08 -06:00
|
|
|
output += doIndent(indent, "require '", require, "'\n")
|
2022-08-15 12:04:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
output += doIndent(indent, "---\n")
|
|
|
|
|
2022-09-04 17:30:59 -06:00
|
|
|
sectionKeys := sortMapKeysAlphabetically(tree.sections)
|
|
|
|
for _, name := range sectionKeys {
|
|
|
|
output += tree.sections[name].ToString(indent)
|
2022-08-18 15:45:34 -06:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-09-27 14:13:02 -06:00
|
|
|
func (what Type) ToString () (output string) {
|
2022-09-29 00:03:19 -06:00
|
|
|
if what.kind == TypeKindNil {
|
|
|
|
output += "NIL-TYPE"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-08-15 12:04:57 -06:00
|
|
|
if what.kind == TypeKindBasic {
|
|
|
|
output += what.name.ToString()
|
|
|
|
} else {
|
|
|
|
output += "{"
|
2022-09-27 14:13:02 -06:00
|
|
|
output += what.points.ToString()
|
2022-08-16 18:53:27 -06:00
|
|
|
|
2022-09-05 09:13:16 -06:00
|
|
|
if what.kind == TypeKindVariableArray {
|
2022-09-04 20:27:06 -06:00
|
|
|
output += " .."
|
2022-08-16 18:53:27 -06:00
|
|
|
}
|
|
|
|
|
2022-08-15 12:04:57 -06:00
|
|
|
output += "}"
|
|
|
|
}
|
|
|
|
|
2022-09-05 09:20:23 -06:00
|
|
|
if what.length > 1 {
|
2022-09-05 09:13:16 -06:00
|
|
|
output += fmt.Sprint(":", what.length)
|
|
|
|
}
|
|
|
|
|
2022-08-15 12:04:57 -06:00
|
|
|
if what.mutable {
|
|
|
|
output += ":mut"
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-29 00:37:14 -06:00
|
|
|
func (declaration Declaration) ToString () (output string) {
|
2022-08-15 12:04:57 -06:00
|
|
|
output += declaration.name + ":"
|
2022-09-27 14:13:02 -06:00
|
|
|
output += declaration.what.ToString()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (list List) ToString (indent int, breakline bool) (output string) {
|
|
|
|
if !breakline { indent = 0 }
|
|
|
|
output += doIndent(indent, "(")
|
|
|
|
if breakline { output += "\n" }
|
|
|
|
|
2022-09-27 16:18:38 -06:00
|
|
|
for index, argument := range list.arguments {
|
|
|
|
if !breakline && index > 0 { output += " "}
|
2022-09-27 14:13:02 -06:00
|
|
|
output += argument.ToString(indent, breakline)
|
|
|
|
}
|
|
|
|
|
2022-09-27 16:18:38 -06:00
|
|
|
output += doIndent(indent, ")")
|
2022-09-27 14:13:02 -06:00
|
|
|
if breakline { output += "\n" }
|
2022-08-15 12:04:57 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-04 17:55:47 -06:00
|
|
|
func (argument Argument) ToString (indent int, breakLine bool) (output string) {
|
2022-08-15 12:04:57 -06:00
|
|
|
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-09-27 14:13:02 -06:00
|
|
|
case ArgumentKindList:
|
|
|
|
output += argument.value.(List).ToString(indent, breakLine)
|
2022-10-11 09:23:50 -06:00
|
|
|
|
|
|
|
case ArgumentKindDereference:
|
|
|
|
output += argument.value.(Dereference).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-29 00:37:14 -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,
|
2022-10-04 15:07:31 -06:00
|
|
|
"'" + argument.value.(string) + "'")
|
2022-08-16 23:04:52 -06:00
|
|
|
if breakLine { output += "\n" }
|
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
|
|
|
|
}
|
|
|
|
|
2022-09-04 17:55:47 -06:00
|
|
|
func (section DataSection) ToString (indent int) (output string) {
|
2022-08-15 12:04:57 -06:00
|
|
|
output += doIndent (
|
|
|
|
indent,
|
2022-09-16 10:16:23 -06:00
|
|
|
"data ",
|
2022-08-15 12:04:57 -06:00
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
2022-09-27 14:13:02 -06:00
|
|
|
section.what.ToString(), "\n")
|
2022-09-27 16:43:40 -06:00
|
|
|
|
|
|
|
if section.argument.kind != ArgumentKindNil {
|
|
|
|
output += section.argument.ToString(indent + 1, true)
|
|
|
|
}
|
2022-09-16 20:37:43 -06:00
|
|
|
|
|
|
|
if section.external {
|
|
|
|
output += doIndent(indent + 1, "external\n")
|
|
|
|
}
|
|
|
|
|
2022-08-18 15:45:34 -06:00
|
|
|
return
|
|
|
|
}
|
2022-08-20 10:40:44 -06:00
|
|
|
|
2022-09-29 00:10:58 -06:00
|
|
|
func (member TypeSectionMember) ToString (indent int) (output string) {
|
|
|
|
output += doIndent(indent, member.permission.ToString())
|
2022-09-29 00:13:22 -06:00
|
|
|
output += " " + member.name
|
2022-09-29 00:10:58 -06:00
|
|
|
|
|
|
|
if member.what.kind != TypeKindNil {
|
2022-09-29 00:13:22 -06:00
|
|
|
output += ":" + member.what.ToString()
|
2022-09-29 00:10:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if member.argument.kind != ArgumentKindNil {
|
|
|
|
output += " " + member.argument.ToString(indent, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
if member.bitWidth > 0 {
|
|
|
|
output += fmt.Sprint(" & ", member.bitWidth)
|
|
|
|
}
|
|
|
|
|
|
|
|
output += "\n"
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:27:29 -06:00
|
|
|
func (section TypeSection) ToString (indent int) (output string) {
|
2022-08-20 10:40:44 -06:00
|
|
|
output += doIndent (
|
|
|
|
indent,
|
2022-09-12 13:27:29 -06:00
|
|
|
"type ",
|
2022-08-20 10:40:44 -06:00
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
2022-09-27 14:13:02 -06:00
|
|
|
section.what.ToString(), "\n")
|
2022-09-27 16:43:40 -06:00
|
|
|
|
|
|
|
if section.argument.kind != ArgumentKindNil {
|
|
|
|
output += section.argument.ToString(indent + 1, true)
|
|
|
|
}
|
2022-09-29 00:10:58 -06:00
|
|
|
|
|
|
|
for _, member := range section.members {
|
|
|
|
output += member.ToString(indent + 1)
|
|
|
|
}
|
2022-08-20 10:40:44 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-04 17:55:47 -06:00
|
|
|
func (section EnumSection) ToString (indent int) (output string) {
|
2022-08-21 00:40:04 -06:00
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"enum ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, ":",
|
2022-09-27 14:13:02 -06:00
|
|
|
section.what.ToString(), "\n")
|
2022-08-21 00:40:04 -06:00
|
|
|
|
2022-08-23 23:16:44 -06:00
|
|
|
for _, member := range section.members {
|
2022-09-27 15:36:39 -06:00
|
|
|
output += doIndent(indent + 1, "- ", member.name)
|
|
|
|
if member.argument.kind != ArgumentKindNil {
|
|
|
|
output += " " + member.argument.ToString(indent, false)
|
|
|
|
}
|
2022-09-16 22:58:08 -06:00
|
|
|
output += "\n"
|
2022-08-21 00:40:04 -06:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2022-08-23 11:54:44 -06:00
|
|
|
|
2022-09-04 17:55:47 -06:00
|
|
|
func (section FaceSection) ToString (indent int) (output string) {
|
2022-08-23 11:54:44 -06:00
|
|
|
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
|
|
|
|
2022-09-29 13:52:14 -06:00
|
|
|
if section.kind == FaceKindType {
|
|
|
|
for _, name := range sortMapKeysAlphabetically(section.behaviors) {
|
|
|
|
behavior := section.behaviors[name]
|
|
|
|
output += behavior.ToString(indent + 1)
|
|
|
|
}
|
|
|
|
} else if section.kind == FaceKindFunc {
|
|
|
|
for _, inputItem := range section.inputs {
|
|
|
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, outputItem := range section.outputs {
|
|
|
|
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
|
|
|
}
|
2022-08-23 11:54:44 -06:00
|
|
|
}
|
2022-09-29 13:52:14 -06:00
|
|
|
|
2022-08-23 11:54:44 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-04 17:55:47 -06:00
|
|
|
func (behavior FaceBehavior) ToString (indent int) (output string) {
|
2022-08-23 11:54:44 -06:00
|
|
|
output += doIndent(indent, behavior.name, "\n")
|
|
|
|
|
|
|
|
for _, inputItem := range behavior.inputs {
|
2022-09-29 00:37:14 -06:00
|
|
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
2022-08-23 11:54:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, outputItem := range behavior.outputs {
|
2022-09-29 00:37:14 -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-10-11 09:23:50 -06:00
|
|
|
func (dereference Dereference) ToString (indent int) (output string) {
|
|
|
|
output += "{"
|
|
|
|
output += dereference.argument.ToString(indent, false)
|
|
|
|
if dereference.offset != 0 {
|
|
|
|
output += fmt.Sprint(" ", dereference.offset)
|
|
|
|
}
|
|
|
|
output += "}"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-03 13:22:18 -06:00
|
|
|
func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
|
|
|
|
if ownLine {
|
|
|
|
output += doIndent(indent)
|
|
|
|
}
|
2022-09-03 17:24:09 -06:00
|
|
|
|
2022-09-27 14:13:02 -06:00
|
|
|
output += "["
|
|
|
|
|
|
|
|
switch phrase.kind {
|
2022-09-29 00:43:24 -06:00
|
|
|
case PhraseKindCase:
|
|
|
|
output += ":"
|
|
|
|
|
|
|
|
case PhraseKindAssign:
|
|
|
|
output += "="
|
|
|
|
|
|
|
|
case PhraseKindOperator:
|
2022-09-27 14:13:02 -06:00
|
|
|
|
|
|
|
switch phrase.operator {
|
|
|
|
case lexer.TokenKindColon:
|
|
|
|
output += ":"
|
|
|
|
case lexer.TokenKindPlus:
|
|
|
|
output += "+"
|
|
|
|
case lexer.TokenKindMinus:
|
|
|
|
output += "-"
|
|
|
|
case lexer.TokenKindIncrement:
|
|
|
|
output += "++"
|
|
|
|
case lexer.TokenKindDecrement:
|
|
|
|
output += "--"
|
|
|
|
case lexer.TokenKindAsterisk:
|
|
|
|
output += "*"
|
|
|
|
case lexer.TokenKindSlash:
|
|
|
|
output += "/"
|
|
|
|
case lexer.TokenKindExclamation:
|
|
|
|
output += "!"
|
|
|
|
case lexer.TokenKindPercent:
|
|
|
|
output += "%"
|
|
|
|
case lexer.TokenKindPercentAssignment:
|
|
|
|
output += "%="
|
|
|
|
case lexer.TokenKindTilde:
|
|
|
|
output += "~"
|
|
|
|
case lexer.TokenKindTildeAssignment:
|
|
|
|
output += "~="
|
|
|
|
case lexer.TokenKindAssignment:
|
|
|
|
output += "="
|
|
|
|
case lexer.TokenKindEqualTo:
|
|
|
|
output += "=="
|
|
|
|
case lexer.TokenKindNotEqualTo:
|
|
|
|
output += "!="
|
|
|
|
case lexer.TokenKindLessThanEqualTo:
|
|
|
|
output += "<="
|
|
|
|
case lexer.TokenKindLessThan:
|
|
|
|
output += "<"
|
|
|
|
case lexer.TokenKindLShift:
|
|
|
|
output += "<<"
|
|
|
|
case lexer.TokenKindLShiftAssignment:
|
|
|
|
output += "<<="
|
|
|
|
case lexer.TokenKindGreaterThan:
|
|
|
|
output += ">"
|
|
|
|
case lexer.TokenKindGreaterThanEqualTo:
|
|
|
|
output += ">="
|
|
|
|
case lexer.TokenKindRShift:
|
|
|
|
output += ">>"
|
|
|
|
case lexer.TokenKindRShiftAssignment:
|
|
|
|
output += ">>="
|
|
|
|
case lexer.TokenKindBinaryOr:
|
|
|
|
output += "|"
|
|
|
|
case lexer.TokenKindBinaryOrAssignment:
|
|
|
|
output += "|="
|
|
|
|
case lexer.TokenKindLogicalOr:
|
|
|
|
output += "||"
|
|
|
|
case lexer.TokenKindBinaryAnd:
|
|
|
|
output += "&"
|
|
|
|
case lexer.TokenKindBinaryAndAssignment:
|
|
|
|
output += "&="
|
|
|
|
case lexer.TokenKindLogicalAnd:
|
|
|
|
output += "&&"
|
|
|
|
case lexer.TokenKindBinaryXor:
|
|
|
|
output += "^"
|
|
|
|
case lexer.TokenKindBinaryXorAssignment:
|
|
|
|
output += "^="
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
output += phrase.command.ToString(0, false)
|
|
|
|
}
|
|
|
|
|
2022-09-03 13:22:18 -06:00
|
|
|
for _, argument := range phrase.arguments {
|
2022-09-16 20:35:55 -06:00
|
|
|
output += " " + argument.ToString(0, false)
|
2022-09-03 13:22:18 -06:00
|
|
|
}
|
|
|
|
output += "]"
|
|
|
|
|
2022-09-05 09:49:19 -06:00
|
|
|
if len(phrase.returnees) > 0 {
|
2022-09-03 13:22:18 -06:00
|
|
|
output += " ->"
|
2022-09-05 09:49:19 -06:00
|
|
|
for _, returnItem := range phrase.returnees {
|
2022-09-03 13:22:18 -06:00
|
|
|
output += " " + returnItem.ToString(0, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ownLine {
|
|
|
|
output += "\n"
|
|
|
|
output += phrase.block.ToString(indent + 1)
|
2022-09-16 20:35:55 -06:00
|
|
|
} else if len(phrase.block) > 0 {
|
2022-09-16 20:54:26 -06:00
|
|
|
output += "NON-BLOCK-LEVEL-PHRASE-HAS-BLOCK"
|
2022-09-03 13:22:18 -06:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-09-29 00:37:14 -06:00
|
|
|
func (funcOutput FuncOutput) ToString (indent int) (output string) {
|
|
|
|
output += doIndent(indent + 1)
|
|
|
|
output += "< " + funcOutput.Declaration.ToString()
|
|
|
|
if funcOutput.argument.kind != ArgumentKindNil {
|
|
|
|
output += " " + funcOutput.argument.ToString(indent, false)
|
|
|
|
}
|
|
|
|
output += "\n"
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
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-04 17:55:47 -06:00
|
|
|
func (section FuncSection) ToString (indent int) (output string) {
|
2022-09-02 00:36:14 -06:00
|
|
|
output += doIndent (
|
|
|
|
indent,
|
|
|
|
"func ",
|
|
|
|
section.permission.ToString(), " ",
|
|
|
|
section.name, "\n")
|
|
|
|
|
|
|
|
if section.receiver != nil {
|
|
|
|
output += doIndent (
|
|
|
|
indent + 1,
|
2022-09-29 00:37:14 -06:00
|
|
|
"@ ", section.receiver.ToString(), "\n")
|
2022-09-02 00:36:14 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, inputItem := range section.inputs {
|
2022-09-29 00:37:14 -06:00
|
|
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
2022-09-02 00:36:14 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, outputItem := range section.outputs {
|
2022-09-29 00:37:14 -06:00
|
|
|
output += outputItem.ToString(indent)
|
2022-09-02 00:36:14 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|