From d91423863bdba4238b7140a6ea9b002e82d3d3f7 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 15 Aug 2022 14:04:57 -0400 Subject: [PATCH] Added ToString methods for syntax tree nodes --- parser/data.go | 2 +- parser/parser_test.go | 84 ++++++++++++++++- parser/tree-tostring.go | 179 +++++++++++++++++++++++++++++++++++++ parser/tree.go | 12 +-- tests/parser/data/main.arf | 15 ++-- types/permission.go | 16 ++++ 6 files changed, 293 insertions(+), 15 deletions(-) create mode 100644 parser/tree-tostring.go diff --git a/parser/data.go b/parser/data.go index 9f72e54..17f001d 100644 --- a/parser/data.go +++ b/parser/data.go @@ -2,5 +2,5 @@ package parser // parseData parses a data section func (parser *ParsingOperation) parseData () (err error) { - + return } diff --git a/parser/parser_test.go b/parser/parser_test.go index f4a7181..3824045 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -2,6 +2,7 @@ package parser import "reflect" import "testing" +import "git.tebibyte.media/sashakoshka/arf/types" func checkTree (modulePath string, correct *SyntaxTree, test *testing.T) { tree, err := Parse(modulePath) @@ -20,8 +21,23 @@ func checkTree (modulePath string, correct *SyntaxTree, test *testing.T) { } } +// quickIdentifier returns a simple identifier of names +func quickIdentifier (trail ...string) (identifier Identifier) { + for _, item := range trail { + identifier.trail = append ( + identifier.trail, + Argument { + what: ArgumentKindString, + value: item, + }, + ) + } + + return +} + func TestMeta (test *testing.T) { - checkTree("../tests/parser/meta",&SyntaxTree { + checkTree ("../tests/parser/meta", &SyntaxTree { license: "GPLv3", author: "Sasha Koshka", @@ -31,3 +47,69 @@ func TestMeta (test *testing.T) { }, }, test) } + +func TestData (test *testing.T) { + tree := &SyntaxTree { + dataSections: []DataSection { + DataSection { + name: "integer", + permission: types.PermissionFrom("wr"), + + what: Type { + kind: TypeKindBasic, + name: quickIdentifier("Int"), + }, + value: []Argument { + Argument { + what: ArgumentKindUInt, + value: 3202, + }, + }, + }, + + DataSection { + name: "integerPointer", + permission: types.PermissionFrom("wr"), + + what: Type { + kind: TypeKindPointer, + points: &Type { + kind: TypeKindBasic, + name: quickIdentifier("Int"), + }, + }, + value: []Argument { + Argument { + what: ArgumentKindUInt, + value: 3202, + }, + }, + }, + + DataSection { + name: "integerArray16", + permission: types.PermissionFrom("wr"), + + what: Type { + kind: TypeKindArray, + points: &Type { + kind: TypeKindBasic, + name: quickIdentifier("Int"), + }, + length: Argument { + what: ArgumentKindUInt, + value: 16, + } + }, + value: []Argument { + Argument { + what: ArgumentKindUInt, + value: 3202, + }, + }, + }, + }, + } + + checkTree ("../tests/parser/data", tree, test) +} diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go new file mode 100644 index 0000000..acfeaa9 --- /dev/null +++ b/parser/tree-tostring.go @@ -0,0 +1,179 @@ +package parser + +import "fmt" + +func doIndent (indent int, input ...string) (output string) { + for index := 0; index < indent; index ++ { + output += "\t" + } + for _, inputSection := range input { + output += inputSection + } + return +} + +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") + + for _, require := range tree.dataSections { + output += require.ToString(1) + } + return +} + +func (identifier *Identifier) ToString () (output string) { + for index, trailItem := range identifier.trail { + if index > 0 { + output += "." + } + + output += trailItem.ToString(0, false) + } + return +} + +func (what *Type) ToString () (output string) { + if what.kind == TypeKindBasic { + output += what.name.ToString() + } else { + output += "{" + output += what.points.ToString() + output += "}" + } + + if what.mutable { + output += ":mut" + } + + return +} + +func (declaration *Declaration) ToString () (output string) { + output += declaration.name + ":" + output += declaration.what.ToString() + return +} + +func (attribute *ObjectAttribute) ToString ( + indent int, + breakLine bool, +) ( + output string, +) { + if breakLine { + output += doIndent(indent) + } + + output += ", " + attribute.name + if breakLine { + output += "\n" + attribute.value.ToString(indent + 1, true) + } else { + output += " " + attribute.value.ToString(0, false) + } + + return +} + +func (phrase *Phrase) ToString (indent int, breakLine bool) (output string) { + if breakLine { + output += doIndent ( + indent, + "[", phrase.command.ToString(0, false)) + output += "\n" + for _, argument := range phrase.arguments { + output += doIndent ( + indent, + argument.ToString(indent + 1, true)) + } + } else { + output += "[" + phrase.command.ToString(0, false) + for _, argument := range phrase.arguments { + output += " " + argument.ToString(0, false) + } + } + + output += "]" + + if len(phrase.returnsTo) > 0 { + output += " ->" + for _, returnItem := range phrase.returnsTo { + output += " " + returnItem.ToString(0, false) + } + } + + if breakLine { + output += "\n" + } + return +} + +func (argument *Argument) ToString (indent int, breakLine bool) (output string) { + if !breakLine { indent = 0 } + + switch argument.what { + case ArgumentKindPhrase: + output += doIndent ( + indent, + argument.value.(*Phrase).ToString ( + indent, + breakLine)) + + case ArgumentKindObjectAttribute: + output += doIndent ( + indent, + argument.value.(*ObjectAttribute).ToString ( + indent, + breakLine)) + + case ArgumentKindIdentifier: + output += doIndent ( + indent, + argument.value.(*Identifier).ToString()) + + case ArgumentKindDeclaration: + output += doIndent ( + indent, + argument.value.(*Declaration).ToString()) + + case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat: + output += doIndent(indent, fmt.Sprint(argument.value)) + + case ArgumentKindString: + output += doIndent ( + indent, + "\"" + argument.value.(string) + "\"") + + case ArgumentKindRune: + output += doIndent ( + indent, + "'" + string(argument.value.(rune)) + "'") + + case ArgumentKindOperator: + // TODO + } + return +} + +func (section *DataSection) ToString (indent int) (output string) { + output += doIndent ( + indent, + "data ", + section.permission.ToString(), " ", + section.name, ":", + section.what.ToString()) + return +} diff --git a/parser/tree.go b/parser/tree.go index d93bf11..f4c095d 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -10,7 +10,8 @@ type SyntaxTree struct { license string author string - requires []string + requires []string + dataSections []DataSection } // Identifier represents a chain of arguments separated by a dot. @@ -41,14 +42,14 @@ type Type struct { mutable bool kind TypeKind - // only applicable for arrays. a value of zero means it has an + // only applicable for arrays. a value of nil means it has an // undefined/dynamic length. - length uint64 + length *Argument - // not applicable for pointers. + // only applicable for basic. name Identifier - // only applicable for pointers. + // not applicable for basic. points *Type } @@ -119,6 +120,7 @@ const ( ArgumentKindRune // + - * / etc... + // this is only used as a phrase command ArgumentKindOperator ) diff --git a/tests/parser/data/main.arf b/tests/parser/data/main.arf index f781595..b7cedc3 100644 --- a/tests/parser/data/main.arf +++ b/tests/parser/data/main.arf @@ -27,11 +27,10 @@ data wr nestedObject:Obj , bird3 9328.21348239 -# parsing an object literal -func rr main - --- - [let object:Obj - , this 324 - , that 2139] - - let object:Obj , this 324 , that 2139 +# func rr main + # --- + # [let object:Obj + # , this 324 + # , that 2139] + # + # let object:Obj , this 324 , that 2139 diff --git a/types/permission.go b/types/permission.go index 4421058..cd24150 100644 --- a/types/permission.go +++ b/types/permission.go @@ -30,3 +30,19 @@ func PermissionFrom (data string) (permission Permission) { permission.External = ModeFrom(rune(data[1])) return } + +func (mode Mode) ToString () (output string) { + switch mode { + case ModeNone: output = "n" + case ModeRead: output = "r" + case ModeWrite: output = "w" + } + + return +} + +func (permission Permission) ToString () (output string) { + output += permission.Internal.ToString() + output += permission.External.ToString() + return +}