diff --git a/parser/body.go b/parser/body.go index 82b2635..a5bf767 100644 --- a/parser/body.go +++ b/parser/body.go @@ -40,6 +40,14 @@ func (parser *ParsingOperation) parseBody () (err error) { if err != nil { return } case "face": case "enum": + var section *EnumSection + section, err = parser.parseEnumSection() + if parser.tree.enumSections == nil { + parser.tree.enumSections = + make(map[string] *EnumSection) + } + parser.tree.enumSections[section.name] = section + if err != nil { return } case "func": default: err = parser.token.NewError ( diff --git a/parser/enum.go b/parser/enum.go new file mode 100644 index 0000000..139cd9f --- /dev/null +++ b/parser/enum.go @@ -0,0 +1,94 @@ +package parser + +import "git.tebibyte.media/sashakoshka/arf/types" +import "git.tebibyte.media/sashakoshka/arf/lexer" +import "git.tebibyte.media/sashakoshka/arf/infoerr" + +func (parser *ParsingOperation) parseEnumSection () ( + section *EnumSection, + err error, +) { + err = parser.expect(lexer.TokenKindName) + if err != nil { return } + + section = &EnumSection { + location: parser.token.Location(), + members: make(map[string] Argument), + } + + // 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.what, err = parser.parseType() + if err != nil { return } + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + + // parse members + err = parser.parseEnumMembers(section) + if err != nil { return } + + if len(section.members) == 0 { + infoerr.NewError ( + section.location, + "defining an enum with no members", + infoerr.ErrorKindWarn).Print() + } + return +} + +// parseEnumMembers parses a list of members for an enum section. Indentation +// level is assumed. +func (parser *ParsingOperation) parseEnumMembers ( + into *EnumSection, +) ( + 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 name + err = parser.nextToken(lexer.TokenKindName) + if err != nil { return } + name := parser.token.Value().(string) + err = parser.nextToken() + if err != nil { return } + + // parse default value + var argument Argument + if parser.token.Is(lexer.TokenKindNewline) { + err = parser.nextToken() + if err != nil { return } + + argument, err = parser.parseInitializationValues(1) + into.members[name] = argument + if err != nil { return } + } else { + argument, err = parser.parseArgument() + into.members[name] = argument + if err != nil { return } + + err = parser.expect(lexer.TokenKindNewline) + if err != nil { return } + err = parser.nextToken() + if err != nil { return } + } + } +} diff --git a/parser/parser_test.go b/parser/parser_test.go index d433d64..ca4b7a0 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -158,3 +158,37 @@ objt ro Init:Obj `, test) } +func TestEnum (test *testing.T) { + checkTree ("../tests/parser/enum", +`:arf +--- +enum ro AffrontToGod:{Int 4} + bird0 + 28394 + 9328 + 398 + 9 + bird1 + 23 + 932832 + 398 + 2349 + bird2 + 1 + 2 + 3 + 4 +enum ro NamedColor:U32 + blue 255 + green 65280 + red 16711680 +enum ro Weekday:Int + friday + monday + saturday + sunday + thursday + tuesday + wednesday +`, test) +} diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index d469ed3..8c67798 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -56,6 +56,11 @@ func (tree *SyntaxTree) ToString (indent int) (output string) { output += tree.objtSections[name].ToString(indent) } + enumSectionKeys := sortMapKeysAlphabetically(tree.enumSections) + for _, name := range enumSectionKeys { + output += tree.enumSections[name].ToString(indent) + } + dataSectionKeys := sortMapKeysAlphabetically(tree.dataSections) for _, name := range dataSectionKeys { output += tree.dataSections[name].ToString(indent) @@ -319,3 +324,32 @@ func (section *ObjtSection) ToString (indent int) (output string) { return } +func (section *EnumSection) ToString (indent int) (output string) { + output += doIndent ( + indent, + "enum ", + section.permission.ToString(), " ", + section.name, ":", + section.what.ToString(), "\n") + + for _, name := range sortMapKeysAlphabetically(section.members) { + output += doIndent(indent + 1, name) + + defaultValue := section.members[name] + + isComplexInitialization := + defaultValue.kind == ArgumentKindObjectInitializationValues || + defaultValue.kind == ArgumentKindArrayInitializationValues + + if defaultValue.value == nil { + output += "\n" + } else if isComplexInitialization { + output += "\n" + output += defaultValue.ToString(indent + 2, true) + } else { + output += " " + defaultValue.ToString(0, false) + output += "\n" + } + } + return +} diff --git a/parser/tree.go b/parser/tree.go index c1b5e74..559dbc8 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -13,6 +13,7 @@ type SyntaxTree struct { requires []string typeSections map[string] *TypeSection objtSections map[string] *ObjtSection + enumSections map[string] *EnumSection dataSections map[string] *DataSection } @@ -191,3 +192,14 @@ type ObjtSection struct { permission types.Permission members map[string] ObjtMember } + +// EnumSection represents an enumerated type section. +type EnumSection struct { + location file.Location + name string + + what Type + permission types.Permission + // TODO: order matters here we need to store these in an array + members map[string] Argument +} diff --git a/tests/parser/enum/main.arf b/tests/parser/enum/main.arf new file mode 100644 index 0000000..0571149 --- /dev/null +++ b/tests/parser/enum/main.arf @@ -0,0 +1,30 @@ +:arf +--- + +enum ro Weekday:Int + sunday + monday + tuesday + wednesday + thursday + friday + saturday + +enum ro NamedColor:U32 + red 0xFF0000 + green 0x00FF00 + blue 0x0000FF + +enum ro AffrontToGod:{Int 4} + bird0 + 28394 9328 + 398 9 + bird1 + 23 932832 + 398 + 2349 + bird2 + 1 + 2 + 3 + 4