syntax-tree-accessors #2
276
parser/accessors.go
Normal file
276
parser/accessors.go
Normal file
|
@ -0,0 +1,276 @@
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import "git.tebibyte.media/arf/arf/types"
|
||||||
|
|
||||||
|
// LookupSection looks returns the section under the give name. If the section
|
||||||
|
// does not exist, nil is returned.
|
||||||
|
func (tree SyntaxTree) LookupSection (name string) (section Section) {
|
||||||
|
section = tree.sections[name]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sections returns an iterator for the tree's sections
|
||||||
|
func (tree SyntaxTree) Sections () (iterator types.Iterator[Section]) {
|
||||||
|
iterator = types.NewIterator(tree.sections)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the section's kind (SectionKindType).
|
||||||
|
func (section TypeSection) Kind () (kind SectionKind) {
|
||||||
|
kind = SectionKindType
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the section's kind (SectionKindObjt).
|
||||||
|
func (section ObjtSection) Kind () (kind SectionKind) {
|
||||||
|
kind = SectionKindObjt
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the section's kind (SectionKindEnum).
|
||||||
|
func (section EnumSection) Kind () (kind SectionKind) {
|
||||||
|
kind = SectionKindEnum
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the section's kind (SectionKindFace).
|
||||||
|
func (section FaceSection) Kind () (kind SectionKind) {
|
||||||
|
kind = SectionKindFace
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the section's kind (SectionKindData).
|
||||||
|
func (section DataSection) Kind () (kind SectionKind) {
|
||||||
|
kind = SectionKindData
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the section's kind (SectionKindFunc).
|
||||||
|
func (section FuncSection) Kind () (kind SectionKind) {
|
||||||
|
kind = SectionKindFunc
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the amount of names in the identifier.
|
||||||
|
func (identifier Identifier) Length () (length int) {
|
||||||
|
length = len(identifier.trail)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item returns the name at the specified index.
|
||||||
|
func (identifier Identifier) Item (index int) (item string) {
|
||||||
|
item = identifier.trail[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns the type's kind.
|
||||||
|
func (what Type) Kind () (kind TypeKind) {
|
||||||
|
kind = what.kind
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutable returns whether or not the type's data is mutable.
|
||||||
|
func (what Type) Mutable () (mutable bool) {
|
||||||
|
mutable = what.mutable
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the length of the type if the type is a fixed length array.
|
||||||
|
// Otherwise, it just returns zero.
|
||||||
|
func (what Type) Length () (length uint64) {
|
||||||
|
if what.kind == TypeKindArray {
|
||||||
|
length = what.length
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the type, if it is a basic type. Otherwise, it
|
||||||
|
// returns a zero value identifier.
|
||||||
|
func (what Type) Name () (name Identifier) {
|
||||||
|
if what.kind == TypeKindBasic {
|
||||||
|
name = what.name
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Points returns the type that this type points to, or is an array of. If the
|
||||||
|
// type is a basic type, this returns a zero value type.
|
||||||
|
func (what Type) Points () (points Type) {
|
||||||
|
if what.kind != TypeKindBasic {
|
||||||
|
points = *what.points
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns an iterator for the initialization values.
|
||||||
|
func (values ObjectInitializationValues) Sections () (
|
||||||
|
iterator types.Iterator[Argument],
|
||||||
|
) {
|
||||||
|
iterator = types.NewIterator(values.attributes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the amount of values.
|
||||||
|
func (values ArrayInitializationValues) Length () (length int) {
|
||||||
|
length = len(values.values)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item returns the value at index.
|
||||||
|
func (values ArrayInitializationValues) Value (index int) (value Argument) {
|
||||||
|
value = values.values[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns what kind of argument it is.
|
||||||
|
func (argument Argument) Kind () (kind ArgumentKind) {
|
||||||
|
kind = argument.kind
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the underlying value of the argument. You can use Kind() to
|
||||||
|
// find out what to cast this to.
|
||||||
|
func (argument Argument) Value () (value any) {
|
||||||
|
value = argument.value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitWidth returns the bit width of the object member. If it is zero, it should
|
||||||
|
// be treated as unspecified.
|
||||||
|
func (member ObjtMember) BitWidth () (width uint64) {
|
||||||
|
width = member.bitWidth
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the amount of members in the section.
|
||||||
|
func (section ObjtSection) Length () (length int) {
|
||||||
|
length = len(section.members)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item returns the member at index.
|
||||||
|
func (section ObjtSection) Item (index int) (member ObjtMember) {
|
||||||
|
member = section.members[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the amount of members in the section.
|
||||||
|
func (section EnumSection) Length () (length int) {
|
||||||
|
length = len(section.members)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item returns the member at index.
|
||||||
|
func (section EnumSection) Item (index int) (member EnumMember) {
|
||||||
|
member = section.members[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// InputsLength returns the amount of inputs in the behavior.
|
||||||
|
func (behavior FaceBehavior) IntputsLength () (length int) {
|
||||||
|
length = len(behavior.inputs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input returns the input at index.
|
||||||
|
func (behavior FaceBehavior) Input (index int) (input Declaration) {
|
||||||
|
input = behavior.inputs[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputsLength returns the amount of outputs in the behavior.
|
||||||
|
func (behavior FaceBehavior) OutputsLength () (length int) {
|
||||||
|
length = len(behavior.outputs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output returns the output at index.
|
||||||
|
func (behavior FaceBehavior) Output (index int) (output Declaration) {
|
||||||
|
output = behavior.outputs[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Behaviors returns an iterator for the interface's behaviors.
|
||||||
|
func (section FaceSection) Behaviors () (iterator types.Iterator[FaceBehavior]) {
|
||||||
|
iterator = types.NewIterator(section.behaviors)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kind returns what kind of phrase it is.
|
||||||
|
func (phrase Phrase) Kind () (kind PhraseKind) {
|
||||||
|
kind = phrase.kind
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReturnsToLength returns the amount of things the phrase returns to.
|
||||||
|
func (phrase Phrase) ReturnsToLength () (length int) {
|
||||||
|
length = len(phrase.returnsTo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReturnTo returns the thing alskdjaslkdjsa whatever i dont even know wtf.
|
||||||
|
func (phrase Phrase) ReturnTo (index int) (returnTo Argument) {
|
||||||
|
returnTo = phrase.returnsTo[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block returns the block under the phrase, if it is a control flow statement.
|
||||||
|
func (phrase Phrase) Block () (block Block) {
|
||||||
|
block = phrase.block
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receiver returns the method receiver, if there is one. Otherwise, it returns
|
||||||
|
// nil.
|
||||||
|
func (section FuncSection) Receiver () (receiver *Declaration) {
|
||||||
|
receiver = section.receiver
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// InputsLength returns the number of inputs in the function.
|
||||||
|
func (section FuncSection) InputsLength () (length int) {
|
||||||
|
length = len(section.inputs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input returns the input at index.
|
||||||
|
func (section FuncSection) Input (index int) (input Declaration) {
|
||||||
|
input = section.inputs[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputsLength returns the number of outputs in the function.
|
||||||
|
func (section FuncSection) OutputsLength () (length int) {
|
||||||
|
length = len(section.outputs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output returns the output at index.
|
||||||
|
func (section FuncSection) Output (index int) (output FuncOutput) {
|
||||||
|
output = section.outputs[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root returns the root block of the section.
|
||||||
|
func (section FuncSection) Root () (root Block) {
|
||||||
|
root = section.root
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// External returns whether or not the function is an external function or not.
|
||||||
|
func (section FuncSection) External () (external bool) {
|
||||||
|
external = section.external
|
||||||
|
return
|
||||||
|
}
|
|
@ -41,13 +41,15 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error)
|
||||||
infoerr.ErrorKindError)
|
infoerr.ErrorKindError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declaration := Declaration { }
|
||||||
|
declaration.what = what
|
||||||
|
declaration.name = identifier.trail[0]
|
||||||
|
declaration.location = argument.Location()
|
||||||
|
|
||||||
argument.kind = ArgumentKindDeclaration
|
argument.kind = ArgumentKindDeclaration
|
||||||
argument.value = Declaration {
|
argument.value = declaration
|
||||||
location: argument.location,
|
|
||||||
name: identifier.trail[0],
|
|
||||||
what: what,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
argument.kind = ArgumentKindIdentifier
|
argument.kind = ArgumentKindIdentifier
|
||||||
argument.value = identifier
|
argument.value = identifier
|
||||||
|
|
|
@ -8,63 +8,45 @@ func (parser *ParsingOperation) parseBody () (err error) {
|
||||||
for {
|
for {
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
sectionType := parser.token.Value().(string)
|
sectionType := parser.token.Value().(string)
|
||||||
|
|
||||||
switch sectionType {
|
switch sectionType {
|
||||||
case "data":
|
case "data":
|
||||||
var section *DataSection
|
section, parseErr := parser.parseDataSection()
|
||||||
section, err = parser.parseDataSection()
|
err = parser.tree.addSection(section)
|
||||||
if parser.tree.dataSections == nil {
|
if err != nil { return }
|
||||||
parser.tree.dataSections =
|
if parseErr != nil { return }
|
||||||
make(map[string] *DataSection)
|
|
||||||
}
|
|
||||||
parser.tree.dataSections[section.name] = section
|
|
||||||
if err != nil { return }
|
|
||||||
case "type":
|
case "type":
|
||||||
var section *TypeSection
|
section, parseErr := parser.parseTypeSection()
|
||||||
section, err = parser.parseTypeSection()
|
err = parser.tree.addSection(section)
|
||||||
if parser.tree.typeSections == nil {
|
if err != nil { return }
|
||||||
parser.tree.typeSections =
|
if parseErr != nil { return }
|
||||||
make(map[string] *TypeSection)
|
|
||||||
}
|
|
||||||
parser.tree.typeSections[section.name] = section
|
|
||||||
if err != nil { return }
|
|
||||||
case "objt":
|
case "objt":
|
||||||
var section *ObjtSection
|
section, parseErr := parser.parseObjtSection()
|
||||||
section, err = parser.parseObjtSection()
|
err = parser.tree.addSection(section)
|
||||||
if parser.tree.objtSections == nil {
|
if err != nil { return }
|
||||||
parser.tree.objtSections =
|
if parseErr != nil { return }
|
||||||
make(map[string] *ObjtSection)
|
|
||||||
}
|
|
||||||
parser.tree.objtSections[section.name] = section
|
|
||||||
if err != nil { return }
|
|
||||||
case "face":
|
case "face":
|
||||||
var section *FaceSection
|
section, parseErr := parser.parseFaceSection()
|
||||||
section, err = parser.parseFaceSection()
|
err = parser.tree.addSection(section)
|
||||||
if parser.tree.faceSections == nil {
|
if err != nil { return }
|
||||||
parser.tree.faceSections =
|
if parseErr != nil { return }
|
||||||
make(map[string] *FaceSection)
|
|
||||||
}
|
|
||||||
parser.tree.faceSections[section.name] = section
|
|
||||||
if err != nil { return }
|
|
||||||
case "enum":
|
case "enum":
|
||||||
var section *EnumSection
|
section, parseErr := parser.parseEnumSection()
|
||||||
section, err = parser.parseEnumSection()
|
err = parser.tree.addSection(section)
|
||||||
if parser.tree.enumSections == nil {
|
if err != nil { return }
|
||||||
parser.tree.enumSections =
|
if parseErr != nil { return }
|
||||||
make(map[string] *EnumSection)
|
|
||||||
}
|
|
||||||
parser.tree.enumSections[section.name] = section
|
|
||||||
if err != nil { return }
|
|
||||||
case "func":
|
case "func":
|
||||||
var section *FuncSection
|
section, parseErr := parser.parseFuncSection()
|
||||||
section, err = parser.parseFuncSection()
|
err = parser.tree.addSection(section)
|
||||||
if parser.tree.funcSections == nil {
|
if err != nil { return }
|
||||||
parser.tree.funcSections =
|
if parseErr != nil { return }
|
||||||
make(map[string] *FuncSection)
|
|
||||||
}
|
|
||||||
parser.tree.funcSections[section.name] = section
|
|
||||||
if err != nil { return }
|
|
||||||
default:
|
default:
|
||||||
err = parser.token.NewError (
|
err = parser.token.NewError (
|
||||||
"unknown section type \"" + sectionType + "\"",
|
"unknown section type \"" + sectionType + "\"",
|
||||||
|
@ -73,3 +55,18 @@ func (parser *ParsingOperation) parseBody () (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addSection adds a section to the tree, ensuring it has a unique name within
|
||||||
|
// the module.
|
||||||
|
func (tree *SyntaxTree) addSection (section Section) (err error) {
|
||||||
|
_, exists := tree.sections[section.Name()]
|
||||||
|
if exists {
|
||||||
|
err = section.NewError (
|
||||||
|
"cannot have multiple sections with the same name",
|
||||||
|
infoerr.ErrorKindError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.sections[section.Name()] = section
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@ import "git.tebibyte.media/arf/arf/lexer"
|
||||||
|
|
||||||
// parseData parses a data section.
|
// parseData parses a data section.
|
||||||
func (parser *ParsingOperation) parseDataSection () (
|
func (parser *ParsingOperation) parseDataSection () (
|
||||||
section *DataSection,
|
section DataSection,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section = &DataSection { location: parser.token.Location() }
|
section.location = parser.token.Location()
|
||||||
|
|
||||||
err = parser.nextToken(lexer.TokenKindPermission)
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
|
@ -4,14 +4,15 @@ import "git.tebibyte.media/arf/arf/types"
|
||||||
import "git.tebibyte.media/arf/arf/lexer"
|
import "git.tebibyte.media/arf/arf/lexer"
|
||||||
import "git.tebibyte.media/arf/arf/infoerr"
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
|
// parseEnumSection parses an enumerated type section.
|
||||||
func (parser *ParsingOperation) parseEnumSection () (
|
func (parser *ParsingOperation) parseEnumSection () (
|
||||||
section *EnumSection,
|
section EnumSection,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section = &EnumSection { location: parser.token.Location() }
|
section.location = parser.token.Location()
|
||||||
|
|
||||||
// get permission
|
// get permission
|
||||||
err = parser.nextToken(lexer.TokenKindPermission)
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
|
@ -36,7 +37,7 @@ func (parser *ParsingOperation) parseEnumSection () (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
// parse members
|
// parse members
|
||||||
err = parser.parseEnumMembers(section)
|
err = parser.parseEnumMembers(§ion)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
if len(section.members) == 0 {
|
if len(section.members) == 0 {
|
||||||
|
|
|
@ -6,16 +6,14 @@ import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
// parseFaceSection parses an interface section.
|
// parseFaceSection parses an interface section.
|
||||||
func (parser *ParsingOperation) parseFaceSection () (
|
func (parser *ParsingOperation) parseFaceSection () (
|
||||||
section *FaceSection,
|
section FaceSection,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section = &FaceSection {
|
section.behaviors = make(map[string] FaceBehavior)
|
||||||
location: parser.token.Location(),
|
section.location = parser.token.Location()
|
||||||
behaviors: make(map[string] FaceBehavior),
|
|
||||||
}
|
|
||||||
|
|
||||||
// get permission
|
// get permission
|
||||||
err = parser.nextToken(lexer.TokenKindPermission)
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
|
|
|
@ -6,13 +6,13 @@ import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
// parseFunc parses a function section.
|
// parseFunc parses a function section.
|
||||||
func (parser *ParsingOperation) parseFuncSection () (
|
func (parser *ParsingOperation) parseFuncSection () (
|
||||||
section *FuncSection,
|
section FuncSection,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section = &FuncSection { location: parser.token.Location() }
|
section.location = parser.token.Location()
|
||||||
|
|
||||||
// get permission
|
// get permission
|
||||||
err = parser.nextToken(lexer.TokenKindPermission)
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
|
@ -29,7 +29,7 @@ func (parser *ParsingOperation) parseFuncSection () (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.parseFuncArguments(section)
|
err = parser.parseFuncArguments(§ion)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
// check to see if the function is external
|
// check to see if the function is external
|
||||||
|
@ -185,12 +185,12 @@ func (parser *ParsingOperation) parseFuncArguments (
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
output.defaultValue, err =
|
output.value, err =
|
||||||
parser.parseInitializationValues(1)
|
parser.parseInitializationValues(1)
|
||||||
into.outputs = append(into.outputs, output)
|
into.outputs = append(into.outputs, output)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
} else {
|
} else {
|
||||||
output.defaultValue, err =
|
output.value, err =
|
||||||
parser.parseArgument()
|
parser.parseArgument()
|
||||||
into.outputs = append(into.outputs, output)
|
into.outputs = append(into.outputs, output)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
|
@ -3,6 +3,29 @@ package parser
|
||||||
import "git.tebibyte.media/arf/arf/lexer"
|
import "git.tebibyte.media/arf/arf/lexer"
|
||||||
import "git.tebibyte.media/arf/arf/infoerr"
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
|
// TODO: need to come up with another syntax for bitfields, and use that syntax
|
||||||
|
// for fixed-length arrays. the problem is, we cant use {} for those kinds of
|
||||||
|
// arrays because they aren't pointers under the hood and that goes against the
|
||||||
|
// arf design goals in a nasty ugly way, and not only that. but the :mut type
|
||||||
|
// qualifier is meaningless on fixed length arrays now. the bit field syntax
|
||||||
|
// solves both of these problems very gracefully. but now, the problem is coming
|
||||||
|
// up with new bit field syntax. implementing this change is extremely
|
||||||
|
// necessary, for it will supercharge the coherency of the language and make it
|
||||||
|
// way more awesome.
|
||||||
|
//
|
||||||
|
// this new syntax cannot conflict with arguments, so it cannot have any
|
||||||
|
// tokens that begin those. basically all symbol tokens are on the table here.
|
||||||
|
// some ideas:
|
||||||
|
//
|
||||||
|
// ro member:Type ~ 4
|
||||||
|
// ro member:Type & 4 <- i like this one because binary &. so intuitive.
|
||||||
|
// ro member:Type % 4
|
||||||
|
// ro member:Type | 4
|
||||||
|
// ro member:Type ! 4
|
||||||
|
// ro member:Type (4) <- this looks phenomenal, but it needs new tokens not
|
||||||
|
// used anywhere else, and it would be mildly annoying
|
||||||
|
// to parse.
|
||||||
|
|
||||||
// parseType parses a type notation of the form Name, {Name}, etc.
|
// parseType parses a type notation of the form Name, {Name}, etc.
|
||||||
func (parser *ParsingOperation) parseType () (what Type, err error) {
|
func (parser *ParsingOperation) parseType () (what Type, err error) {
|
||||||
err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace)
|
err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace)
|
||||||
|
@ -34,7 +57,7 @@ func (parser *ParsingOperation) parseType () (what Type, err error) {
|
||||||
err = parser.nextToken(lexer.TokenKindRBrace)
|
err = parser.nextToken(lexer.TokenKindRBrace)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
} else if parser.token.Is(lexer.TokenKindElipsis) {
|
} else if parser.token.Is(lexer.TokenKindElipsis) {
|
||||||
what.kind = TypeKindArray
|
what.kind = TypeKindVariableArray
|
||||||
|
|
||||||
err = parser.nextToken(lexer.TokenKindRBrace)
|
err = parser.nextToken(lexer.TokenKindRBrace)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
70
parser/node-traits.go
Normal file
70
parser/node-traits.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import "git.tebibyte.media/arf/arf/file"
|
||||||
|
import "git.tebibyte.media/arf/arf/types"
|
||||||
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
|
// locatable allows a tree node to have a location.
|
||||||
|
type locatable struct {
|
||||||
|
location file.Location
|
||||||
|
}
|
||||||
|
|
||||||
|
// Location returns the location of the node.
|
||||||
|
func (trait locatable) Location () (location file.Location) {
|
||||||
|
location = trait.location
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewError creates a new error at the node's location.
|
||||||
|
func (trait locatable) NewError (
|
||||||
|
message string,
|
||||||
|
kind infoerr.ErrorKind,
|
||||||
|
) (
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
err = infoerr.NewError(trait.location, message, kind)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// nameable allows a tree node to have a name.
|
||||||
|
type nameable struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the node.
|
||||||
|
func (trait nameable) Name () (name string) {
|
||||||
|
name = trait.name
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// typeable allows a node to have a type.
|
||||||
|
type typeable struct {
|
||||||
|
what Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the type of the node.
|
||||||
|
func (trait typeable) Type () (what Type) {
|
||||||
|
what = trait.what
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// permissionable allows a node to have a permission.
|
||||||
|
type permissionable struct {
|
||||||
|
permission types.Permission
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permission returns the permision of the node.
|
||||||
|
func (trait permissionable) Permission () (permission types.Permission) {
|
||||||
|
permission = trait.permission
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -7,13 +7,13 @@ import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
// parseObjtSection parses an object type definition. This allows for structured
|
// parseObjtSection parses an object type definition. This allows for structured
|
||||||
// types to be defined, and for member variables to be added and overridden.
|
// types to be defined, and for member variables to be added and overridden.
|
||||||
func (parser *ParsingOperation) parseObjtSection () (
|
func (parser *ParsingOperation) parseObjtSection () (
|
||||||
section *ObjtSection,
|
section ObjtSection,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section = &ObjtSection { location: parser.token.Location() }
|
section.location = parser.token.Location()
|
||||||
|
|
||||||
// get permission
|
// get permission
|
||||||
err = parser.nextToken(lexer.TokenKindPermission)
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
|
@ -38,7 +38,7 @@ func (parser *ParsingOperation) parseObjtSection () (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
// parse members
|
// parse members
|
||||||
err = parser.parseObjtMembers(section)
|
err = parser.parseObjtMembers(§ion)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
if len(section.members) == 0 {
|
if len(section.members) == 0 {
|
||||||
|
@ -108,11 +108,11 @@ func (parser *ParsingOperation) parseObjtMember () (
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
member.defaultValue,
|
member.value,
|
||||||
err = parser.parseInitializationValues(1)
|
err = parser.parseInitializationValues(1)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
} else {
|
} else {
|
||||||
member.defaultValue, err = parser.parseArgument()
|
member.value, err = parser.parseArgument()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
err = parser.expect(lexer.TokenKindNewline)
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
|
|
@ -14,13 +14,25 @@ type ParsingOperation struct {
|
||||||
tokens []lexer.Token
|
tokens []lexer.Token
|
||||||
tokenIndex int
|
tokenIndex int
|
||||||
|
|
||||||
tree *SyntaxTree
|
tree SyntaxTree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - implement parser cache
|
||||||
|
// - have this try to hit the cache, and actually parse on miss
|
||||||
|
// - rename this to Fetch
|
||||||
|
// - add `skim bool` argument. when this is true, don't parse any code or data
|
||||||
|
// section initialization values, just definitions and their default values.
|
||||||
|
|
||||||
// Parse reads the files located in the module specified by modulePath, and
|
// Parse reads the files located in the module specified by modulePath, and
|
||||||
// converts them into an abstract syntax tree.
|
// converts them into an abstract syntax tree.
|
||||||
func Parse (modulePath string) (tree *SyntaxTree, err error) {
|
func Parse (modulePath string) (tree SyntaxTree, err error) {
|
||||||
parser := ParsingOperation { modulePath: modulePath }
|
parser := ParsingOperation {
|
||||||
|
modulePath: modulePath,
|
||||||
|
tree: SyntaxTree {
|
||||||
|
sections: make(map[string] Section),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
if parser.modulePath[len(parser.modulePath) - 1] != '/' {
|
if parser.modulePath[len(parser.modulePath) - 1] != '/' {
|
||||||
parser.modulePath += "/"
|
parser.modulePath += "/"
|
||||||
|
@ -54,9 +66,6 @@ func (parser *ParsingOperation) parse (sourceFile *file.File) (err error) {
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
// reset the parser
|
// reset the parser
|
||||||
if parser.tree == nil {
|
|
||||||
parser.tree = &SyntaxTree { }
|
|
||||||
}
|
|
||||||
if len(tokens) == 0 { return }
|
if len(tokens) == 0 { return }
|
||||||
parser.tokens = tokens
|
parser.tokens = tokens
|
||||||
parser.token = tokens[0]
|
parser.token = tokens[0]
|
||||||
|
|
|
@ -7,15 +7,6 @@ import "testing"
|
||||||
|
|
||||||
func checkTree (modulePath string, correct string, test *testing.T) {
|
func checkTree (modulePath string, correct string, test *testing.T) {
|
||||||
tree, err := Parse(modulePath)
|
tree, err := Parse(modulePath)
|
||||||
if tree == nil {
|
|
||||||
test.Log("TREE IS NIL!")
|
|
||||||
if err != io.EOF && err != nil {
|
|
||||||
test.Log("returned error:")
|
|
||||||
test.Log(err)
|
|
||||||
}
|
|
||||||
test.Fail()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
treeString := tree.ToString(0)
|
treeString := tree.ToString(0)
|
||||||
treeRunes := []rune(treeString)
|
treeRunes := []rune(treeString)
|
||||||
|
|
|
@ -30,7 +30,7 @@ func sortMapKeysAlphabetically[KEY_TYPE any] (
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tree *SyntaxTree) ToString (indent int) (output string) {
|
func (tree SyntaxTree) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, ":arf\n")
|
output += doIndent(indent, ":arf\n")
|
||||||
|
|
||||||
if tree.author != "" {
|
if tree.author != "" {
|
||||||
|
@ -47,35 +47,11 @@ func (tree *SyntaxTree) ToString (indent int) (output string) {
|
||||||
|
|
||||||
output += doIndent(indent, "---\n")
|
output += doIndent(indent, "---\n")
|
||||||
|
|
||||||
typeSectionKeys := sortMapKeysAlphabetically(tree.typeSections)
|
sectionKeys := sortMapKeysAlphabetically(tree.sections)
|
||||||
for _, name := range typeSectionKeys {
|
for _, name := range sectionKeys {
|
||||||
output += tree.typeSections[name].ToString(indent)
|
output += tree.sections[name].ToString(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
objtSectionKeys := sortMapKeysAlphabetically(tree.objtSections)
|
|
||||||
for _, name := range objtSectionKeys {
|
|
||||||
output += tree.objtSections[name].ToString(indent)
|
|
||||||
}
|
|
||||||
|
|
||||||
enumSectionKeys := sortMapKeysAlphabetically(tree.enumSections)
|
|
||||||
for _, name := range enumSectionKeys {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
funcSectionKeys := sortMapKeysAlphabetically(tree.funcSections)
|
|
||||||
for _, name := range funcSectionKeys {
|
|
||||||
output += tree.funcSections[name].ToString(indent)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +66,7 @@ func (identifier Identifier) ToString () (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (what *Type) ToString () (output string) {
|
func (what Type) ToString () (output string) {
|
||||||
if what.kind == TypeKindBasic {
|
if what.kind == TypeKindBasic {
|
||||||
output += what.name.ToString()
|
output += what.name.ToString()
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,12 +74,9 @@ func (what *Type) ToString () (output string) {
|
||||||
output += what.points.ToString()
|
output += what.points.ToString()
|
||||||
|
|
||||||
if what.kind == TypeKindArray {
|
if what.kind == TypeKindArray {
|
||||||
output += " "
|
output += fmt.Sprint(" ", what.length)
|
||||||
if what.length == 0 {
|
} else if what.kind == TypeKindVariableArray {
|
||||||
output += ".."
|
output += " .."
|
||||||
} else {
|
|
||||||
output += fmt.Sprint(what.length)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output += "}"
|
output += "}"
|
||||||
|
@ -154,7 +127,7 @@ func (values ArrayInitializationValues) ToString (
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (argument *Argument) ToString (indent int, breakLine bool) (output string) {
|
func (argument Argument) ToString (indent int, breakLine bool) (output string) {
|
||||||
if !breakLine { indent = 0 }
|
if !breakLine { indent = 0 }
|
||||||
if argument.kind == ArgumentKindNil {
|
if argument.kind == ArgumentKindNil {
|
||||||
output += "NIL-ARGUMENT"
|
output += "NIL-ARGUMENT"
|
||||||
|
@ -279,7 +252,7 @@ func (argument *Argument) ToString (indent int, breakLine bool) (output string)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (section *DataSection) ToString (indent int) (output string) {
|
func (section DataSection) ToString (indent int) (output string) {
|
||||||
output += doIndent (
|
output += doIndent (
|
||||||
indent,
|
indent,
|
||||||
"data ",
|
"data ",
|
||||||
|
@ -303,25 +276,25 @@ func (section *DataSection) ToString (indent int) (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (section *TypeSection) ToString (indent int) (output string) {
|
func (section TypeSection) ToString (indent int) (output string) {
|
||||||
output += doIndent (
|
output += doIndent (
|
||||||
indent,
|
indent,
|
||||||
"type ",
|
"type ",
|
||||||
section.permission.ToString(), " ",
|
section.permission.ToString(), " ",
|
||||||
section.name, ":",
|
section.name, ":",
|
||||||
section.inherits.ToString())
|
section.what.ToString())
|
||||||
|
|
||||||
isComplexInitialization :=
|
isComplexInitialization :=
|
||||||
section.defaultValue.kind == ArgumentKindObjectInitializationValues ||
|
section.value.kind == ArgumentKindObjectInitializationValues ||
|
||||||
section.defaultValue.kind == ArgumentKindArrayInitializationValues
|
section.value.kind == ArgumentKindArrayInitializationValues
|
||||||
|
|
||||||
if section.defaultValue.value == nil {
|
if section.value.value == nil {
|
||||||
output += "\n"
|
output += "\n"
|
||||||
} else if isComplexInitialization {
|
} else if isComplexInitialization {
|
||||||
output += "\n"
|
output += "\n"
|
||||||
output += section.defaultValue.ToString(indent + 1, true)
|
output += section.value.ToString(indent + 1, true)
|
||||||
} else {
|
} else {
|
||||||
output += " " + section.defaultValue.ToString(0, false)
|
output += " " + section.value.ToString(0, false)
|
||||||
output += "\n"
|
output += "\n"
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -339,23 +312,23 @@ func (member ObjtMember) ToString (indent int) (output string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
isComplexInitialization :=
|
isComplexInitialization :=
|
||||||
member.defaultValue.kind == ArgumentKindObjectInitializationValues ||
|
member.value.kind == ArgumentKindObjectInitializationValues ||
|
||||||
member.defaultValue.kind == ArgumentKindArrayInitializationValues
|
member.value.kind == ArgumentKindArrayInitializationValues
|
||||||
|
|
||||||
if member.defaultValue.value == nil {
|
if member.value.value == nil {
|
||||||
output += "\n"
|
output += "\n"
|
||||||
} else if isComplexInitialization {
|
} else if isComplexInitialization {
|
||||||
output += "\n"
|
output += "\n"
|
||||||
output += member.defaultValue.ToString(indent + 1, true)
|
output += member.value.ToString(indent + 1, true)
|
||||||
} else {
|
} else {
|
||||||
output += " " + member.defaultValue.ToString(0, false)
|
output += " " + member.value.ToString(0, false)
|
||||||
output += "\n"
|
output += "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (section *ObjtSection) ToString (indent int) (output string) {
|
func (section ObjtSection) ToString (indent int) (output string) {
|
||||||
output += doIndent (
|
output += doIndent (
|
||||||
indent,
|
indent,
|
||||||
"objt ",
|
"objt ",
|
||||||
|
@ -369,7 +342,7 @@ func (section *ObjtSection) ToString (indent int) (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (section *EnumSection) ToString (indent int) (output string) {
|
func (section EnumSection) ToString (indent int) (output string) {
|
||||||
output += doIndent (
|
output += doIndent (
|
||||||
indent,
|
indent,
|
||||||
"enum ",
|
"enum ",
|
||||||
|
@ -397,7 +370,7 @@ func (section *EnumSection) ToString (indent int) (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (section *FaceSection) ToString (indent int) (output string) {
|
func (section FaceSection) ToString (indent int) (output string) {
|
||||||
output += doIndent (
|
output += doIndent (
|
||||||
indent,
|
indent,
|
||||||
"face ",
|
"face ",
|
||||||
|
@ -412,7 +385,7 @@ func (section *FaceSection) ToString (indent int) (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (behavior *FaceBehavior) ToString (indent int) (output string) {
|
func (behavior FaceBehavior) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, behavior.name, "\n")
|
output += doIndent(indent, behavior.name, "\n")
|
||||||
|
|
||||||
for _, inputItem := range behavior.inputs {
|
for _, inputItem := range behavior.inputs {
|
||||||
|
@ -473,13 +446,13 @@ func (block Block) ToString (indent int) (output string) {
|
||||||
|
|
||||||
func (funcOutput FuncOutput) ToString () (output string) {
|
func (funcOutput FuncOutput) ToString () (output string) {
|
||||||
output += funcOutput.Declaration.ToString()
|
output += funcOutput.Declaration.ToString()
|
||||||
if funcOutput.defaultValue.kind != ArgumentKindNil {
|
if funcOutput.value.kind != ArgumentKindNil {
|
||||||
output += " " + funcOutput.defaultValue.ToString(0, false)
|
output += " " + funcOutput.value.ToString(0, false)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (section *FuncSection) ToString (indent int) (output string) {
|
func (section FuncSection) ToString (indent int) (output string) {
|
||||||
output += doIndent (
|
output += doIndent (
|
||||||
indent,
|
indent,
|
||||||
"func ",
|
"func ",
|
||||||
|
|
155
parser/tree.go
155
parser/tree.go
|
@ -2,6 +2,7 @@ package parser
|
||||||
|
|
||||||
import "git.tebibyte.media/arf/arf/file"
|
import "git.tebibyte.media/arf/arf/file"
|
||||||
import "git.tebibyte.media/arf/arf/types"
|
import "git.tebibyte.media/arf/arf/types"
|
||||||
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
// SyntaxTree represents an abstract syntax tree. It covers an entire module. It
|
// SyntaxTree represents an abstract syntax tree. It covers an entire module. It
|
||||||
// can be expected to be syntactically correct, but it might not be semantically
|
// can be expected to be syntactically correct, but it might not be semantically
|
||||||
|
@ -10,22 +11,40 @@ type SyntaxTree struct {
|
||||||
license string
|
license string
|
||||||
author string
|
author string
|
||||||
|
|
||||||
requires []string
|
requires []string
|
||||||
typeSections map[string] *TypeSection
|
sections map[string] Section
|
||||||
objtSections map[string] *ObjtSection
|
|
||||||
enumSections map[string] *EnumSection
|
|
||||||
faceSections map[string] *FaceSection
|
|
||||||
dataSections map[string] *DataSection
|
|
||||||
funcSections map[string] *FuncSection
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identifier represents a chain of arguments separated by a dot.
|
// SectionKind differentiates Section interfaces.
|
||||||
|
type SectionKind int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SectionKindType = iota
|
||||||
|
SectionKindObjt
|
||||||
|
SectionKindEnum
|
||||||
|
SectionKindFace
|
||||||
|
SectionKindData
|
||||||
|
SectionKindFunc
|
||||||
|
)
|
||||||
|
|
||||||
|
// Section can be any kind of section. You can find out what type of section it
|
||||||
|
// is with the Kind method.
|
||||||
|
type Section interface {
|
||||||
|
Location () (location file.Location)
|
||||||
|
Kind () (kind SectionKind)
|
||||||
|
Permission () (permission types.Permission)
|
||||||
|
Name () (name string)
|
||||||
|
NewError (message string, kind infoerr.ErrorKind) (err error)
|
||||||
|
ToString (indent int) (output string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identifier represents a chain of names separated by a dot.
|
||||||
type Identifier struct {
|
type Identifier struct {
|
||||||
location file.Location
|
locatable
|
||||||
trail []string
|
trail []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeKind represents what kind of type a type is
|
// TypeKind represents what kind of type a type is.
|
||||||
type TypeKind int
|
type TypeKind int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -36,19 +55,21 @@ const (
|
||||||
// TypeKindPointer means it's a pointer
|
// TypeKindPointer means it's a pointer
|
||||||
TypeKindPointer
|
TypeKindPointer
|
||||||
|
|
||||||
// TypeKindArray means it's an array.
|
// TypeKindArray means it's a fixed length array.
|
||||||
TypeKindArray
|
TypeKindArray
|
||||||
|
|
||||||
|
// TypeKindVariableArray means it's an array of variable length.
|
||||||
|
TypeKindVariableArray
|
||||||
)
|
)
|
||||||
|
|
||||||
// Type represents a type specifier
|
// Type represents a type specifier
|
||||||
type Type struct {
|
type Type struct {
|
||||||
location file.Location
|
locatable
|
||||||
|
|
||||||
mutable bool
|
mutable bool
|
||||||
kind TypeKind
|
kind TypeKind
|
||||||
|
|
||||||
// only applicable for arrays. a value of zero means it has an
|
// only applicable for fixed length arrays.
|
||||||
// undefined/dynamic length.
|
|
||||||
length uint64
|
length uint64
|
||||||
|
|
||||||
// only applicable for basic.
|
// only applicable for basic.
|
||||||
|
@ -60,23 +81,23 @@ type Type struct {
|
||||||
|
|
||||||
// Declaration represents a variable declaration.
|
// Declaration represents a variable declaration.
|
||||||
type Declaration struct {
|
type Declaration struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
what Type
|
typeable
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectInitializationValues represents a list of object member initialization
|
// ObjectInitializationValues represents a list of object member initialization
|
||||||
// attributes.
|
// attributes.
|
||||||
type ObjectInitializationValues struct {
|
type ObjectInitializationValues struct {
|
||||||
location file.Location
|
locatable
|
||||||
attributes map[string] Argument
|
attributes map[string] Argument
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayInitializationValues represents a list of attributes initializing an
|
// ArrayInitializationValues represents a list of attributes initializing an
|
||||||
// array.
|
// array.
|
||||||
type ArrayInitializationValues struct {
|
type ArrayInitializationValues struct {
|
||||||
location file.Location
|
locatable
|
||||||
values []Argument
|
values []Argument
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArgumentKind specifies the type of thing the value of an argument should be
|
// ArgumentKind specifies the type of thing the value of an argument should be
|
||||||
|
@ -139,75 +160,73 @@ const (
|
||||||
// Argument represents a value that can be placed anywhere a value goes. This
|
// Argument represents a value that can be placed anywhere a value goes. This
|
||||||
// allows things like phrases being arguments to other phrases.
|
// allows things like phrases being arguments to other phrases.
|
||||||
type Argument struct {
|
type Argument struct {
|
||||||
location file.Location
|
locatable
|
||||||
kind ArgumentKind
|
kind ArgumentKind
|
||||||
value any
|
value any
|
||||||
// TODO: if there is an argument expansion operator its existence should
|
// TODO: if there is an argument expansion operator its existence should
|
||||||
// be stored here in a boolean.
|
// be stored here in a boolean.
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataSection represents a global variable.
|
// DataSection represents a global variable.
|
||||||
type DataSection struct {
|
type DataSection struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
|
typeable
|
||||||
what Type
|
permissionable
|
||||||
permission types.Permission
|
valuable
|
||||||
value Argument
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeSection represents a blind type definition.
|
// TypeSection represents a blind type definition.
|
||||||
type TypeSection struct {
|
type TypeSection struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
|
typeable
|
||||||
inherits Type
|
permissionable
|
||||||
permission types.Permission
|
valuable
|
||||||
defaultValue Argument
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjtMember represents a part of an object type definition.
|
// ObjtMember represents a part of an object type definition.
|
||||||
type ObjtMember struct {
|
type ObjtMember struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
|
typeable
|
||||||
what Type
|
permissionable
|
||||||
bitWidth uint64
|
valuable
|
||||||
permission types.Permission
|
|
||||||
defaultValue Argument
|
bitWidth uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjtSection represents an object type definition.
|
// ObjtSection represents an object type definition.
|
||||||
type ObjtSection struct {
|
type ObjtSection struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
|
permissionable
|
||||||
|
inherits Identifier
|
||||||
|
|
||||||
inherits Identifier
|
members []ObjtMember
|
||||||
permission types.Permission
|
|
||||||
members []ObjtMember
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumMember represents a member of an enum section.
|
// EnumMember represents a member of an enum section.
|
||||||
type EnumMember struct {
|
type EnumMember struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
value Argument
|
valuable
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumSection represents an enumerated type section.
|
// EnumSection represents an enumerated type section.
|
||||||
type EnumSection struct {
|
type EnumSection struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
|
typeable
|
||||||
what Type
|
permissionable
|
||||||
permission types.Permission
|
|
||||||
members []EnumMember
|
members []EnumMember
|
||||||
}
|
}
|
||||||
|
|
||||||
// FaceBehavior represents a behavior of an interface section.
|
// FaceBehavior represents a behavior of an interface section.
|
||||||
type FaceBehavior struct {
|
type FaceBehavior struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
|
|
||||||
inputs []Declaration
|
inputs []Declaration
|
||||||
outputs []Declaration
|
outputs []Declaration
|
||||||
|
@ -215,12 +234,12 @@ type FaceBehavior struct {
|
||||||
|
|
||||||
// FaceSection represents an interface type section.
|
// FaceSection represents an interface type section.
|
||||||
type FaceSection struct {
|
type FaceSection struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
|
permissionable
|
||||||
inherits Identifier
|
inherits Identifier
|
||||||
|
|
||||||
permission types.Permission
|
behaviors map[string] FaceBehavior
|
||||||
behaviors map[string] FaceBehavior
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PhraseKind determines what semantic role a phrase plays.
|
// PhraseKind determines what semantic role a phrase plays.
|
||||||
|
@ -248,6 +267,8 @@ type Phrase struct {
|
||||||
location file.Location
|
location file.Location
|
||||||
command Argument
|
command Argument
|
||||||
arguments []Argument
|
arguments []Argument
|
||||||
|
// TODO: this is wack. it should be named after a plural noun like,
|
||||||
|
// returnees or something. accessor methods should beupdated to match.
|
||||||
returnsTo []Argument
|
returnsTo []Argument
|
||||||
|
|
||||||
kind PhraseKind
|
kind PhraseKind
|
||||||
|
@ -263,14 +284,14 @@ type Block []Phrase
|
||||||
// that it can have a default value.
|
// that it can have a default value.
|
||||||
type FuncOutput struct {
|
type FuncOutput struct {
|
||||||
Declaration
|
Declaration
|
||||||
defaultValue Argument
|
valuable
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncSection represents a function section.
|
// FuncSection represents a function section.
|
||||||
type FuncSection struct {
|
type FuncSection struct {
|
||||||
location file.Location
|
locatable
|
||||||
name string
|
nameable
|
||||||
permission types.Permission
|
permissionable
|
||||||
|
|
||||||
receiver *Declaration
|
receiver *Declaration
|
||||||
inputs []Declaration
|
inputs []Declaration
|
||||||
|
|
|
@ -2,18 +2,17 @@ package parser
|
||||||
|
|
||||||
import "git.tebibyte.media/arf/arf/types"
|
import "git.tebibyte.media/arf/arf/types"
|
||||||
import "git.tebibyte.media/arf/arf/lexer"
|
import "git.tebibyte.media/arf/arf/lexer"
|
||||||
// import "git.tebibyte.media/arf/arf/infoerr"
|
|
||||||
|
|
||||||
// parseTypeSection parses a blind type definition, meaning it can inherit from
|
// parseTypeSection parses a blind type definition, meaning it can inherit from
|
||||||
// anything including primitives, but cannot define structure.
|
// anything including primitives, but cannot define structure.
|
||||||
func (parser *ParsingOperation) parseTypeSection () (
|
func (parser *ParsingOperation) parseTypeSection () (
|
||||||
section *TypeSection,
|
section TypeSection,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section = &TypeSection { location: parser.token.Location() }
|
section.location = parser.token.Location()
|
||||||
|
|
||||||
// get permission
|
// get permission
|
||||||
err = parser.nextToken(lexer.TokenKindPermission)
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
|
@ -30,7 +29,7 @@ func (parser *ParsingOperation) parseTypeSection () (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
section.inherits, err = parser.parseType()
|
section.what, err = parser.parseType()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
// parse default values
|
// parse default values
|
||||||
|
@ -38,10 +37,10 @@ func (parser *ParsingOperation) parseTypeSection () (
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section.defaultValue, err = parser.parseInitializationValues(0)
|
section.value, err = parser.parseInitializationValues(0)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
} else {
|
} else {
|
||||||
section.defaultValue, err = parser.parseArgument()
|
section.value, err = parser.parseArgument()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
err = parser.expect(lexer.TokenKindNewline)
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
|
50
types/iterator.go
Normal file
50
types/iterator.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
// Iterator is an object capable of iterating over any string-indexed map, while
|
||||||
|
// protecting its data.
|
||||||
|
type Iterator[VALUE_TYPE any] struct {
|
||||||
|
index int
|
||||||
|
keys []string
|
||||||
|
underlying map[string] VALUE_TYPE
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIterator creates a new iterator that iterates over the specified map.
|
||||||
|
func NewIterator[VALUE_TYPE any] (
|
||||||
|
underlying map[string] VALUE_TYPE,
|
||||||
|
) (
|
||||||
|
iterator Iterator[VALUE_TYPE],
|
||||||
|
) {
|
||||||
|
iterator.underlying = underlying
|
||||||
|
iterator.keys = make([]string, len(underlying))
|
||||||
|
|
||||||
|
index := 0
|
||||||
|
for key, _ := range underlying {
|
||||||
|
iterator.keys[index] = key
|
||||||
|
index ++
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the current key the iterator is on.
|
||||||
|
func (iterator Iterator[VALUE_TYPE]) Key () (key string) {
|
||||||
|
key = iterator.keys[iterator.index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current value the iterator is on.
|
||||||
|
func (iterator Iterator[VALUE_TYPE]) Value () (value VALUE_TYPE) {
|
||||||
|
value = iterator.underlying[iterator.keys[iterator.index]]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next advances the iterator by 1.
|
||||||
|
func (iterator Iterator[VALUE_TYPE]) Next () {
|
||||||
|
iterator.index ++
|
||||||
|
}
|
||||||
|
|
||||||
|
// End returns whether the iterator has reached the end of the map.
|
||||||
|
func (iterator Iterator[VALUE_TYPE]) End () (atEnd bool) {
|
||||||
|
atEnd = iterator.index >= len(iterator.keys) || iterator.index < 0
|
||||||
|
return
|
||||||
|
}
|
Reference in New Issue
Block a user