From edd4b396424ddcf27c6d414e89baa6c22dc93ec1 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 26 Sep 2022 18:28:21 -0400 Subject: [PATCH 01/34] Parser tree changes --- analyzer/argument.go | 18 +++++++++++++++++- parser/node-traits.go | 14 ++++++++++---- parser/tree.go | 25 ++++++++----------------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/analyzer/argument.go b/analyzer/argument.go index b9f5707..5537f03 100644 --- a/analyzer/argument.go +++ b/analyzer/argument.go @@ -29,33 +29,49 @@ func (analyzer AnalysisOperation) analyzeArgument ( ) { switch inputArgument.Kind() { case parser.ArgumentKindNil: + panic ( + "invalid state: attempt to analyze nil argument") case parser.ArgumentKindPhrase: + // TODO case parser.ArgumentKindDereference: + // TODO case parser.ArgumentKindSubscript: + // TODO case parser.ArgumentKindObjectDefaultValues: + // TODO case parser.ArgumentKindArrayDefaultValues: + // TODO case parser.ArgumentKindIdentifier: + // TODO case parser.ArgumentKindDeclaration: + // TODO case parser.ArgumentKindInt: + outputArgument = IntLiteral(inputArgument.Value().(int64)) case parser.ArgumentKindUInt: + outputArgument = UIntLiteral(inputArgument.Value().(uint64)) case parser.ArgumentKindFloat: + outputArgument = FloatLiteral(inputArgument.Value().(float64)) case parser.ArgumentKindString: + outputArgument = StringLiteral(inputArgument.Value().(string)) case parser.ArgumentKindRune: + outputArgument = RuneLiteral(inputArgument.Value().(rune)) case parser.ArgumentKindOperator: - + panic ( + "invalid state: attempt to analyze operator argument " + + "directly") } return } diff --git a/parser/node-traits.go b/parser/node-traits.go index e16aeaf..2ec0da6 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -60,11 +60,17 @@ func (trait permissionable) Permission () (permission types.Permission) { // valuable allows a node to have an argument value. type valuable struct { - value Argument + values []Argument } -// Value returns the value argument of the node. -func (trait valuable) Value () (value Argument) { - value = trait.value +// Length returns the amount of default values in the node. +func (node valuable) Length () (length int) { + length = len(node.values) + return +} + +// Value returns the default value at the specified index. +func (node valuable) Value (index int) (value Argument) { + value = node.values[index] return } diff --git a/parser/tree.go b/parser/tree.go index 54a62e0..bb9147b 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -52,6 +52,7 @@ type TypeMember struct { nameable typeable permissionable + valuable bitWidth uint64 } @@ -72,9 +73,6 @@ type Type struct { // if non-nil, this type defines new members. members []TypeMember - - // the default value of the type. - defaultValue Argument } // Declaration represents a variable declaration. @@ -84,13 +82,6 @@ type Declaration struct { typeable } -// ObjectDefaultValues represents a list of object member initialization -// attributes. -type ObjectDefaultValues map[string] Argument - -// ArrayDefaultValues represents a list of elements initializing an array. -type ArrayDefaultValues []Argument - // ArgumentKind specifies the type of thing the value of an argument should be // cast to. type ArgumentKind int @@ -109,13 +100,6 @@ const ( // {name 23} ArgumentKindSubscript - // (.name ) - // (.name .name (.name - ArgumentKindArrayDefaultValues - // name.name // name.name.name // etc... @@ -249,6 +233,13 @@ type Phrase struct { // Block represents a scoped/indented block of code. type Block []Phrase +// FuncOutput represents a function output declaration. It allows for a default +// value. +type FuncOutput struct { + Declaration + valuable +} + // FuncSection represents a function section. type FuncSection struct { locatable From c4101dcd330dab1c79e7ee37ff82d5912e5ca173 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 14:17:03 -0400 Subject: [PATCH 02/34] More tree changes --- parser/accessors.go | 12 ------------ parser/node-traits.go | 31 +++++++++++++++++++++---------- parser/tree.go | 11 ++++++++++- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/parser/accessors.go b/parser/accessors.go index 1801312..fcb7957 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -169,18 +169,6 @@ func (phrase Phrase) Kind () (kind PhraseKind) { return } -// ArgumentsLength returns the amount of arguments in the phrase. -func (phrase Phrase) ArgumentsLength () (length int) { - length = len(phrase.arguments) - return -} - -// Argument returns the argument at index. -func (phrase Phrase) Argument (index int) (argument Argument) { - argument = phrase.arguments[index] - return -} - // ReturneesLength returns the amount of things the phrase returns to. func (phrase Phrase) ReturneesLength () (length int) { length = len(phrase.returnees) diff --git a/parser/node-traits.go b/parser/node-traits.go index 2ec0da6..6feeb0d 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -43,7 +43,7 @@ type typeable struct { // Type returns the type of the node. func (trait typeable) Type () (what Type) { - what = trait.what + what = trait.what return } @@ -60,17 +60,28 @@ func (trait permissionable) Permission () (permission types.Permission) { // valuable allows a node to have an argument value. type valuable struct { + value Argument +} + +// Value returns the value argument of the node. +func (trait valuable) Value () (value Argument) { + value = trait.value + return +} + +// multiValuable allows a node to have several argument values. +type multiValuable struct { values []Argument } -// Length returns the amount of default values in the node. -func (node valuable) Length () (length int) { - length = len(node.values) - return -} - -// Value returns the default value at the specified index. -func (node valuable) Value (index int) (value Argument) { - value = node.values[index] +// Value returns the value at index. +func (trait multiValuable) Value (index int) (value Argument) { + value = trait.values[index] + return +} + +// Length returns the amount of values in the mode. +func (trait multiValuable) Length () (length int) { + length = len(trait.values) return } diff --git a/parser/tree.go b/parser/tree.go index bb9147b..af89a49 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -82,6 +82,12 @@ type Declaration struct { typeable } +// List represents an array or object literal. +type List struct { + locatable + multiValuable +} + // ArgumentKind specifies the type of thing the value of an argument should be // cast to. type ArgumentKind int @@ -94,6 +100,9 @@ const ( // etc... ArgumentKindPhrase + // (argument argument argument) + ArgumentKindList + // {name} ArgumentKindDereference @@ -221,8 +230,8 @@ const ( type Phrase struct { location file.Location command Argument - arguments []Argument returnees []Argument + multiValuable kind PhraseKind From 873d6c89b1d7783fbe5e21655b92f76924c94ef7 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 14:17:15 -0400 Subject: [PATCH 03/34] Rewrote parser test case input files --- tests/parser/data/main.arf | 37 ++++++++++++------------------- tests/parser/enum/main.arf | 34 ++++++++++++++-------------- tests/parser/face/main.arf | 2 ++ tests/parser/func/main.arf | 17 +++++++------- tests/parser/skim/main.arf | 28 ++++++++++-------------- tests/parser/type/main.arf | 45 +++++++++++++++++++------------------- 6 files changed, 75 insertions(+), 88 deletions(-) diff --git a/tests/parser/data/main.arf b/tests/parser/data/main.arf index 824cacd..bd204ba 100644 --- a/tests/parser/data/main.arf +++ b/tests/parser/data/main.arf @@ -1,9 +1,9 @@ :arf --- -data ro aInteger:Int:<3202> +data ro aInteger:Int: 3202 -data ro bMutInteger:Int:mut:<3202> +data ro bMutInteger:Int:mut: 3202 data ro cIntegerPointer:{Int} @@ -13,33 +13,24 @@ data ro eIntegerArray16:Int:16 data ro fIntegerArrayVariable:{Int ..} -data ro gIntegerArrayInitialized:Int:16:< - 3948 293 293049 948 912 - 340 0 2304 0 4785 92 - > +data ro gIntegerArrayInitialized:Int:16 + (3948 293 293049 948 912 + 340 0 2304 0 4785 92) -data rw hIntegerPointerInit:{Int}:<[& integer]> +data rw hIntegerPointerInit:{Int} [& integer] -data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]> +data rw iMutIntegerPointerInit:{Int}:mut + [& integer] -data ro jObject:Obj:( - .this:<324> - .that:<324>) - -data ro kNestedObject:Obj:( - .this:( - .bird0:<324> - .bird1:<"hello world">) - .ro newMember:Int:<9023> - .that:( - .bird2:<123.8439> - .bird3:<9328.21348239>)) +data ro jObject:Obj + (324 + 438) data ro lMutIntegerArray16:Int:16:mut data ro mExternalData:Int:8 external -data ro nIntegerArrayInitialized:Int:16:mut: - <3948 293 293049 948 912 - 340 0 2304 0 4785 92> +data ro nIntegerArrayInitialized:Int:16:mut + (3948 293 293049 948 912 + 340 0 2304 0 4785 92) diff --git a/tests/parser/enum/main.arf b/tests/parser/enum/main.arf index 9e2aedf..e935f73 100644 --- a/tests/parser/enum/main.arf +++ b/tests/parser/enum/main.arf @@ -11,26 +11,26 @@ enum ro Weekday:Int - saturday enum ro NamedColor:U32 - - red: <0xFF0000> - - green: <0x00FF00> - - blue: <0x0000FF> + - red 0xFF0000 + - green 0x00FF00 + - blue 0x0000FF enum ro AffrontToGod:Int:4 - - bird0: - <28394 9328 - 398 9> - - bird1: - <23 932832 + - bird0 + (28394 9328 + 398 9) + - bird1 + (23 932832 398 - 2349> - - bird2: - <1 + 2349) + - bird2 + (1 2 3 - 4> + 4) -enum ro ThisIsTerrible:Obj:(.rw x:Int .rw y:Int) - - up: (.x:< 0> .y:<-1>) - - down: (.x:< 0> .y:< 1>) - - left: (.x:<-1> .y:< 0>) - - right: (.x:< 1> .y:< 0>) +enum ro ThisIsTerrible:Vector + - up ( 0 -1) + - down ( 0 1) + - left (-1 0) + - right ( 1 0) diff --git a/tests/parser/face/main.arf b/tests/parser/face/main.arf index 4a78a7c..8288cdc 100644 --- a/tests/parser/face/main.arf +++ b/tests/parser/face/main.arf @@ -13,3 +13,5 @@ face ro ReadWriter:Face face ro Destroyer:Face destroy + +# TODO: add test case for func interface diff --git a/tests/parser/func/main.arf b/tests/parser/func/main.arf index adee836..2834cfe 100644 --- a/tests/parser/func/main.arf +++ b/tests/parser/func/main.arf @@ -2,14 +2,14 @@ --- func ro aBasicExternal > someInput:Int:mut - < someOutput:Int:<4> + < someOutput:Int 4 --- external func ro bMethod @ bird:{Bird} > someInput:Int:mut - < someOutput:Int:<4> + < someOutput:Int 4 --- external @@ -126,10 +126,9 @@ func ro hSetPhrase --- let x:Int:<3> # loc is a reference, similar to * in C - let y:{Int}:<[loc x]> - let z:Int:8: - <398 9 2309 983 -2387 - 478 555 123> - let bird:Bird:( - .that:(.whenYou:<99999>) - .this:<324>) + let y:{Int} [loc x] + let z:Int:8 (398 9 2309 983 -2387 + 478 555 123) + let bird:Bird ( + (99999) + 324) diff --git a/tests/parser/skim/main.arf b/tests/parser/skim/main.arf index 762a451..bfeba2d 100644 --- a/tests/parser/skim/main.arf +++ b/tests/parser/skim/main.arf @@ -6,37 +6,31 @@ data ro aExternalData:Int data ro bSingleValue:Int 342 -data ro cNestedObject:Obj - -- this - -- bird0 324 - -- bird1 "hello world" - -- that - -- bird2 123.8439 - -- bird3 9328.21348239 +data ro cNestedObject:Obj ( + (324 "hello world") + (123.8439 9328.21348239) +) data ro dUninitialized:Int:16:mut data ro eIntegerArrayInitialized:Int:16:mut - 3948 293 293049 948 912 - 340 0 2304 0 4785 92 + (3948 293 293049 948 912 + 340 0 2304 0 4785 92) func ro fComplexFunction --- = x:Int 3 = y:{Int} [loc x] - = z:Int:8 + = z:Int:8 ( 398 9 2309 983 -2387 - 478 555 123 - = bird:Bird - -- that - -- whenYou 99999 - -- this 324 + 478 555 123) + = bird:Bird ((99999) 324) func ro gExternalFunction > x:Int < arr:Int 5 - 34908 + (34908 39 3498 - 38 219 + 38 219) --- external diff --git a/tests/parser/type/main.arf b/tests/parser/type/main.arf index 8ffe9df..611adf9 100644 --- a/tests/parser/type/main.arf +++ b/tests/parser/type/main.arf @@ -1,35 +1,36 @@ :arf --- -type ro aBasic:Obj:( - .ro that:Int - .ro this:Int) +type ro aBasic:Obj + ro that:Int + ro this:Int -type ro bBitFields:Obj:( - .ro that:Int & 1 - .ro this:Int:<298> & 24) +type ro bBitFields:Obj + ro that:Int & 1 + ro this:Int 298 & 24 type ro cInit:Obj:( - .ro that:String:<"hello world"> - .ro this:Int:<23>) + ro that:String "hello world" + ro this:Int 23 -type ro dInitInherit:aBasic:( - .that:<9384> - .this:<389>) +# the semantic analyzer should let these sections restrict the permissions of +# inherited members, but it should not let the sections lessen the permissions. +type ro dInitInherit:aBasic + ro that 9384 + ro this 389 -type ro eInitAndDefine:aBasic:( - .this:<389> - .ro these:aBasic:( - .ro born:Int:<4> - .ro in:Int - .ro the:Int:3:<9348 92384 92834> - .this:<98>) - .that:<9384>) +type ro eInitAndDefine:aBasic + ro this 389 + ro that 9384 + ro born:Int 4 + ro in:Int + ro the:Int:3 (9348 92384 92834) + ro walls:String "live in the walls, die in the walls." type ro fBasic:Int -type ro gBasicInit:Int:<6> +type ro gBasicInit:Int 6 type ro hIntArray:{Int ..} -type ro iIntArrayInit:Int:3: - <3298 923 92> +type ro iIntArrayInit:Int:3 + (3298 923 92) From 48325e224bc8e7f15ab27ea18ac535067ffb2c5f Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 14:18:46 -0400 Subject: [PATCH 04/34] Renamed method recievers from trait to node in node-traits --- parser/node-traits.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/parser/node-traits.go b/parser/node-traits.go index 6feeb0d..34fafd7 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -10,19 +10,19 @@ type locatable struct { } // Location returns the location of the node. -func (trait locatable) Location () (location file.Location) { - location = trait.location +func (node locatable) Location () (location file.Location) { + location = node.location return } // NewError creates a new error at the node's location. -func (trait locatable) NewError ( +func (node locatable) NewError ( message string, kind infoerr.ErrorKind, ) ( err error, ) { - err = infoerr.NewError(trait.location, message, kind) + err = infoerr.NewError(node.location, message, kind) return } @@ -32,8 +32,8 @@ type nameable struct { } // Name returns the name of the node. -func (trait nameable) Name () (name string) { - name = trait.name +func (node nameable) Name () (name string) { + name = node.name return } // typeable allows a node to have a type. @@ -42,8 +42,8 @@ type typeable struct { } // Type returns the type of the node. -func (trait typeable) Type () (what Type) { - what = trait.what +func (node typeable) Type () (what Type) { + what = node.what return } @@ -53,8 +53,8 @@ type permissionable struct { } // Permission returns the permision of the node. -func (trait permissionable) Permission () (permission types.Permission) { - permission = trait.permission +func (node permissionable) Permission () (permission types.Permission) { + permission = node.permission return } @@ -64,8 +64,8 @@ type valuable struct { } // Value returns the value argument of the node. -func (trait valuable) Value () (value Argument) { - value = trait.value +func (node valuable) Value () (value Argument) { + value = node.value return } @@ -75,13 +75,13 @@ type multiValuable struct { } // Value returns the value at index. -func (trait multiValuable) Value (index int) (value Argument) { - value = trait.values[index] +func (node multiValuable) Value (index int) (value Argument) { + value = node.values[index] return } // Length returns the amount of values in the mode. -func (trait multiValuable) Length () (length int) { - length = len(trait.values) +func (node multiValuable) Length () (length int) { + length = len(node.values) return } From 1ed612b3d1dfc146d7fc87969b2afc7bbc1ea119 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 14:26:02 -0400 Subject: [PATCH 05/34] Values are now properly referred to as arguments --- parser/node-traits.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/parser/node-traits.go b/parser/node-traits.go index 34fafd7..e245882 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -60,28 +60,28 @@ func (node permissionable) Permission () (permission types.Permission) { // valuable allows a node to have an argument value. type valuable struct { - value Argument + argument Argument } -// Value returns the value argument of the node. -func (node valuable) Value () (value Argument) { - value = node.value +// Argument returns the value argument of the node. +func (node valuable) Argument () (argument Argument) { + argument = node.argument return } // multiValuable allows a node to have several argument values. type multiValuable struct { - values []Argument + arguments []Argument } -// Value returns the value at index. -func (node multiValuable) Value (index int) (value Argument) { - value = node.values[index] +// Argument returns the argument at index. +func (node multiValuable) Argument (index int) (argument Argument) { + argument = node.arguments[index] return } -// Length returns the amount of values in the mode. +// Length returns the amount of arguments in the mode. func (node multiValuable) Length () (length int) { - length = len(node.values) + length = len(node.arguments) return } From 4228d2b4cf368a2687f10e648aad77de90019637 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 14:48:05 -0400 Subject: [PATCH 06/34] Operators can no longer be arguments --- parser/phrase.go | 22 +++++++++++++--------- parser/tree.go | 13 +++++++------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/parser/phrase.go b/parser/phrase.go index 7db3fbd..bcf71f3 100644 --- a/parser/phrase.go +++ b/parser/phrase.go @@ -129,7 +129,10 @@ func (parser *ParsingOperation) parseBlockLevelPhrase ( // get command err = parser.expect(validPhraseStartTokens...) if err != nil { return } - phrase.command, phrase.kind, err = parser.parsePhraseCommand() + phrase.command, + phrase.kind, + phrase.operator, + err = parser.parsePhraseCommand() if err != nil { return } for { @@ -233,7 +236,10 @@ func (parser *ParsingOperation) parseArgumentLevelPhrase () ( // get command err = parser.nextToken(validPhraseStartTokens...) if err != nil { return } - phrase.command, phrase.kind, err = parser.parsePhraseCommand() + phrase.command, + phrase.kind, + phrase.operator, + err = parser.parsePhraseCommand() if err != nil { return } for { @@ -272,24 +278,22 @@ func (parser *ParsingOperation) parseArgumentLevelPhrase () ( // parsePhraseCommand parses the command argument of a phrase. func (parser *ParsingOperation) parsePhraseCommand () ( - command Argument, - kind PhraseKind, - err error, + command Argument, + kind PhraseKind, + operator lexer.TokenKind, + err error, ) { if isTokenOperator(parser.token) { err = parser.expect(operatorTokens...) if err != nil { return } - command.location = parser.token.Location() - command.kind = ArgumentKindOperator - command.value = parser.token.Kind() - if parser.token.Is(lexer.TokenKindColon) { kind = PhraseKindCase } else if parser.token.Is(lexer.TokenKindAssignment) { kind = PhraseKindAssign } else { kind = PhraseKindOperator + operator = parser.token.Kind() } err = parser.nextToken() diff --git a/parser/tree.go b/parser/tree.go index af89a49..cb3a8a2 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -2,6 +2,7 @@ package parser import "git.tebibyte.media/arf/arf/file" import "git.tebibyte.media/arf/arf/types" +import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/infoerr" // SyntaxTree represents an abstract syntax tree. It covers an entire module. It @@ -135,10 +136,6 @@ const ( // 'S' ArgumentKindRune - - // + - * / etc... - // this is only used as a phrase command - ArgumentKindOperator ) // Argument represents a value that can be placed anywhere a value goes. This @@ -229,11 +226,15 @@ const ( // syntactical concept. type Phrase struct { location file.Location - command Argument returnees []Argument multiValuable - + kind PhraseKind + + command Argument + + // only applicable for PhraseKindOperator + operator lexer.TokenKind // only applicable for control flow phrases block Block From cd9de16338a1d816c426683b1c88eda148fe2bc3 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 15:48:47 -0400 Subject: [PATCH 07/34] Removed previous code from type-notation.go --- parser/tree.go | 4 +- parser/type-notation.go | 240 +------------------------------------ tests/parser/data/main.arf | 6 + tests/parser/type/main.arf | 2 +- 4 files changed, 11 insertions(+), 241 deletions(-) diff --git a/parser/tree.go b/parser/tree.go index cb3a8a2..0ef5fd3 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -230,7 +230,9 @@ type Phrase struct { multiValuable kind PhraseKind - + + // TODO: do not have this be an argument. make a string version, and + // and identifier version. command Argument // only applicable for PhraseKindOperator diff --git a/parser/type-notation.go b/parser/type-notation.go index 945a08f..a97213a 100644 --- a/parser/type-notation.go +++ b/parser/type-notation.go @@ -48,11 +48,7 @@ func (parser *ParsingOperation) parseType () (what Type, err error) { err = parser.skipWhitespace() if err != nil { return } - err = parser.expect( - lexer.TokenKindName, - lexer.TokenKindUInt, - lexer.TokenKindLParen, - lexer.TokenKindLessThan) + err = parser.expect(lexer.TokenKindName, lexer.TokenKindUInt) if err != nil { return } if parser.token.Is(lexer.TokenKindName) { @@ -77,242 +73,8 @@ func (parser *ParsingOperation) parseType () (what Type, err error) { err = parser.nextToken() if err != nil { return } - } else if parser.token.Is(lexer.TokenKindLessThan) { - // parse default value - what.defaultValue, err = parser.parseBasicDefaultValue() - if err != nil { return } - - } else if parser.token.Is(lexer.TokenKindLParen) { - // parse members and member default values - what.defaultValue, - what.members, - err = parser.parseObjectDefaultValueAndMembers() - if err != nil { return } } } return } - -// parseBasicDefaultValue parses a default value of a non-object type. -func (parser *ParsingOperation) parseBasicDefaultValue () ( - value Argument, - err error, -) { - value.location = parser.token.Location() - - err = parser.expect(lexer.TokenKindLessThan) - if err != nil { return } - err = parser.nextToken() - if err != nil { return } - - var attributes []Argument - - defer func () { - // if we have multiple values, we need to return the full array - // instead. - if len(attributes) > 1 { - value.kind = ArgumentKindArrayDefaultValues - value.value = ArrayDefaultValues(attributes) - } - } () - - for { - err = parser.skipWhitespace() - if err != nil { return } - if parser.token.Is(lexer.TokenKindGreaterThan) { break } - - value, err = parser.parseArgument() - if err != nil { return } - attributes = append(attributes, value) - } - - err = parser.nextToken() - if err != nil { return } - - return -} - -// parseObjectDefaultValueAndMembers parses default values and new members of an -// object type. -func (parser *ParsingOperation) parseObjectDefaultValueAndMembers () ( - value Argument, - members []TypeMember, - err error, -) { - value.location = parser.token.Location() - - err = parser.expect(lexer.TokenKindLParen) - if err != nil { return } - parser.nextToken() - if err != nil { return } - - var attributes ObjectDefaultValues - - for { - err = parser.skipWhitespace() - if err != nil { return } - if parser.token.Is(lexer.TokenKindRParen) { break } - - err = parser.expect(lexer.TokenKindDot) - if err != nil { return } - parser.nextToken(lexer.TokenKindName, lexer.TokenKindPermission) - if err != nil { return } - - if parser.token.Is(lexer.TokenKindName) { - // parsing a defalut value for an inherited member - var memberName string - var memberValue Argument - - memberName, - memberValue, err = parser.parseObjectInheritedMember() - if err != nil { return } - - if value.kind == ArgumentKindNil { - // create default value map if it doesn't - // already exist - value.kind = ArgumentKindObjectDefaultValues - attributes = make(ObjectDefaultValues) - value.value = attributes - } - - // TODO: error on duplicate - if memberValue.kind != ArgumentKindNil { - attributes[memberName] = memberValue - } - - } else if parser.token.Is(lexer.TokenKindPermission) { - // parsing a member declaration - var member TypeMember - member, err = parser.parseObjectNewMember() - - // TODO: error on duplicate - members = append(members, member) - if err != nil { return } - } - } - - err = parser.nextToken() - if err != nil { return } - - return -} - -// parseObjectDefaultValue parses member default values only, and will throw an -// error when it encounteres a new member definition. -func (parser *ParsingOperation) parseObjectDefaultValue () ( - value Argument, - err error, -) { - value.location = parser.token.Location() - - err = parser.expect(lexer.TokenKindLParen) - if err != nil { return } - parser.nextToken() - if err != nil { return } - - var attributes ObjectDefaultValues - - for { - err = parser.skipWhitespace() - if err != nil { return } - if parser.token.Is(lexer.TokenKindRParen) { break } - - err = parser.expect(lexer.TokenKindDot) - if err != nil { return } - parser.nextToken(lexer.TokenKindName) - if err != nil { return } - - if value.kind == ArgumentKindNil { - value.kind = ArgumentKindObjectDefaultValues - attributes = make(ObjectDefaultValues) - value.value = attributes - } - - var memberName string - var memberValue Argument - memberName, - memberValue, err = parser.parseObjectInheritedMember() - - attributes[memberName] = memberValue - } - - err = parser.nextToken() - if err != nil { return } - - return -} - -// .name: - -// parseObjectInheritedMember parses a new default value for an inherited -// member. -func (parser *ParsingOperation) parseObjectInheritedMember () ( - name string, - value Argument, - err error, -) { - // get the name of the inherited member - err = parser.expect(lexer.TokenKindName) - value.location = parser.token.Location() - if err != nil { return } - name = parser.token.Value().(string) - - // we require a default value to be present - err = parser.nextToken(lexer.TokenKindColon) - if err != nil { return } - err = parser.nextToken(lexer.TokenKindLParen, lexer.TokenKindLessThan) - if err != nil { return } - - if parser.token.Is(lexer.TokenKindLessThan) { - // parse default value - value, err = parser.parseBasicDefaultValue() - if err != nil { return } - - } else if parser.token.Is(lexer.TokenKindLParen) { - // parse member default values - value, err = parser.parseObjectDefaultValue() - if err != nil { return } - } - - return -} - -// .ro name:Type:qualifier: - -// parseObjectNewMember parses an object member declaration, and its -// default value if it exists. -func (parser *ParsingOperation) parseObjectNewMember () ( - member TypeMember, - err error, -) { - // get member permission - err = parser.expect(lexer.TokenKindPermission) - member.location = parser.token.Location() - if err != nil { return } - member.permission = parser.token.Value().(types.Permission) - - // get member name - err = parser.nextToken(lexer.TokenKindName) - if err != nil { return } - member.name = parser.token.Value().(string) - - // get type - err = parser.nextToken(lexer.TokenKindColon) - if err != nil { return } - err = parser.nextToken(lexer.TokenKindName, lexer.TokenKindLBrace) - if err != nil { return } - member.what, err = parser.parseType() - if err != nil { return } - - // get bit width - if parser.token.Is(lexer.TokenKindBinaryAnd) { - err = parser.nextToken(lexer.TokenKindUInt) - if err != nil { return } - member.bitWidth = parser.token.Value().(uint64) - err = parser.nextToken() - if err != nil { return } - } - - return -} diff --git a/tests/parser/data/main.arf b/tests/parser/data/main.arf index bd204ba..7f6c767 100644 --- a/tests/parser/data/main.arf +++ b/tests/parser/data/main.arf @@ -26,6 +26,12 @@ data ro jObject:Obj (324 438) +# TODO: at some point, have this syntax for object literals. terminate members +# with newlines. +# data ro jObject:Bird ( + # .this 324 + # .that 438) + data ro lMutIntegerArray16:Int:16:mut data ro mExternalData:Int:8 diff --git a/tests/parser/type/main.arf b/tests/parser/type/main.arf index 611adf9..7236678 100644 --- a/tests/parser/type/main.arf +++ b/tests/parser/type/main.arf @@ -8,7 +8,7 @@ type ro bBitFields:Obj ro that:Int & 1 ro this:Int 298 & 24 -type ro cInit:Obj:( +type ro cInit:Obj ro that:String "hello world" ro this:Int 23 From 26f887dfcc6a60c7a0c16fb1e70ae10a61531557 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 16:13:02 -0400 Subject: [PATCH 08/34] tree-tostring is free of compiler errors --- parser/tree-tostring.go | 291 +++++++++++++++------------------------- parser/tree.go | 2 + 2 files changed, 108 insertions(+), 185 deletions(-) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index e38f6cf..1f3ce0f 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -66,66 +66,12 @@ func (identifier Identifier) ToString () (output string) { return } -func (values ObjectDefaultValues) ToString ( - indent int, - breakLine bool, -) ( - output string, -) { - if !breakLine { indent = 0 } - output += doIndent(indent, "(") - if breakLine { output += "\n" } - - for index, name := range sortMapKeysAlphabetically(values) { - if index > 0 && !breakLine { output += " " } - - value := values[name] - - output += doIndent(indent, "." + name + ":") - - isComplexDefaultValue := - value.kind == ArgumentKindObjectDefaultValues || - value.kind == ArgumentKindArrayDefaultValues - - if isComplexDefaultValue { - if breakLine { output += "\n" } - output += value.ToString(indent + 1, breakLine) - } else { - output += "<" - output += value.ToString(indent + 1, false) - output += ">" - } - if breakLine { output += "\n" } - } - output += doIndent(indent, ")") - return -} - -func (values ArrayDefaultValues) ToString ( - indent int, - breakLine bool, -) ( - output string, -) { - if !breakLine { indent = 0 } - output += doIndent(indent, "<") - if breakLine { output += "\n" } - - for index, value := range values { - if index > 0 && !breakLine { output += " " } - output += value.ToString(indent, breakLine) - } - - output += doIndent(indent, ">") - return -} - func (member TypeMember) ToString (indent int, breakLine bool) (output string) { output += doIndent(indent, ".") output += member.permission.ToString() + " " output += member.name + ":" - output += member.what.ToString(indent + 1, breakLine) + output += member.what.ToString() if member.bitWidth > 0 { output += fmt.Sprint(" & ", member.bitWidth) @@ -138,12 +84,12 @@ func (member TypeMember) ToString (indent int, breakLine bool) (output string) { return } -func (what Type) ToString (indent int, breakLine bool) (output string) { +func (what Type) ToString () (output string) { if what.kind == TypeKindBasic { output += what.name.ToString() } else { output += "{" - output += what.points.ToString(indent, breakLine) + output += what.points.ToString() if what.kind == TypeKindVariableArray { output += " .." @@ -159,46 +105,26 @@ func (what Type) ToString (indent int, breakLine bool) (output string) { if what.mutable { output += ":mut" } - - if what.members != nil { - if breakLine { - output += ":\n" + doIndent(indent, "(\n") - for _, member := range what.members { - output += member.ToString(indent, breakLine) - } - output += doIndent(indent, ")") - } else { - output += ":(" - for index, member := range what.members { - if index > 0 { output += " " } - output += member.ToString(indent, breakLine) - } - output += ")" - } - } - - defaultValueKind := what.defaultValue.kind - if defaultValueKind != ArgumentKindNil { - isComplexDefaultValue := - defaultValueKind == ArgumentKindObjectDefaultValues || - defaultValueKind == ArgumentKindArrayDefaultValues - - if isComplexDefaultValue { - output += ":" - if breakLine { output += "\n" } - output += what.defaultValue.ToString(indent, breakLine) - } else { - output += ":<" - output += what.defaultValue.ToString(indent, false) - output += ">" - } - } return } func (declaration Declaration) ToString (indent int) (output string) { output += declaration.name + ":" - output += declaration.what.ToString(indent, false) + 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" } + + for _, argument := range list.arguments { + output += argument.ToString(indent, breakline) + } + + output += doIndent(indent, "(") + if breakline { output += "\n" } return } @@ -216,13 +142,8 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) { indent, breakLine) - case ArgumentKindObjectDefaultValues: - output += argument.value.(ObjectDefaultValues). - ToString(indent, breakLine) - - case ArgumentKindArrayDefaultValues: - output += argument.value.(ArrayDefaultValues). - ToString(indent, breakLine) + case ArgumentKindList: + output += argument.value.(List).ToString(indent, breakLine) case ArgumentKindIdentifier: output += doIndent ( @@ -251,75 +172,6 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) { indent, "'" + string(argument.value.(rune)) + "'") if breakLine { output += "\n" } - - case ArgumentKindOperator: - var stringValue string - switch argument.value.(lexer.TokenKind) { - case lexer.TokenKindColon: - stringValue = ":" - case lexer.TokenKindPlus: - stringValue = "+" - case lexer.TokenKindMinus: - stringValue = "-" - case lexer.TokenKindIncrement: - stringValue = "++" - case lexer.TokenKindDecrement: - stringValue = "--" - case lexer.TokenKindAsterisk: - stringValue = "*" - case lexer.TokenKindSlash: - stringValue = "/" - case lexer.TokenKindExclamation: - stringValue = "!" - case lexer.TokenKindPercent: - stringValue = "%" - case lexer.TokenKindPercentAssignment: - stringValue = "%=" - case lexer.TokenKindTilde: - stringValue = "~" - case lexer.TokenKindTildeAssignment: - stringValue = "~=" - case lexer.TokenKindAssignment: - stringValue = "=" - case lexer.TokenKindEqualTo: - stringValue = "==" - case lexer.TokenKindNotEqualTo: - stringValue = "!=" - case lexer.TokenKindLessThanEqualTo: - stringValue = "<=" - case lexer.TokenKindLessThan: - stringValue = "<" - case lexer.TokenKindLShift: - stringValue = "<<" - case lexer.TokenKindLShiftAssignment: - stringValue = "<<=" - case lexer.TokenKindGreaterThan: - stringValue = ">" - case lexer.TokenKindGreaterThanEqualTo: - stringValue = ">=" - case lexer.TokenKindRShift: - stringValue = ">>" - case lexer.TokenKindRShiftAssignment: - stringValue = ">>=" - case lexer.TokenKindBinaryOr: - stringValue = "|" - case lexer.TokenKindBinaryOrAssignment: - stringValue = "|=" - case lexer.TokenKindLogicalOr: - stringValue = "||" - case lexer.TokenKindBinaryAnd: - stringValue = "&" - case lexer.TokenKindBinaryAndAssignment: - stringValue = "&=" - case lexer.TokenKindLogicalAnd: - stringValue = "&&" - case lexer.TokenKindBinaryXor: - stringValue = "^" - case lexer.TokenKindBinaryXorAssignment: - stringValue = "^=" - } - output += doIndent(indent, stringValue) - if breakLine { output += "\n" } } return @@ -331,7 +183,9 @@ func (section DataSection) ToString (indent int) (output string) { "data ", section.permission.ToString(), " ", section.name, ":", - section.what.ToString(indent + 1, true), "\n") + section.what.ToString(), "\n") + + output += section.argument.ToString(indent + 1, true) if section.external { output += doIndent(indent + 1, "external\n") @@ -346,32 +200,23 @@ func (section TypeSection) ToString (indent int) (output string) { "type ", section.permission.ToString(), " ", section.name, ":", - section.what.ToString(indent + 1, true), "\n") + section.what.ToString(), "\n") + + output += section.argument.ToString(indent + 1, true) return } - func (section EnumSection) ToString (indent int) (output string) { output += doIndent ( indent, "enum ", section.permission.ToString(), " ", section.name, ":", - section.what.ToString(indent + 1, true), "\n") + section.what.ToString(), "\n") for _, member := range section.members { - output += doIndent(indent + 1, "- ", member.name) - - isComplexInitialization := - member.value.kind == ArgumentKindObjectDefaultValues || - member.value.kind == ArgumentKindArrayDefaultValues - - if isComplexInitialization { - output += ":\n" - output += member.value.ToString(indent + 2, true) - } else if member.value.kind != ArgumentKindNil { - output += ":<" + member.value.ToString(0, false) + ">" - } + output += doIndent(indent + 1, "- ", member.name, "") + output += member.argument.ToString(indent, false) output += "\n" } return @@ -411,7 +256,83 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) { output += doIndent(indent) } - output += "[" + phrase.command.ToString(0, false) + output += "[" + + switch phrase.kind { + case + PhraseKindOperator, + PhraseKindLet, + PhraseKindAssign: + + 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) + } + for _, argument := range phrase.arguments { output += " " + argument.ToString(0, false) } diff --git a/parser/tree.go b/parser/tree.go index 0ef5fd3..c48f88e 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -154,6 +154,7 @@ type DataSection struct { nameable typeable permissionable + valuable external bool } @@ -164,6 +165,7 @@ type TypeSection struct { nameable typeable permissionable + valuable } // EnumMember represents a member of an enum section. From 870a33f4c227a20d3598e368934588ea63838f21 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 17:00:44 -0400 Subject: [PATCH 09/34] Untested, updated enum parsing --- parser/enum.go | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/parser/enum.go b/parser/enum.go index c2427d9..bd0cd7d 100644 --- a/parser/enum.go +++ b/parser/enum.go @@ -91,32 +91,19 @@ func (parser *ParsingOperation) parseEnumMember () ( member.name = parser.token.Value().(string) // see if value exists - err = parser.nextToken ( - lexer.TokenKindColon, - lexer.TokenKindNewline) + err = parser.nextToken() if err != nil { return } - - if parser.token.Is(lexer.TokenKindColon) { - err = parser.nextToken() - if err != nil { return } - err = parser.skipWhitespace() - if err != nil { return } - err = parser.expect ( - lexer.TokenKindLessThan, - lexer.TokenKindLParen) - if err != nil { return } - - if parser.token.Is(lexer.TokenKindLessThan) { - // parse value - member.value, err = parser.parseBasicDefaultValue() - if err != nil { return } - - } else if parser.token.Is(lexer.TokenKindLParen) { - // parse default values - member.value, err = parser.parseObjectDefaultValue() - if err != nil { return } - } + if parser.token.Is(lexer.TokenKindNewline) { + parser.nextToken() + // if we have exited the member, return + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 2 { return } } + // get value + member.argument, err = parser.parseArgument() + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + return } From 38409db74b023fbf83b9cc36961897f30b81648c Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 17:05:13 -0400 Subject: [PATCH 10/34] Updated enum correct test case --- parser/enum_test.go | 54 +++++++++++++++++++---------------------- parser/type-notation.go | 1 - 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/parser/enum_test.go b/parser/enum_test.go index 74c59b7..b199d06 100644 --- a/parser/enum_test.go +++ b/parser/enum_test.go @@ -7,55 +7,51 @@ func TestEnum (test *testing.T) { `:arf --- enum ro AffrontToGod:Int:4 - - bird0: - < + - bird0 + ) 28394 9328 398 9 - > - - bird1: - < + ) + - bird1 + ( 23 932832 398 2349 - > - - bird2: - < + ) + - bird2 + ( 1 2 3 4 - > + ) enum ro NamedColor:U32 - - red:<16711680> - - green:<65280> - - blue:<255> -enum ro ThisIsTerrible:Obj: - ( - .rw x:Int - .rw y:Int - ) - - up: + - red 16711680 + - green 65280 + - blue 255 +enum ro ThisIsTerrible:Vector + - up ( - .x:<0> - .y:<-1> + 0 + -1 ) - - down: + - down ( - .x:<0> - .y:<1> + 0 + 1 ) - - left: + - left ( - .x:<-1> - .y:<0> + -1 + 0 ) - - right: + - right ( - .x:<1> - .y:<0> + 1 + 0 ) enum ro Weekday:Int - sunday diff --git a/parser/type-notation.go b/parser/type-notation.go index a97213a..c94a608 100644 --- a/parser/type-notation.go +++ b/parser/type-notation.go @@ -2,7 +2,6 @@ package parser import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/infoerr" -import "git.tebibyte.media/arf/arf/types" // parseType parses a type notation of the form Name, {Name}, etc. func (parser *ParsingOperation) parseType () (what Type, err error) { From 37a216a53dc8a441e24627efb7b4887af7ef6c2b Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 17:36:39 -0400 Subject: [PATCH 11/34] Fixed enum parsing I think I did anyways. It wont parse either way becasue I haven't implemented lists. --- parser/enum.go | 15 +++++++-------- parser/tree-tostring.go | 6 ++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/parser/enum.go b/parser/enum.go index bd0cd7d..4460941 100644 --- a/parser/enum.go +++ b/parser/enum.go @@ -61,18 +61,11 @@ func (parser *ParsingOperation) parseEnumMembers ( // if we've left the block, stop parsing if !parser.token.Is(lexer.TokenKindIndent) { return } if parser.token.Value().(int) != 1 { return } - err = parser.nextToken(lexer.TokenKindMinus) - if err != nil { return } var member EnumMember member, err = parser.parseEnumMember() into.members = append(into.members, member) if err != nil { return } - - err = parser.expect(lexer.TokenKindNewline) - if err != nil { return } - err = parser.nextToken() - if err != nil { return } } } @@ -81,7 +74,7 @@ func (parser *ParsingOperation) parseEnumMember () ( member EnumMember, err error, ) { - err = parser.expect(lexer.TokenKindMinus) + err = parser.nextToken(lexer.TokenKindMinus) if err != nil { return } // get name @@ -98,6 +91,9 @@ func (parser *ParsingOperation) parseEnumMember () ( // if we have exited the member, return if !parser.token.Is(lexer.TokenKindIndent) { return } if parser.token.Value().(int) != 2 { return } + + err = parser.nextToken() + if err != nil { return } } // get value @@ -105,5 +101,8 @@ func (parser *ParsingOperation) parseEnumMember () ( err = parser.expect(lexer.TokenKindNewline) if err != nil { return } + err = parser.nextToken() + if err != nil { return } + return } diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 1f3ce0f..8965a6b 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -215,8 +215,10 @@ func (section EnumSection) ToString (indent int) (output string) { section.what.ToString(), "\n") for _, member := range section.members { - output += doIndent(indent + 1, "- ", member.name, "") - output += member.argument.ToString(indent, false) + output += doIndent(indent + 1, "- ", member.name) + if member.argument.kind != ArgumentKindNil { + output += " " + member.argument.ToString(indent, false) + } output += "\n" } return From 8dd90e1c6b1b79599840c810235c001844207dbe Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 18:03:27 -0400 Subject: [PATCH 12/34] Implemented list parsing --- parser/argument.go | 7 +++++++ parser/list.go | 32 ++++++++++++++++++++++++++++++++ parser/tree.go | 3 +++ 3 files changed, 42 insertions(+) create mode 100644 parser/list.go diff --git a/parser/argument.go b/parser/argument.go index e821322..5332e2b 100644 --- a/parser/argument.go +++ b/parser/argument.go @@ -3,6 +3,8 @@ package parser import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/infoerr" +// TODO: add support for dereferences and subscripts + var validArgumentStartTokens = []lexer.TokenKind { lexer.TokenKindName, @@ -13,6 +15,7 @@ var validArgumentStartTokens = []lexer.TokenKind { lexer.TokenKindRune, lexer.TokenKindLBracket, + lexer.TokenKindLParen, } func (parser *ParsingOperation) parseArgument () (argument Argument, err error) { @@ -84,6 +87,10 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error) argument.kind = ArgumentKindPhrase argument.value, err = parser.parseArgumentLevelPhrase() + case lexer.TokenKindLParen: + argument.kind = ArgumentKindList + argument.value, err = parser.parseList() + default: panic ( "unimplemented argument kind " + diff --git a/parser/list.go b/parser/list.go new file mode 100644 index 0000000..3be30f9 --- /dev/null +++ b/parser/list.go @@ -0,0 +1,32 @@ +package parser + +import "git.tebibyte.media/arf/arf/lexer" + +// parseList parses a parenthetically delimited list of arguments. +func (parser *ParsingOperation) parseList () (list List, err error) { + list.location = parser.token.Location() + + err = parser.expect(lexer.TokenKindLParen) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + + for { + err = parser.skipWhitespace() + if err != nil { return } + + // if we have reached the end of the list, stop + if parser.token.Is(lexer.TokenKindRParen) { break } + + // otherwise, parse argument + var argument Argument + argument, err = parser.parseArgument() + list.arguments = append(list.arguments, argument) + if err != nil { return } + } + + err = parser.nextToken() + if err != nil { return } + + return +} diff --git a/parser/tree.go b/parser/tree.go index c48f88e..81cdf49 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -86,6 +86,9 @@ type Declaration struct { // List represents an array or object literal. type List struct { locatable + + // TODO: have an array of unnamed arguments, and a map of named + // arguments multiValuable } From 3a4ccdda10da9ff262c65fd4b1793af74ebcad51 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 18:18:38 -0400 Subject: [PATCH 13/34] Fixed List.ToString for non breakline --- parser/tree-tostring.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 8965a6b..79103b5 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -119,11 +119,12 @@ func (list List) ToString (indent int, breakline bool) (output string) { output += doIndent(indent, "(") if breakline { output += "\n" } - for _, argument := range list.arguments { + for index, argument := range list.arguments { + if !breakline && index > 0 { output += " "} output += argument.ToString(indent, breakline) } - output += doIndent(indent, "(") + output += doIndent(indent, ")") if breakline { output += "\n" } return } From 93bc742339775475989114b30873069842e2d98e Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 18:23:23 -0400 Subject: [PATCH 14/34] Fixed enum test case to match ToString --- parser/enum_test.go | 48 +++++++-------------------------------------- 1 file changed, 7 insertions(+), 41 deletions(-) diff --git a/parser/enum_test.go b/parser/enum_test.go index b199d06..2fa0672 100644 --- a/parser/enum_test.go +++ b/parser/enum_test.go @@ -7,52 +7,18 @@ func TestEnum (test *testing.T) { `:arf --- enum ro AffrontToGod:Int:4 - - bird0 - ) - 28394 - 9328 - 398 - 9 - ) - - bird1 - ( - 23 - 932832 - 398 - 2349 - ) - - bird2 - ( - 1 - 2 - 3 - 4 - ) + - bird0 (28394 9328 398 9) + - bird1 (23 932832 398 2349) + - bird2 (1 2 3 4) enum ro NamedColor:U32 - red 16711680 - green 65280 - blue 255 enum ro ThisIsTerrible:Vector - - up - ( - 0 - -1 - ) - - down - ( - 0 - 1 - ) - - left - ( - -1 - 0 - ) - - right - ( - 1 - 0 - ) + - up (0 -1) + - down (0 1) + - left (-1 0) + - right (1 0) enum ro Weekday:Int - sunday - monday From 6c70e9c50dbc35cf6bf0fad9e30b9d2cebc8c043 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 18:42:00 -0400 Subject: [PATCH 15/34] Fixed data section parsing --- parser/data.go | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/parser/data.go b/parser/data.go index 313a909..27a23c0 100644 --- a/parser/data.go +++ b/parser/data.go @@ -35,28 +35,37 @@ func (parser *ParsingOperation) parseDataSection () ( return } - err = parser.expect(lexer.TokenKindNewline) - if err != nil { return } - err = parser.nextToken() - if err != nil { return } - - // check if data is external - if parser.token.Is(lexer.TokenKindIndent) && - parser.token.Value().(int) == 1 { + // see if value exists + if parser.token.Is(lexer.TokenKindNewline) { + parser.nextToken() + // if we have exited the member, return + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 1 { return } - err = parser.nextToken(lexer.TokenKindName) + err = parser.nextToken() if err != nil { return } + } + + // check if external + if parser.token.Is(lexer.TokenKindName) { if parser.token.Value().(string) == "external" { - section.external = true + err = parser.nextToken(lexer.TokenKindNewline) - if err != nil { return } + if err != nil { return } err = parser.nextToken() if err != nil { return } return } - - parser.previousToken() } + + // get value + section.argument, err = parser.parseArgument() + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + + err = parser.nextToken() + if err != nil { return } + return } From 3a38465368b32a1277f4f304f351d2e94ec9d3e2 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 18:43:40 -0400 Subject: [PATCH 16/34] Fixed DataSection/TypeSection.ToString --- parser/tree-tostring.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 79103b5..1f866e6 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -185,8 +185,10 @@ func (section DataSection) ToString (indent int) (output string) { section.permission.ToString(), " ", section.name, ":", section.what.ToString(), "\n") - - output += section.argument.ToString(indent + 1, true) + + if section.argument.kind != ArgumentKindNil { + output += section.argument.ToString(indent + 1, true) + } if section.external { output += doIndent(indent + 1, "external\n") @@ -202,8 +204,10 @@ func (section TypeSection) ToString (indent int) (output string) { section.permission.ToString(), " ", section.name, ":", section.what.ToString(), "\n") - - output += section.argument.ToString(indent + 1, true) + + if section.argument.kind != ArgumentKindNil { + output += section.argument.ToString(indent + 1, true) + } return } From f4c079786b37a0168c0b87c0d07e4bdd8c1fcc0a Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 27 Sep 2022 18:46:17 -0400 Subject: [PATCH 17/34] Made data test cases consistent with eachother --- parser/data_test.go | 44 ++++++++++++++------------------------ tests/parser/data/main.arf | 4 ++-- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/parser/data_test.go b/parser/data_test.go index 30739c1..d6155a4 100644 --- a/parser/data_test.go +++ b/parser/data_test.go @@ -6,14 +6,16 @@ func TestData (test *testing.T) { checkTree ("../tests/parser/data", false, `:arf --- -data ro aInteger:Int:<3202> -data ro bMutInteger:Int:mut:<3202> +data ro aInteger:Int + 3202 +data ro bMutInteger:Int:mut + 3202 data ro cIntegerPointer:{Int} data ro dMutIntegerPointer:{Int}:mut data ro eIntegerArray16:Int:16 data ro fIntegerArrayVariable:{Int ..} -data ro gIntegerArrayInitialized:Int:16: - < +data ro gIntegerArrayInitialized:Int:16 + ( 3948 293 293049 @@ -25,35 +27,21 @@ data ro gIntegerArrayInitialized:Int:16: 0 4785 92 - > -data rw hIntegerPointerInit:{Int}:<[& integer]> -data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]> -data ro jObject:Obj: - ( - .that:<324> - .this:<324> ) -data ro kNestedObject:Obj: +data rw hIntegerPointerInit:{Int} + [& integer] +data rw iMutIntegerPointerInit:{Int}:mut + [& integer] +data ro jObject:Obj ( - .ro newMember:Int:<9023> - ): - ( - .that: - ( - .bird2:<123.8439> - .bird3:<9328.21348239> - ) - .this: - ( - .bird0:<324> - .bird1:<"hello world"> - ) + 324 + 438 ) data ro lMutIntegerArray16:Int:16:mut data ro mExternalData:Int:8 external -data ro nIntegerArrayInitialized:Int:16:mut: - < +data ro nIntegerArrayInitialized:Int:16:mut + ( 3948 293 293049 @@ -65,6 +53,6 @@ data ro nIntegerArrayInitialized:Int:16:mut: 0 4785 92 - > + ) `, test) } diff --git a/tests/parser/data/main.arf b/tests/parser/data/main.arf index 7f6c767..35bf1b5 100644 --- a/tests/parser/data/main.arf +++ b/tests/parser/data/main.arf @@ -1,9 +1,9 @@ :arf --- -data ro aInteger:Int: 3202 +data ro aInteger:Int 3202 -data ro bMutInteger:Int:mut: 3202 +data ro bMutInteger:Int:mut 3202 data ro cIntegerPointer:{Int} From 1bd886fea04cf76ed95e6d80a6cdc837cc9688d3 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 28 Sep 2022 10:36:29 -0400 Subject: [PATCH 18/34] Rewrote type section correct test --- parser/type_test.go | 83 +++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/parser/type_test.go b/parser/type_test.go index 9863344..2a7eb43 100644 --- a/parser/type_test.go +++ b/parser/type_test.go @@ -6,55 +6,42 @@ func TestType (test *testing.T) { checkTree ("../tests/parser/type", false, `:arf --- -type ro aBasic:Obj: - ( - .ro that:Int - .ro this:Int - ) -type ro bBitFields:Obj: - ( - .ro that:Int & 1 - .ro this:Int:<298> & 24 - ) -type ro cInit:Obj: - ( - .ro that:String:<"hello world"> - .ro this:Int:<23> - ) -type ro dInitInherit:aBasic: - ( - .that:<9384> - .this:<389> - ) -type ro eInitAndDefine:aBasic: - ( - .ro these:aBasic: - ( - .ro born:Int:<4> - .ro in:Int - .ro the:Int:3: - < - 9348 - 92384 - 92834 - > - ): - ( - .this:<98> - ) - ): - ( - .that:<9384> - .this:<389> - ) +type ro aBasic:Obj + ro that:Int + ro this:Int + +type ro bBitFields:Obj + ro that:Int & 1 + ro this:Int + 298 & 24 +type ro cInit:Obj + ro that:String + "hello world" + ro this:Int + 23 +type ro dInitInherit:aBasic + ro that + 9384 + ro this + 389 +type ro eInitAndDefine:aBasic + ro this + 389 + ro that + 9384 + ro born:Int + 4 + ro in:Int + ro the:Int:3 + (9348 92384 92834) + ro walls:String + "live in the walls, die in the walls." type ro fBasic:Int -type ro gBasicInit:Int:<6> +type ro gBasicInit:Int + 6 type ro hIntArray:{Int ..} -type ro iIntArrayInit:Int:3: - < - 3298 - 923 - 92 - > +type ro iIntArrayInit:Int:3 + (3298 923 92) + `, test) } From 58af5f3f1512b77765a468c333adfbf5fc67c075 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 28 Sep 2022 11:07:39 -0400 Subject: [PATCH 19/34] Put type members back where they were --- parser/accessors.go | 12 ++++++------ parser/tree.go | 28 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/parser/accessors.go b/parser/accessors.go index fcb7957..f4dd4e1 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -82,22 +82,22 @@ func (what Type) Points () (points Type) { return } -// MembersLength returns the amount of new members the type specifier defines. +// MembersLength returns the amount of new members the type section defines. // If it defines no new members, it returns zero. -func (what Type) MembersLength () (length int) { - length = len(what.members) +func (section TypeSection) MembersLength () (length int) { + length = len(section.members) return } // Member returns the member at index. -func (what Type) Member (index int) (member TypeMember) { - member = what.members[index] +func (section TypeSection) Member (index int) (member TypeSectionMember) { + member = section.members[index] return } // BitWidth returns the bit width of the type member. If it is zero, it should // be treated as unspecified. -func (member TypeMember) BitWidth () (width uint64) { +func (member TypeSectionMember) BitWidth () (width uint64) { width = member.bitWidth return } diff --git a/parser/tree.go b/parser/tree.go index 81cdf49..f89be1e 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -47,17 +47,6 @@ const ( TypeKindVariableArray ) -// TypeMember represents a member variable of a type specifier. -type TypeMember struct { - locatable - nameable - typeable - permissionable - valuable - - bitWidth uint64 -} - // Type represents a type specifier type Type struct { locatable @@ -71,9 +60,6 @@ type Type struct { // not applicable for basic. points *Type - - // if non-nil, this type defines new members. - members []TypeMember } // Declaration represents a variable declaration. @@ -162,6 +148,17 @@ type DataSection struct { external bool } +// TypeSectionMember represents a member variable of a type section. +type TypeSectionMember struct { + locatable + nameable + typeable + permissionable + valuable + + bitWidth uint64 +} + // TypeSection represents a type definition. type TypeSection struct { locatable @@ -169,6 +166,9 @@ type TypeSection struct { typeable permissionable valuable + + // if non-nil, this type defines new members. + members []TypeSectionMember } // EnumMember represents a member of an enum section. From 6c02e45e2ec76fcec123eb1f3b7d22975968d29b Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:01:31 -0400 Subject: [PATCH 20/34] Untested type section parsing yay --- parser/data.go | 2 +- parser/tree-tostring.go | 2 +- parser/tree.go | 5 +- parser/type.go | 105 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 105 insertions(+), 9 deletions(-) diff --git a/parser/data.go b/parser/data.go index 27a23c0..0b0f0f3 100644 --- a/parser/data.go +++ b/parser/data.go @@ -38,7 +38,7 @@ func (parser *ParsingOperation) parseDataSection () ( // see if value exists if parser.token.Is(lexer.TokenKindNewline) { parser.nextToken() - // if we have exited the member, return + // if we have exited the section, return if !parser.token.Is(lexer.TokenKindIndent) { return } if parser.token.Value().(int) != 1 { return } diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 1f866e6..4ae2019 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -66,7 +66,7 @@ func (identifier Identifier) ToString () (output string) { return } -func (member TypeMember) ToString (indent int, breakLine bool) (output string) { +func (member TypeSectionMember) ToString (indent int, breakLine bool) (output string) { output += doIndent(indent, ".") output += member.permission.ToString() + " " diff --git a/parser/tree.go b/parser/tree.go index f89be1e..6051312 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -36,9 +36,12 @@ type Identifier struct { type TypeKind int const ( + // TypeKindNil means that the type is unspecified. + TypeKindNil TypeKind = iota + // TypeKindBasic means its a normal type and inherits from something. // Basic types can define new members on their parent types. - TypeKindBasic TypeKind = iota + TypeKindBasic // TypeKindPointer means it's a pointer. TypeKindPointer diff --git a/parser/type.go b/parser/type.go index 14c8aa6..292ec32 100644 --- a/parser/type.go +++ b/parser/type.go @@ -3,8 +3,8 @@ package parser import "git.tebibyte.media/arf/arf/types" import "git.tebibyte.media/arf/arf/lexer" -// parseTypeSection parses a blind type definition, meaning it can inherit from -// anything including primitives, but cannot define structure. +// parseTypeSection parses a type definition. It can inherit from other types, +// and define new members on them. func (parser *ParsingOperation) parseTypeSection () ( section TypeSection, err error, @@ -32,10 +32,103 @@ func (parser *ParsingOperation) parseTypeSection () ( section.what, err = parser.parseType() if err != nil { return } - parser.expect(lexer.TokenKindNewline) - if err != nil { return } - err = parser.nextToken() - if err != nil { return } + // see if value exists + if parser.token.Is(lexer.TokenKindNewline) { + parser.nextToken() + // if we have exited the section, return + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 1 { return } + + err = parser.nextToken() + if err != nil { return } + } + + // if we have not encountered members, get value and return. + if !parser.token.Is(lexer.TokenKindPermission) { + section.argument, err = parser.parseArgument() + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + + err = parser.nextToken() + if err != nil { return } + + return + } + + parser.previousToken() + + for { + // if we have exited the section, return + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 1 { return } + + err = parser.nextToken(lexer.TokenKindPermission) + if err != nil { return } + var member TypeSectionMember + member, err = parser.parseTypeSectionMember() + section.members = append(section.members, member) + if err != nil { return } + } return } + +// parseTypeSectionMember parses a type section member variable. +func (parser *ParsingOperation) parseTypeSectionMember () ( + member TypeSectionMember, + err error, +) { + // get permission + err = parser.expect(lexer.TokenKindPermission) + if err != nil { return } + member.permission = parser.token.Value().(types.Permission) + + // get name + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + member.name = parser.token.Value().(string) + + // if there is a type, get it + err = parser.nextToken() + if err != nil { return } + if parser.token.Is(lexer.TokenKindColon) { + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + member.what, err = parser.parseType() + if err != nil { return } + } + + // see if value exists + if parser.token.Is(lexer.TokenKindNewline) { + parser.nextToken() + // if we have exited the member, return + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 2 { return } + + err = parser.nextToken() + if err != nil { return } + } + + // if default value exists, get it + if !parser.token.Is(lexer.TokenKindBinaryAnd) { + member.argument, err = parser.parseArgument() + } + + // if there is a bit width specifier, get it + if parser.token.Is(lexer.TokenKindBinaryAnd) { + err = parser.nextToken(lexer.TokenKindUInt) + if err != nil { return } + member.bitWidth = parser.token.Value().(uint64) + + err = parser.nextToken() + if err != nil { return } + } + + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + + err = parser.nextToken() + if err != nil { return } + + return +} From 16fe6afdffe1518e1b52e1d75daf76ecd664a95c Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:03:19 -0400 Subject: [PATCH 21/34] Fixed segfault in Type.ToString --- parser/tree-tostring.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 4ae2019..68bb4ce 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -85,6 +85,11 @@ func (member TypeSectionMember) ToString (indent int, breakLine bool) (output st } func (what Type) ToString () (output string) { + if what.kind == TypeKindNil { + output += "NIL-TYPE" + return + } + if what.kind == TypeKindBasic { output += what.name.ToString() } else { From 06f9b5b71cdf169eeee4843fc5042ae00e88cd19 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:04:44 -0400 Subject: [PATCH 22/34] parseType sets the type kind in all cases --- parser/type-notation.go | 1 + 1 file changed, 1 insertion(+) diff --git a/parser/type-notation.go b/parser/type-notation.go index c94a608..a03fef3 100644 --- a/parser/type-notation.go +++ b/parser/type-notation.go @@ -8,6 +8,7 @@ func (parser *ParsingOperation) parseType () (what Type, err error) { err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace) if err != nil { return } what.location = parser.token.Location() + what.kind = TypeKindBasic if parser.token.Is(lexer.TokenKindLBrace) { what.kind = TypeKindPointer From 23072b54764153a23e14a0eef9511680bc07fe0d Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:10:58 -0400 Subject: [PATCH 23/34] Type members actually get ToString'd now --- parser/tree-tostring.go | 43 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 68bb4ce..15e4ec2 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -66,24 +66,6 @@ func (identifier Identifier) ToString () (output string) { return } -func (member TypeSectionMember) ToString (indent int, breakLine bool) (output string) { - output += doIndent(indent, ".") - - output += member.permission.ToString() + " " - output += member.name + ":" - output += member.what.ToString() - - if member.bitWidth > 0 { - output += fmt.Sprint(" & ", member.bitWidth) - } - - if breakLine { - output += "\n" - } - - return -} - func (what Type) ToString () (output string) { if what.kind == TypeKindNil { output += "NIL-TYPE" @@ -202,6 +184,27 @@ func (section DataSection) ToString (indent int) (output string) { return } +func (member TypeSectionMember) ToString (indent int) (output string) { + output += doIndent(indent, member.permission.ToString()) + + if member.what.kind != TypeKindNil { + output += " " + member.name + ":" + output += member.what.ToString() + } + + if member.argument.kind != ArgumentKindNil { + output += " " + member.argument.ToString(indent, false) + } + + if member.bitWidth > 0 { + output += fmt.Sprint(" & ", member.bitWidth) + } + + output += "\n" + + return +} + func (section TypeSection) ToString (indent int) (output string) { output += doIndent ( indent, @@ -213,6 +216,10 @@ func (section TypeSection) ToString (indent int) (output string) { if section.argument.kind != ArgumentKindNil { output += section.argument.ToString(indent + 1, true) } + + for _, member := range section.members { + output += member.ToString(indent + 1) + } return } From 011c9681920d43a0cfc938a53b94750250bed55f Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:13:22 -0400 Subject: [PATCH 24/34] Type section now passes test --- parser/tree-tostring.go | 4 ++-- parser/type_test.go | 38 +++++++++++++++----------------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 15e4ec2..8e2685b 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -186,10 +186,10 @@ func (section DataSection) ToString (indent int) (output string) { func (member TypeSectionMember) ToString (indent int) (output string) { output += doIndent(indent, member.permission.ToString()) + output += " " + member.name if member.what.kind != TypeKindNil { - output += " " + member.name + ":" - output += member.what.ToString() + output += ":" + member.what.ToString() } if member.argument.kind != ArgumentKindNil { diff --git a/parser/type_test.go b/parser/type_test.go index 2a7eb43..6619c1d 100644 --- a/parser/type_test.go +++ b/parser/type_test.go @@ -9,39 +9,31 @@ func TestType (test *testing.T) { type ro aBasic:Obj ro that:Int ro this:Int - type ro bBitFields:Obj ro that:Int & 1 - ro this:Int - 298 & 24 + ro this:Int 298 & 24 type ro cInit:Obj - ro that:String - "hello world" - ro this:Int - 23 + ro that:String "hello world" + ro this:Int 23 type ro dInitInherit:aBasic - ro that - 9384 - ro this - 389 + ro that 9384 + ro this 389 type ro eInitAndDefine:aBasic - ro this - 389 - ro that - 9384 - ro born:Int - 4 + ro this 389 + ro that 9384 + ro born:Int 4 ro in:Int - ro the:Int:3 - (9348 92384 92834) - ro walls:String - "live in the walls, die in the walls." + ro the:Int:3 (9348 92384 92834) + ro walls:String "live in the walls, die in the walls." type ro fBasic:Int type ro gBasicInit:Int 6 type ro hIntArray:{Int ..} type ro iIntArrayInit:Int:3 - (3298 923 92) - + ( + 3298 + 923 + 92 + ) `, test) } From 5f0e4697b5eb99349ca6db265ff2c170aa22bed1 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:18:47 -0400 Subject: [PATCH 25/34] Made some updates to func test case --- parser/func_test.go | 14 +++++++------- tests/parser/func/main.arf | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/parser/func_test.go b/parser/func_test.go index e44e528..c111e6d 100644 --- a/parser/func_test.go +++ b/parser/func_test.go @@ -8,13 +8,13 @@ func TestFunc (test *testing.T) { --- func ro aBasicExternal > someInput:Int:mut - < someOutput:Int:<4> + < someOutput:Int 4 --- external func ro bMethod @ bird:{Bird} > someInput:Int:mut - < someOutput:Int:<4> + < someOutput:Int 4 --- external func ro cBasicPhrases @@ -99,11 +99,11 @@ func ro gControlFlow [nestedThing] [else] [otherThing] -func ro hSetPhrase +func ro hDataInit --- - [let x:Int:<3>] - [let y:{Int}:<[loc x]>] - [let z:Int:8:<398 9 2309 983 -2387 478 555 123>] - [let bird:Bird:(.that:(.whenYou:<99999>) .this:<324>)] + [let x:Int 3] + [let y:{Int} [loc x]] + [let z:Int:8 (398 9 2309 983 -2387 478 555 123)] + [let bird:Bird ((99999) 324)] `, test) } diff --git a/tests/parser/func/main.arf b/tests/parser/func/main.arf index 2834cfe..0f33b45 100644 --- a/tests/parser/func/main.arf +++ b/tests/parser/func/main.arf @@ -122,9 +122,9 @@ func ro gControlFlow else otherThing -func ro hSetPhrase +func ro hDataInit --- - let x:Int:<3> + let x:Int 3 # loc is a reference, similar to * in C let y:{Int} [loc x] let z:Int:8 (398 9 2309 983 -2387 From 290f8799cf7261f3acb0638d9bfda70941ef2963 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:29:35 -0400 Subject: [PATCH 26/34] Parser parses function outputs --- parser/func.go | 22 +++++++++++++++++++--- parser/tree.go | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/parser/func.go b/parser/func.go index 7e775c5..5b61ace 100644 --- a/parser/func.go +++ b/parser/func.go @@ -171,7 +171,7 @@ func (parser *ParsingOperation) parseFuncArguments ( if err != nil { return } case lexer.TokenKindLessThan: - output := Declaration { } + output := FuncOutput { } output.location = parser.token.Location() // get name @@ -189,10 +189,26 @@ func (parser *ParsingOperation) parseFuncArguments ( into.outputs = append(into.outputs, output) - parser.expect(lexer.TokenKindNewline) + // skip newline if it is there + if parser.token.Is(lexer.TokenKindNewline) { + parser.nextToken() + // if we have exited the output, break + if !parser.token.Is(lexer.TokenKindIndent) { break } + if parser.token.Value().(int) != 2 { break } + + err = parser.nextToken() + if err != nil { return } + } + + // if default value exists, get it + if !parser.token.Is(lexer.TokenKindBinaryAnd) { + output.argument, err = parser.parseArgument() + } + + err = parser.expect(lexer.TokenKindNewline) if err != nil { return } + err = parser.nextToken() - if err != nil { return } } } } diff --git a/parser/tree.go b/parser/tree.go index 6051312..ad935ab 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -268,7 +268,7 @@ type FuncSection struct { receiver *Declaration inputs []Declaration - outputs []Declaration + outputs []FuncOutput root Block external bool From 94967d25e2845784a2a144523134fae18391fcbd Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:37:14 -0400 Subject: [PATCH 27/34] Removed let phrases We don't need them anymore --- parser/func_test.go | 8 ++++---- parser/phrase.go | 2 -- parser/tree-tostring.go | 26 ++++++++++++++++++-------- parser/tree.go | 1 - tests/parser/func/main.arf | 8 ++++---- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/parser/func_test.go b/parser/func_test.go index c111e6d..7ad00d2 100644 --- a/parser/func_test.go +++ b/parser/func_test.go @@ -101,9 +101,9 @@ func ro gControlFlow [otherThing] func ro hDataInit --- - [let x:Int 3] - [let y:{Int} [loc x]] - [let z:Int:8 (398 9 2309 983 -2387 478 555 123)] - [let bird:Bird ((99999) 324)] + [= x:Int 3] + [= y:{Int} [loc x]] + [= z:Int:8 (398 9 2309 983 -2387 478 555 123)] + [= bird:Bird ((99999) 324)] `, test) } diff --git a/parser/phrase.go b/parser/phrase.go index bcf71f3..da04024 100644 --- a/parser/phrase.go +++ b/parser/phrase.go @@ -312,8 +312,6 @@ func (parser *ParsingOperation) parsePhraseCommand () ( identifier := command.value.(Identifier) if len(identifier.trail) == 1 { switch identifier.trail[0] { - case "let": - kind = PhraseKindLet case "loc": kind = PhraseKindReference case "defer": diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 8e2685b..b6e9d64 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -95,7 +95,7 @@ func (what Type) ToString () (output string) { return } -func (declaration Declaration) ToString (indent int) (output string) { +func (declaration Declaration) ToString () (output string) { output += declaration.name + ":" output += declaration.what.ToString() return @@ -142,7 +142,7 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) { case ArgumentKindDeclaration: output += doIndent ( indent, - argument.value.(Declaration).ToString(indent)) + argument.value.(Declaration).ToString()) if breakLine { output += "\n" } case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat: @@ -260,11 +260,11 @@ func (behavior FaceBehavior) ToString (indent int) (output string) { output += doIndent(indent, behavior.name, "\n") for _, inputItem := range behavior.inputs { - output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n") + output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n") } for _, outputItem := range behavior.outputs { - output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n") + output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n") } return @@ -280,7 +280,6 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) { switch phrase.kind { case PhraseKindOperator, - PhraseKindLet, PhraseKindAssign: switch phrase.operator { @@ -373,6 +372,17 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) { return } +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 +} + func (block Block) ToString (indent int) (output string) { for _, phrase := range block { output += phrase.ToString(indent, true) @@ -391,15 +401,15 @@ func (section FuncSection) ToString (indent int) (output string) { if section.receiver != nil { output += doIndent ( indent + 1, - "@ ", section.receiver.ToString(indent), "\n") + "@ ", section.receiver.ToString(), "\n") } for _, inputItem := range section.inputs { - output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n") + output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n") } for _, outputItem := range section.outputs { - output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n") + output += outputItem.ToString(indent) } output += doIndent(indent + 1, "---\n") diff --git a/parser/tree.go b/parser/tree.go index ad935ab..c89b899 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -217,7 +217,6 @@ const ( PhraseKindCall = iota PhraseKindCallExternal PhraseKindOperator - PhraseKindLet PhraseKindAssign PhraseKindReference PhraseKindDefer diff --git a/tests/parser/func/main.arf b/tests/parser/func/main.arf index 0f33b45..3c47e1c 100644 --- a/tests/parser/func/main.arf +++ b/tests/parser/func/main.arf @@ -124,11 +124,11 @@ func ro gControlFlow func ro hDataInit --- - let x:Int 3 + = x:Int 3 # loc is a reference, similar to * in C - let y:{Int} [loc x] - let z:Int:8 (398 9 2309 983 -2387 + = y:{Int} [loc x] + = z:Int:8 (398 9 2309 983 -2387 478 555 123) - let bird:Bird ( + = bird:Bird ( (99999) 324) From 7374de26331a3a5c51316d4b1e99e051ddb77b66 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 02:43:24 -0400 Subject: [PATCH 28/34] Func section tostring fixes --- parser/tree-tostring.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index b6e9d64..c0bef0e 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -278,9 +278,13 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) { output += "[" switch phrase.kind { - case - PhraseKindOperator, - PhraseKindAssign: + case PhraseKindCase: + output += ":" + + case PhraseKindAssign: + output += "=" + + case PhraseKindOperator: switch phrase.operator { case lexer.TokenKindColon: From a31c975c9dee9135dfe36af64dfdc686b36db534 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 11:02:37 -0400 Subject: [PATCH 29/34] Func section tostrings and parses output values properly --- parser/func.go | 21 +++++++++++++-------- parser/tree-tostring.go | 3 +++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/parser/func.go b/parser/func.go index 5b61ace..d7f9405 100644 --- a/parser/func.go +++ b/parser/func.go @@ -186,29 +186,34 @@ func (parser *ParsingOperation) parseFuncArguments ( if err != nil { return } output.what, err = parser.parseType() if err != nil { return } - - into.outputs = append(into.outputs, output) // skip newline if it is there if parser.token.Is(lexer.TokenKindNewline) { parser.nextToken() // if we have exited the output, break - if !parser.token.Is(lexer.TokenKindIndent) { break } - if parser.token.Value().(int) != 2 { break } + exited := + !parser.token.Is(lexer.TokenKindIndent) || + parser.token.Value().(int) != 2 + + if exited { + into.outputs = append(into.outputs, output) + break + } err = parser.nextToken() if err != nil { return } } - // if default value exists, get it - if !parser.token.Is(lexer.TokenKindBinaryAnd) { - output.argument, err = parser.parseArgument() - } + // get default value + output.argument, err = parser.parseArgument() + into.outputs = append(into.outputs, output) + if err != nil { return } err = parser.expect(lexer.TokenKindNewline) if err != nil { return } err = parser.nextToken() + if err != nil { return } } } } diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index c0bef0e..ad5e786 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -379,10 +379,13 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) { func (funcOutput FuncOutput) ToString (indent int) (output string) { output += doIndent(indent + 1) output += "< " + funcOutput.Declaration.ToString() + // why is it always nil??? WHY??? if funcOutput.argument.kind != ArgumentKindNil { output += " " + funcOutput.argument.ToString(indent, false) } output += "\n" + + print(funcOutput.argument.ToString(0, true)) return } From 8b88e1d44070096394c15fa794ba21bc1a77e936 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 11:06:45 -0400 Subject: [PATCH 30/34] Sort ToString of requires --- parser/meta_test.go | 2 +- parser/tree-tostring.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/parser/meta_test.go b/parser/meta_test.go index 467135f..07d3952 100644 --- a/parser/meta_test.go +++ b/parser/meta_test.go @@ -11,8 +11,8 @@ func TestMeta (test *testing.T) { author "Sasha Koshka" license "GPLv3" require "` + filepath.Join(cwd, "./some/local/module") + `" -require "/some/absolute/path/to/someModule" require "/usr/local/include/arf/someLibraryInstalledInStandardLocation" +require "/some/absolute/path/to/someModule" --- `, test) } diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index ad5e786..0896e16 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -41,7 +41,8 @@ func (tree SyntaxTree) ToString (indent int) (output string) { output += doIndent(indent, "license \"", tree.license, "\"\n") } - for _, require := range tree.requires { + for _, name := range sortMapKeysAlphabetically(tree.requires) { + require := tree.requires[name] output += doIndent(indent, "require \"", require, "\"\n") } @@ -379,13 +380,10 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) { func (funcOutput FuncOutput) ToString (indent int) (output string) { output += doIndent(indent + 1) output += "< " + funcOutput.Declaration.ToString() - // why is it always nil??? WHY??? if funcOutput.argument.kind != ArgumentKindNil { output += " " + funcOutput.argument.ToString(indent, false) } output += "\n" - - print(funcOutput.argument.ToString(0, true)) return } From 51428e3755193ae1d7e3cb5c1880c44e655d0c87 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 11:15:58 -0400 Subject: [PATCH 31/34] Pass skim test --- parser/parser.go | 27 +++++++++++++++++++++++---- parser/skim_test.go | 2 +- tests/parser/skim/main.arf | 4 +++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index b64f89c..1e54f3f 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -150,16 +150,35 @@ func (parser *ParsingOperation) previousToken () { // skipIndentLevel advances the parser, ignoring every line with an indentation // equal to or greater than the specified indent. func (parser *ParsingOperation) skipIndentLevel (indent int) (err error) { + braceLevel := 0 + parenLevel := 0 + bracketLevel := 0 + for { if parser.token.Is(lexer.TokenKindNewline) { err = parser.nextToken() if err != nil { return } - if !parser.token.Is(lexer.TokenKindIndent) || - parser.token.Value().(int) < indent { + shouldBreak := + !parser.token.Is(lexer.TokenKindIndent) || + parser.token.Value().(int) < indent + + shouldBreak = + shouldBreak && + braceLevel < 1 && + parenLevel < 1 && + bracketLevel < 1 - return - } + if shouldBreak { return } + } + + switch parser.token.Kind() { + case lexer.TokenKindLBrace: braceLevel ++ + case lexer.TokenKindRBrace: braceLevel -- + case lexer.TokenKindLParen: parenLevel ++ + case lexer.TokenKindRParen: parenLevel -- + case lexer.TokenKindLBracket: bracketLevel ++ + case lexer.TokenKindRBracket: bracketLevel -- } err = parser.nextToken() diff --git a/parser/skim_test.go b/parser/skim_test.go index 44eed97..372f0a9 100644 --- a/parser/skim_test.go +++ b/parser/skim_test.go @@ -21,7 +21,7 @@ func ro fComplexFunction external func ro gExternalFunction > x:Int - < arr:Int + < arr:Int 5 --- external `, test) diff --git a/tests/parser/skim/main.arf b/tests/parser/skim/main.arf index bfeba2d..e2bfed6 100644 --- a/tests/parser/skim/main.arf +++ b/tests/parser/skim/main.arf @@ -20,7 +20,9 @@ data ro eIntegerArrayInitialized:Int:16:mut func ro fComplexFunction --- = x:Int 3 - = y:{Int} [loc x] + = y:{Int +} [loc x +] = z:Int:8 ( 398 9 2309 983 -2387 478 555 123) From 4811ea5257a4ebf99ec0ba536f99b2b405fcf3cf Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 11:28:12 -0400 Subject: [PATCH 32/34] Wrote interface test case --- parser/face_test.go | 25 +++++++++++++++++++++++++ tests/parser/face/main.arf | 9 ++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 parser/face_test.go diff --git a/parser/face_test.go b/parser/face_test.go new file mode 100644 index 0000000..a7b8b4b --- /dev/null +++ b/parser/face_test.go @@ -0,0 +1,25 @@ +package parser + +import "testing" + +func TestFace (test *testing.T) { + checkTree ("../tests/parser/face", false, +`:arf +--- +face ro ReadWriter:Face + write + > data:{Byte ..} + < wrote:Int + < err:Error + read + > into:{Byte ..} + < read:Int + < err:Error +face ro Destroyer:Face + destroy +face ro cFuncInterface + > something:Int + < someOutput:Int + < otherOutput:String +`, test) +} diff --git a/tests/parser/face/main.arf b/tests/parser/face/main.arf index 8288cdc..ab00e62 100644 --- a/tests/parser/face/main.arf +++ b/tests/parser/face/main.arf @@ -1,7 +1,7 @@ :arf --- -face ro ReadWriter:Face +face ro aReadWriter:Face write > data:{Byte ..} < wrote:Int @@ -11,7 +11,10 @@ face ro ReadWriter:Face < read:Int < err:Error -face ro Destroyer:Face +face ro bDestroyer:Face destroy -# TODO: add test case for func interface +face ro cFuncInterface + > something:Int + < someOutput:Int + < otherOutput:String From 2ceb3f817433c62ef625915095905d7c2da33a5a Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 15:45:25 -0400 Subject: [PATCH 33/34] Interfaces get parsed properly (i think) --- parser/face.go | 88 ++++++++++++++++++++++++++++---------- parser/face_test.go | 14 +++--- parser/tree.go | 14 +++++- tests/parser/face/main.arf | 2 +- 4 files changed, 87 insertions(+), 31 deletions(-) diff --git a/parser/face.go b/parser/face.go index 62f2605..776f198 100644 --- a/parser/face.go +++ b/parser/face.go @@ -12,8 +12,7 @@ func (parser *ParsingOperation) parseFaceSection () ( err = parser.expect(lexer.TokenKindName) if err != nil { return } - section.behaviors = make(map[string] FaceBehavior) - section.location = parser.token.Location() + section.location = parser.token.Location() // get permission err = parser.nextToken(lexer.TokenKindPermission) @@ -32,24 +31,59 @@ func (parser *ParsingOperation) parseFaceSection () ( if err != nil { return } section.inherits, err = parser.parseIdentifier() if err != nil { return } - err = parser.nextToken(lexer.TokenKindNewline) + err = parser.expect(lexer.TokenKindNewline) if err != nil { return } err = parser.nextToken() if err != nil { return } + + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 1 { return } + err = parser.nextToken ( + lexer.TokenKindName, + lexer.TokenKindGreaterThan, + lexer.TokenKindLessThan) + if err != nil { return } + + if parser.token.Is(lexer.TokenKindName) { + // parse type interface + parser.previousToken() + section.behaviors, err = parser.parseFaceBehaviors() + if err != nil { return } + } else { + // parse function interface + parser.previousToken() + section.inputs, + section.outputs, err = parser.parseFaceBehaviorArguments(1) + if err != nil { return } + } + + return +} + +// parseFaceBehaviors parses a list of interface behaviors for an object +// interface. +func (parser *ParsingOperation) parseFaceBehaviors () ( + behaviors map[string] FaceBehavior, + err error, +) { // parse members + behaviors = make(map[string] FaceBehavior) for { // if we've left the block, stop parsing if !parser.token.Is(lexer.TokenKindIndent) { return } if parser.token.Value().(int) != 1 { return } + + err = parser.nextToken(lexer.TokenKindName) + behaviorBeginning := parser.token.Location() + if err != nil { return } // parse behavior - behaviorBeginning := parser.token.Location() var behavior FaceBehavior - behavior, err = parser.parseFaceBehavior() + behavior, err = parser.parseFaceBehavior(1) // add to section - _, exists := section.behaviors[behavior.name] + _, exists := behaviors[behavior.name] if exists { err = infoerr.NewError ( behaviorBeginning, @@ -58,23 +92,21 @@ func (parser *ParsingOperation) parseFaceSection () ( infoerr.ErrorKindError) return } - section.behaviors[behavior.name] = behavior + behaviors[behavior.name] = behavior if err != nil { return } } } -// parseFaceBehavior parses a single interface behavior. Indentation level is -// assumed. -func (parser *ParsingOperation) parseFaceBehavior () ( +// parseFaceBehavior parses a single interface behavior. +func (parser *ParsingOperation) parseFaceBehavior ( + indent int, +) ( behavior FaceBehavior, err error, ) { - err = parser.expect(lexer.TokenKindIndent) - if err != nil { return } - // get name - err = parser.nextToken(lexer.TokenKindName) + err = parser.expect(lexer.TokenKindName) if err != nil { return } behavior.name = parser.token.Value().(string) @@ -82,11 +114,27 @@ func (parser *ParsingOperation) parseFaceBehavior () ( if err != nil { return } err = parser.nextToken() if err != nil { return } + + behavior.inputs, + behavior.outputs, + err = parser.parseFaceBehaviorArguments(indent + 1) + if err != nil { return } + + return +} + +func (parser *ParsingOperation) parseFaceBehaviorArguments ( + indent int, +) ( + inputs []Declaration, + outputs []Declaration, + err error, +) { for { - // if we've left the block, stop parsing + // if we've left the behavior, stop parsing if !parser.token.Is(lexer.TokenKindIndent) { return } - if parser.token.Value().(int) != 2 { return } + if parser.token.Value().(int) != indent { return } // get preceding symbol err = parser.nextToken ( @@ -115,13 +163,9 @@ func (parser *ParsingOperation) parseFaceBehavior () ( if err != nil { return } if kind == lexer.TokenKindGreaterThan { - behavior.inputs = append ( - behavior.inputs, - declaration) + inputs = append(inputs, declaration) } else { - behavior.outputs = append ( - behavior.outputs, - declaration) + outputs = append(outputs, declaration) } } } diff --git a/parser/face_test.go b/parser/face_test.go index a7b8b4b..ff38360 100644 --- a/parser/face_test.go +++ b/parser/face_test.go @@ -6,18 +6,18 @@ func TestFace (test *testing.T) { checkTree ("../tests/parser/face", false, `:arf --- -face ro ReadWriter:Face - write - > data:{Byte ..} - < wrote:Int - < err:Error +face ro aReadWriter:Face read > into:{Byte ..} < read:Int < err:Error -face ro Destroyer:Face + write + > data:{Byte ..} + < wrote:Int + < err:Error +face ro bDestroyer:Face destroy -face ro cFuncInterface +face ro cFuncInterface:Func > something:Int < someOutput:Int < otherOutput:String diff --git a/parser/tree.go b/parser/tree.go index c89b899..35eb8fd 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -191,6 +191,15 @@ type EnumSection struct { members []EnumMember } +// FaceKind determines if an interface is a type interface or an function +// interface. +type FaceKind int + +const ( + FaceKindType FaceKind = iota + FaceKindFunc +) + // FaceBehavior represents a behavior of an interface section. type FaceBehavior struct { locatable @@ -206,8 +215,11 @@ type FaceSection struct { nameable permissionable inherits Identifier - + + kind FaceKind + behaviors map[string] FaceBehavior + FaceBehavior } // PhraseKind determines what semantic role a phrase plays. diff --git a/tests/parser/face/main.arf b/tests/parser/face/main.arf index ab00e62..0a39686 100644 --- a/tests/parser/face/main.arf +++ b/tests/parser/face/main.arf @@ -14,7 +14,7 @@ face ro aReadWriter:Face face ro bDestroyer:Face destroy -face ro cFuncInterface +face ro cFuncInterface:Func > something:Int < someOutput:Int < otherOutput:String From 3e1acdc74af1fc3fbd4333abf7acaab4aebf8f13 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 29 Sep 2022 15:52:14 -0400 Subject: [PATCH 34/34] Face test is now passed --- parser/face.go | 11 +++++++---- parser/tree-tostring.go | 17 ++++++++++++++--- parser/tree.go | 3 ++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/parser/face.go b/parser/face.go index 776f198..80368e7 100644 --- a/parser/face.go +++ b/parser/face.go @@ -47,11 +47,13 @@ func (parser *ParsingOperation) parseFaceSection () ( if parser.token.Is(lexer.TokenKindName) { // parse type interface + section.kind = FaceKindType parser.previousToken() section.behaviors, err = parser.parseFaceBehaviors() if err != nil { return } } else { // parse function interface + section.kind = FaceKindFunc parser.previousToken() section.inputs, section.outputs, err = parser.parseFaceBehaviorArguments(1) @@ -157,15 +159,16 @@ func (parser *ParsingOperation) parseFaceBehaviorArguments ( if err != nil { return } declaration.what, err = parser.parseType() if err != nil { return } - err = parser.expect(lexer.TokenKindNewline) - if err != nil { return } - err = parser.nextToken() - if err != nil { return } if kind == lexer.TokenKindGreaterThan { inputs = append(inputs, declaration) } else { outputs = append(outputs, declaration) } + + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } } } diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 0896e16..ab75531 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -250,10 +250,21 @@ func (section FaceSection) ToString (indent int) (output string) { section.name, ":", section.inherits.ToString(), "\n") - for _, name := range sortMapKeysAlphabetically(section.behaviors) { - behavior := section.behaviors[name] - output += behavior.ToString(indent + 1) + 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") + } } + return } diff --git a/parser/tree.go b/parser/tree.go index 35eb8fd..f46e053 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -196,7 +196,8 @@ type EnumSection struct { type FaceKind int const ( - FaceKindType FaceKind = iota + FaceKindEmpty FaceKind = iota + FaceKindType FaceKindFunc )