Merge pull request 'type-section' (#4) from type-section into main

Reviewed-on: sashakoshka/arf#4
This commit is contained in:
Sasha Koshka 2022-08-20 02:06:44 +00:00
commit 018499310c
7 changed files with 292 additions and 6 deletions

View File

@ -21,6 +21,14 @@ func (parser *ParsingOperation) parseBody () (err error) {
parser.tree.dataSections[section.name] = section
if err != nil { return }
case "type":
var section *TypeSection
section, err = parser.parseTypeSection()
if parser.tree.typeSections == nil {
parser.tree.typeSections =
make(map[string] *TypeSection)
}
parser.tree.typeSections[section.root.name] = section
if err != nil { return }
case "face":
case "enum":
case "func":

View File

@ -94,9 +94,6 @@ func (parser *ParsingOperation) parseObjectInitializationValues () (
initializationValues ObjectInitializationValues,
err error,
) {
println("BEGIN")
defer println("END")
initializationValues.attributes = make(map[string] Argument)
baseIndent := 0
@ -116,8 +113,6 @@ func (parser *ParsingOperation) parseObjectInitializationValues () (
// do not parse any further if the indent has changed
if indent != baseIndent { break }
println("HIT")
// move on to the beginning of the line, which must contain
// a member initialization value
err = parser.nextToken(lexer.TokenKindDot)

View File

@ -109,3 +109,31 @@ data ro object:Obj
`, test)
}
func TestType (test *testing.T) {
checkTree ("../tests/parser/type",
`:arf
---
type ro Basic:Int
type ro BasicInit:Int 6
type ro Complex:Obj
ro that:Basic
ro this:Basic
type ro ComplexInit:Obj
ro that:BasicInit
ro this:Basic 23
type ro ComplexWithComplexInit:Obj
ro basic:Basic 87
ro complex0:Complex
.that 98
.this 2
ro complex1:Complex
.that 98902
.this 235
type ro IntArray:{Int ..}
type ro IntArrayInit:{Int 3}
3298
923
92
`, test)
}

View File

@ -46,6 +46,11 @@ func (tree *SyntaxTree) ToString (indent int) (output string) {
output += doIndent(indent, "---\n")
typeSectionKeys := sortMapKeysAlphabetically(tree.typeSections)
for _, name := range typeSectionKeys {
output += tree.typeSections[name].ToString(indent)
}
dataSectionKeys := sortMapKeysAlphabetically(tree.dataSections)
for _, name := range dataSectionKeys {
output += tree.dataSections[name].ToString(indent)
@ -246,3 +251,41 @@ func (section *DataSection) ToString (indent int) (output string) {
}
return
}
func (section *TypeSection) ToString (indent int) (output string) {
output += section.root.ToString(indent, true)
return
}
func (node TypeNode) ToString (indent int, isRoot bool) (output string) {
output += doIndent(indent)
if isRoot {
output += "type "
}
output += node.permission.ToString() + " "
output += node.name + ":"
output += node.what.ToString()
isComplexInitialization :=
node.defaultValue.kind == ArgumentKindObjectInitializationValues ||
node.defaultValue.kind == ArgumentKindArrayInitializationValues
if node.defaultValue.value == nil {
output += "\n"
if len(node.children) > 0 {
for _, name := range sortMapKeysAlphabetically(node.children) {
child := node.children[name]
output += child.ToString(indent + 1, false)
}
}
} else if isComplexInitialization {
output += "\n"
output += node.defaultValue.ToString(indent + 1, true)
} else {
output += " " + node.defaultValue.ToString(0, false)
output += "\n"
}
return
}

View File

@ -11,6 +11,7 @@ type SyntaxTree struct {
author string
requires []string
typeSections map[string] *TypeSection
dataSections map[string] *DataSection
}
@ -156,6 +157,23 @@ type DataSection struct {
name string
what Type
value Argument
permission types.Permission
value Argument
}
// TypeNode represents a part of a type.
type TypeNode struct {
location file.Location
name string
what Type
permission types.Permission
defaultValue Argument
children map[string] TypeNode
}
// TypeSection represents a type definition.
type TypeSection struct {
location file.Location
root TypeNode
}

167
parser/type.go Normal file
View File

@ -0,0 +1,167 @@
package parser
import "git.tebibyte.media/sashakoshka/arf/types"
import "git.tebibyte.media/sashakoshka/arf/lexer"
import "git.tebibyte.media/sashakoshka/arf/infoerr"
// parseTypeSection parses a type definition.
func (parser *ParsingOperation) parseTypeSection () (
section *TypeSection,
err error,
) {
err = parser.expect(lexer.TokenKindName)
if err != nil { return }
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)
if err != nil { return }
node.permission = parser.token.Value().(types.Permission)
// get name
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
node.name = parser.token.Value().(string)
// get inherited type
err = parser.nextToken(lexer.TokenKindColon)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
node.what, err = parser.parseType()
if err != nil { return }
// get value, or child nodes
if parser.token.Is(lexer.TokenKindNewline) {
err = parser.nextToken()
if err != nil { return }
err = parser.parseTypeNodeBlock(baseIndent, &node)
if err != nil { return }
} else {
node.defaultValue, err = parser.parseArgument()
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
}
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
}

View File

@ -0,0 +1,27 @@
:arf
---
type ro Basic:Int
type ro BasicInit:Int 6
type ro IntArray:{Int ..}
type ro IntArrayInit:{Int 3}
3298 923 92
type ro Complex:Obj
ro that:Basic
ro this:Basic
type ro ComplexInit:Obj
ro that:BasicInit
ro this:Basic 23
type ro ComplexWithComplexInit:Obj
ro complex0:Complex
.that 98
.this 2
ro complex1:Complex
.that 98902
.this 235
ro basic:Basic 87