From f95c7e0b1c19ef2343c6ae83e39ae7131ecc2ced Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 10:55:50 -0400 Subject: [PATCH 01/12] Basic test file for interface section --- tests/parser/face/main.arf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/parser/face/main.arf diff --git a/tests/parser/face/main.arf b/tests/parser/face/main.arf new file mode 100644 index 0000000..81d6b24 --- /dev/null +++ b/tests/parser/face/main.arf @@ -0,0 +1,15 @@ +:arf +--- + +face ro ReadWriter + write + > data:{Byte ..} + < wrote:Int + < err:Error + read + > into:{Byte ..} + < read:Int + < err:Error + +face ro Destroyer + destroy From cd55a0ad8d635ca27cf4268175b1edfd8025b1e7 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 10:56:37 -0400 Subject: [PATCH 02/12] Add interface section to tree --- parser/tree.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/parser/tree.go b/parser/tree.go index 559dbc8..f10a5e5 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -14,6 +14,7 @@ type SyntaxTree struct { typeSections map[string] *TypeSection objtSections map[string] *ObjtSection enumSections map[string] *EnumSection + faceSections map[string] *FaceSection dataSections map[string] *DataSection } @@ -203,3 +204,22 @@ type EnumSection struct { // TODO: order matters here we need to store these in an array members map[string] Argument } + +// FaceBehavior represents a behavior of an interface section. +type FaceBehavior struct { + location file.Location + name string + + inputs []Declaration + outputs []Declaration +} + +// FaceSection represents an interface type section. +type FaceSection struct { + location file.Location + name string + + what Type + permission types.Permission + behaviors map[string] FaceBehavior +} From 944fc8514ececda598080c7dd706a14c697d4e87 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 13:46:20 -0400 Subject: [PATCH 03/12] Add correct output for face test case --- parser/parser_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/parser/parser_test.go b/parser/parser_test.go index ca4b7a0..a6b555a 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -192,3 +192,21 @@ enum ro Weekday:Int wednesday `, test) } + +func Test (test *testing.T) { + checkTree ("../tests/parser/face", +`:arf +--- +face ro Destroyer + destroy +face ro ReadWriter + read + > into:{Byte ..} + < read:Int + < err:Error + write + > data:{Byte ..} + < wrote:Int + < err:Error +`, test) +} From 3ef1e706b38b8cd0382043b23785fd9443a86de5 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 13:54:44 -0400 Subject: [PATCH 04/12] Added ToString method to face section --- parser/tree-tostring.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 8c67798..6d96aac 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -353,3 +353,32 @@ func (section *EnumSection) ToString (indent int) (output string) { } return } + +func (section *FaceSection) ToString (indent int) (output string) { + output += doIndent ( + indent, + "face ", + section.permission.ToString(), " ", + section.name, ":", + section.inherits, "\n") + + for _, name := range sortMapKeysAlphabetically(section.behaviors) { + behavior := section.behaviors[name] + output += behavior.ToString(indent + 1) + } + return +} + +func (behavior *FaceBehavior) ToString (indent int) (output string) { + output += doIndent(indent, behavior.name, "\n") + + for _, inputItem := range behavior.inputs { + output += doIndent(indent, "> ", inputItem.ToString(), "\n") + } + + for _, outputItem := range behavior.outputs { + output += doIndent(indent, "< ", outputItem.ToString(), "\n") + } + + return +} From 8817d72cb3243d03078420e15d5502ee0bf2abde Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 13:56:59 -0400 Subject: [PATCH 05/12] Interfaces can inherit other interfaces --- parser/tree.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/tree.go b/parser/tree.go index f10a5e5..f6e6e55 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -218,8 +218,8 @@ type FaceBehavior struct { type FaceSection struct { location file.Location name string + inherits string - what Type permission types.Permission behaviors map[string] FaceBehavior } From 441b036a1c7d273a4ab12bcdf8a14bb4460680b1 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 14:07:56 -0400 Subject: [PATCH 06/12] Updated test case to reflect previous commit --- parser/parser_test.go | 4 ++-- tests/parser/face/main.arf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/parser_test.go b/parser/parser_test.go index a6b555a..cf25d54 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -197,9 +197,9 @@ func Test (test *testing.T) { checkTree ("../tests/parser/face", `:arf --- -face ro Destroyer +face ro Destroyer:Face destroy -face ro ReadWriter +face ro ReadWriter:Face read > into:{Byte ..} < read:Int diff --git a/tests/parser/face/main.arf b/tests/parser/face/main.arf index 81d6b24..4a78a7c 100644 --- a/tests/parser/face/main.arf +++ b/tests/parser/face/main.arf @@ -1,7 +1,7 @@ :arf --- -face ro ReadWriter +face ro ReadWriter:Face write > data:{Byte ..} < wrote:Int @@ -11,5 +11,5 @@ face ro ReadWriter < read:Int < err:Error -face ro Destroyer +face ro Destroyer:Face destroy From 4eac5c67aa471a624d400eae8b0668d869624bf8 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 15:13:00 -0400 Subject: [PATCH 07/12] Added untested interface section parsing --- parser/face.go | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 parser/face.go diff --git a/parser/face.go b/parser/face.go new file mode 100644 index 0000000..a6b96eb --- /dev/null +++ b/parser/face.go @@ -0,0 +1,130 @@ +package parser + +import "git.tebibyte.media/sashakoshka/arf/types" +import "git.tebibyte.media/sashakoshka/arf/lexer" +import "git.tebibyte.media/sashakoshka/arf/infoerr" + +// parseFaceSection parses an interface section. +func (parser *ParsingOperation) parseFaceSection () ( + section *FaceSection, + err error, +) { + err = parser.expect(lexer.TokenKindName) + if err != nil { return } + + section = &FaceSection { + location: parser.token.Location(), + behaviors: make(map[string] FaceBehavior), + } + + // get permission + err = parser.nextToken(lexer.TokenKindPermission) + if err != nil { return } + section.permission = parser.token.Value().(types.Permission) + + // get name + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + section.name = parser.token.Value().(string) + + // parse inherited interface + err = parser.nextToken(lexer.TokenKindColon) + if err != nil { return } + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + section.inherits = parser.token.Value().(string) + if err != nil { return } + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + + // parse members + for { + // if we've left the block, stop parsing + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 1 { return } + + // parse behavior + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + behaviorBeginning := parser.token.Location() + var behavior FaceBehavior + behavior, err = parser.parseFaceBehavior() + + // add to section + _, exists := section.behaviors[behavior.name] + if exists { + err = infoerr.NewError ( + behaviorBeginning, + "multiple behaviors named " + behavior.name + + " in this interface", + infoerr.ErrorKindError) + return + } + + if err != nil { return } + } + return +} + +// parseFaceBehavior parses a single interface behavior. Indentation level is +// assumed. +func (parser *ParsingOperation) parseFaceBehavior () ( + behavior FaceBehavior, + err error, +) { + // get name + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + behavior.name = parser.token.Value().(string) + + for { + err = parser.nextToken(lexer.TokenKindNewline) + if err != nil { return } + + // if we've left the block, stop parsing + err = parser.nextToken() + if err != nil { return } + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 2 { return } + + // get preceding symbol + err = parser.nextToken ( + lexer.TokenKindGreaterThan, + lexer.TokenKindLessThan) + if err != nil { return } + kind := parser.token.Kind() + + var declaration Declaration + + // get name + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + declaration.name = parser.token.Value().(string) + + // parse inherited type + err = parser.nextToken(lexer.TokenKindColon) + if err != nil { return } + err = parser.nextToken() + 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 { + behavior.inputs = append ( + behavior.inputs, + declaration) + } else { + behavior.inputs = append ( + behavior.inputs, + declaration) + } + } + + return +} From b0d4ecc83f1143f1555a5a2fd8473fd1cfaed622 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 15:14:44 -0400 Subject: [PATCH 08/12] Added interface section parsing to body --- parser/body.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/parser/body.go b/parser/body.go index a5bf767..3174e13 100644 --- a/parser/body.go +++ b/parser/body.go @@ -39,6 +39,14 @@ func (parser *ParsingOperation) parseBody () (err error) { parser.tree.objtSections[section.name] = section if err != nil { return } case "face": + var section *FaceSection + section, err = parser.parseFaceSection() + if parser.tree.faceSections == nil { + parser.tree.faceSections = + make(map[string] *FaceSection) + } + parser.tree.faceSections[section.name] = section + if err != nil { return } case "enum": var section *EnumSection section, err = parser.parseEnumSection() From 1f88b54eaad97fdeaccf5362a8f67b08cc6e2a33 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 23 Aug 2022 22:25:21 -0400 Subject: [PATCH 09/12] Face sections are actually ToString'd now --- parser/tree-tostring.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 6d96aac..832c3a0 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -61,6 +61,11 @@ func (tree *SyntaxTree) ToString (indent int) (output string) { output += tree.enumSections[name].ToString(indent) } + faceSectionKeys := sortMapKeysAlphabetically(tree.faceSections) + for _, name := range faceSectionKeys { + output += tree.faceSections[name].ToString(indent) + } + dataSectionKeys := sortMapKeysAlphabetically(tree.dataSections) for _, name := range dataSectionKeys { output += tree.dataSections[name].ToString(indent) From 39f8d7e4ac64eec84c338d20a3265a7218af96e8 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 24 Aug 2022 00:25:52 -0400 Subject: [PATCH 10/12] Fixed parsing of interface section behaviors --- examples/full/main.arf | 2 +- parser/face.go | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/full/main.arf b/examples/full/main.arf index 8990b62..9db675a 100644 --- a/examples/full/main.arf +++ b/examples/full/main.arf @@ -9,7 +9,7 @@ data pv helloText:String "Hello, world!" # this is a struct definition objt ro Greeter:Obj - wr text:String "Hi." + rw text:String "Hi." # this is a function func ro main diff --git a/parser/face.go b/parser/face.go index a6b96eb..d0e1b64 100644 --- a/parser/face.go +++ b/parser/face.go @@ -34,7 +34,7 @@ func (parser *ParsingOperation) parseFaceSection () ( if err != nil { return } section.inherits = parser.token.Value().(string) if err != nil { return } - err = parser.expect(lexer.TokenKindNewline) + err = parser.nextToken(lexer.TokenKindNewline) if err != nil { return } err = parser.nextToken() if err != nil { return } @@ -46,8 +46,6 @@ func (parser *ParsingOperation) parseFaceSection () ( if parser.token.Value().(int) != 1 { return } // parse behavior - err = parser.nextToken(lexer.TokenKindName) - if err != nil { return } behaviorBeginning := parser.token.Location() var behavior FaceBehavior behavior, err = parser.parseFaceBehavior() @@ -74,18 +72,21 @@ func (parser *ParsingOperation) parseFaceBehavior () ( behavior FaceBehavior, err error, ) { + err = parser.expect(lexer.TokenKindIndent) + if err != nil { return } + // get name err = parser.nextToken(lexer.TokenKindName) if err != nil { return } behavior.name = parser.token.Value().(string) + err = parser.nextToken(lexer.TokenKindNewline) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + for { - err = parser.nextToken(lexer.TokenKindNewline) - if err != nil { return } - // if we've left the block, stop parsing - err = parser.nextToken() - if err != nil { return } if !parser.token.Is(lexer.TokenKindIndent) { return } if parser.token.Value().(int) != 2 { return } From 08935d69c0a300dc8661eec67bee0ef12d64360a Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 24 Aug 2022 00:52:37 -0400 Subject: [PATCH 11/12] Parser actually adds interface behavior to interface --- parser/face.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/parser/face.go b/parser/face.go index d0e1b64..3a53381 100644 --- a/parser/face.go +++ b/parser/face.go @@ -60,6 +60,7 @@ func (parser *ParsingOperation) parseFaceSection () ( infoerr.ErrorKindError) return } + section.behaviors[behavior.name] = behavior if err != nil { return } } @@ -121,8 +122,8 @@ func (parser *ParsingOperation) parseFaceBehavior () ( behavior.inputs, declaration) } else { - behavior.inputs = append ( - behavior.inputs, + behavior.outputs = append ( + behavior.outputs, declaration) } } From 0b80a55f798e21a6c72b3924d120034ffebd9a3f Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 24 Aug 2022 00:53:42 -0400 Subject: [PATCH 12/12] Repaired output formatting of interface section --- parser/tree-tostring.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 832c3a0..df8a9b1 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -378,11 +378,11 @@ func (behavior *FaceBehavior) ToString (indent int) (output string) { output += doIndent(indent, behavior.name, "\n") for _, inputItem := range behavior.inputs { - output += doIndent(indent, "> ", inputItem.ToString(), "\n") + output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n") } for _, outputItem := range behavior.outputs { - output += doIndent(indent, "< ", outputItem.ToString(), "\n") + output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n") } return