From bd433fc65ddc7a1db9f1ffb271ce33ca32314732 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sat, 20 Aug 2022 13:26:24 -0400 Subject: [PATCH] Untested object section parsing --- parser/objt.go | 103 +++++++++++++++++++++++++++++++++++++ parser/type.go | 136 ++++--------------------------------------------- 2 files changed, 114 insertions(+), 125 deletions(-) create mode 100644 parser/objt.go diff --git a/parser/objt.go b/parser/objt.go new file mode 100644 index 0000000..1f70434 --- /dev/null +++ b/parser/objt.go @@ -0,0 +1,103 @@ +package parser + +import "git.tebibyte.media/sashakoshka/arf/types" +import "git.tebibyte.media/sashakoshka/arf/lexer" +import "git.tebibyte.media/sashakoshka/arf/infoerr" + +// parseObjtSection parses an object type definition. This allows for structured +// types to be defined, and for member variables to be added and overridden. +func (parser *ParsingOperation) parseObjtSection () ( + section *ObjtSection, + err error, +) { + err = parser.expect(lexer.TokenKindName) + if err != nil { return } + + section = &ObjtSection { location: parser.token.Location() } + + // 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 type + err = parser.nextToken(lexer.TokenKindColon) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + section.inherits, err = parser.parseType() + if err != nil { return } + err = parser.nextToken(lexer.TokenKindNewline) + if err != nil { return } + + // parse members + err = parser.parseObjtMembers(section) + + if len(section.members) == 0 { + infoerr.NewError ( + section.location, + "defining an object with no members", + infoerr.ErrorKindWarn).Print() + } + return +} + +func (parser *ParsingOperation) parseObjtMembers ( + into *ObjtSection, +) ( + err error, +) { + for { + // if we've left the block, stop parsing + if !parser.token.Is(lexer.TokenKindIndent) { return } + if parser.token.Value().(int) != 1 { return } + + // get permission + err = parser.nextToken(lexer.TokenKindPermission) + if err != nil { return } + member := ObjtMember { } + member.permission = parser.token.Value().(types.Permission) + + // get 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() + if err != nil { return } + member.what, err = parser.parseType() + if err != nil { return } + + // parse default value + if parser.token.Is(lexer.TokenKindNewline) { + err = parser.nextToken() + if err != nil { return } + + member.defaultValue, + err = parser.parseInitializationValues(1) + if err != nil { return } + } else { + member.defaultValue, err = parser.parseArgument() + if err != nil { return } + + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + } + + // go onto the next line + err = parser.nextToken(lexer.TokenKindNewline) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + } +} diff --git a/parser/type.go b/parser/type.go index a954396..9691dcf 100644 --- a/parser/type.go +++ b/parser/type.go @@ -2,9 +2,10 @@ package parser import "git.tebibyte.media/sashakoshka/arf/types" import "git.tebibyte.media/sashakoshka/arf/lexer" -import "git.tebibyte.media/sashakoshka/arf/infoerr" +// import "git.tebibyte.media/sashakoshka/arf/infoerr" -// parseTypeSection parses a type definition. +// parseTypeSection parses a blind type definition, meaning it can inherit from +// anything including primitives, but cannot define structure. func (parser *ParsingOperation) parseTypeSection () ( section *TypeSection, err error, @@ -14,50 +15,33 @@ func (parser *ParsingOperation) parseTypeSection () ( section = &TypeSection { location: parser.token.Location() } - // parse root node - err = parser.nextToken() - if err != nil { return } - section.root, err = parser.parseTypeNode(0) - - return -} - -// parseTypeNode parses a single type definition node recursively. -func (parser *ParsingOperation) parseTypeNode ( - baseIndent int, -) ( - node TypeNode, - err error, -) { - node.children = make(map[string] TypeNode) - // get permission - err = parser.expect(lexer.TokenKindPermission) + err = parser.nextToken(lexer.TokenKindPermission) if err != nil { return } - node.permission = parser.token.Value().(types.Permission) + section.permission = parser.token.Value().(types.Permission) // get name err = parser.nextToken(lexer.TokenKindName) if err != nil { return } - node.name = parser.token.Value().(string) + section.name = parser.token.Value().(string) - // get inherited type + // parse inherited type err = parser.nextToken(lexer.TokenKindColon) if err != nil { return } err = parser.nextToken() if err != nil { return } - node.what, err = parser.parseType() + section.inherits, err = parser.parseType() if err != nil { return } - // get value, or child nodes + // parse default values if parser.token.Is(lexer.TokenKindNewline) { err = parser.nextToken() if err != nil { return } - err = parser.parseTypeNodeBlock(baseIndent, &node) + section.defaultValue, err = parser.parseInitializationValues(0) if err != nil { return } } else { - node.defaultValue, err = parser.parseArgument() + section.defaultValue, err = parser.parseArgument() if err != nil { return } err = parser.expect(lexer.TokenKindNewline) @@ -67,101 +51,3 @@ func (parser *ParsingOperation) parseTypeNode ( } return } - -// parseTypeNodeBlock starts on the line after a type node, and parses what -// could be either an array initialization, an object initialization, or more -// child nodes. It is similar to parseInitializationValues. If none of these -// things were found the parser stays at the beginning of the line and the -// method returns. -func (parser *ParsingOperation) parseTypeNodeBlock ( - baseIndent int, - parent *TypeNode, -) ( - err error, -) { - // check if line is indented one more than baseIndent - if !parser.token.Is(lexer.TokenKindIndent) { return } - if parser.token.Value().(int) != baseIndent + 1 { return } - - thingLocation := parser.token.Location() - - err = parser.nextToken() - if err != nil { return } - - if parser.token.Is(lexer.TokenKindDot) { - - // object initialization - parser.previousToken() - initializationArgument := Argument { location: thingLocation } - var initializationValues ObjectInitializationValues - initializationValues, err = parser.parseObjectInitializationValues() - initializationArgument.kind = ArgumentKindObjectInitializationValues - initializationArgument.value = &initializationValues - parent.defaultValue = initializationArgument - - } else if parser.token.Is(lexer.TokenKindPermission) { - - // child members - parser.previousToken() - err = parser.parseTypeNodeChildren(parent) - - } else { - - // array initialization - parser.previousToken() - initializationArgument := Argument { location: thingLocation } - var initializationValues ArrayInitializationValues - initializationValues, err = parser.parseArrayInitializationValues() - initializationArgument.kind = ArgumentKindArrayInitializationValues - initializationArgument.value = &initializationValues - parent.defaultValue = initializationArgument - } - - return -} - -// parseTypeNodeChildren parses child type nodes into a parent type node. -func (parser *ParsingOperation) parseTypeNodeChildren ( - parent *TypeNode, -) ( - err error, -) { - baseIndent := 0 - begin := true - - for { - // if there is no indent we can just stop parsing - if !parser.token.Is(lexer.TokenKindIndent) { break } - indent := parser.token.Value().(int) - - if begin == true { - baseIndent = indent - begin = false - } - - // do not parse any further if the indent has changed - if indent != baseIndent { break } - - // move on to the beginning of the line, which must contain - // a type node - err = parser.nextToken() - if err != nil { return } - var child TypeNode - child, err = parser.parseTypeNode(baseIndent) - - // if the member has already been listed, throw an error - _, exists := parent.children[child.name] - if exists { - err = parser.token.NewError ( - "duplicate member \"" + child.name + - "\" in object member initialization", - infoerr.ErrorKindError) - return - } - - // store in parent - parent.children[child.name] = child - } - - return -}