Merge pull request 'face-section' (#7) from face-section into main
Reviewed-on: sashakoshka/arf#7
This commit is contained in:
commit
a5477717eb
@ -9,7 +9,7 @@ data pv helloText:String "Hello, world!"
|
|||||||
|
|
||||||
# this is a struct definition
|
# this is a struct definition
|
||||||
objt ro Greeter:Obj
|
objt ro Greeter:Obj
|
||||||
wr text:String "Hi."
|
rw text:String "Hi."
|
||||||
|
|
||||||
# this is a function
|
# this is a function
|
||||||
func ro main
|
func ro main
|
||||||
|
@ -39,6 +39,14 @@ func (parser *ParsingOperation) parseBody () (err error) {
|
|||||||
parser.tree.objtSections[section.name] = section
|
parser.tree.objtSections[section.name] = section
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
case "face":
|
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":
|
case "enum":
|
||||||
var section *EnumSection
|
var section *EnumSection
|
||||||
section, err = parser.parseEnumSection()
|
section, err = parser.parseEnumSection()
|
||||||
|
132
parser/face.go
Normal file
132
parser/face.go
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
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.nextToken(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
|
||||||
|
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
|
||||||
|
}
|
||||||
|
section.behaviors[behavior.name] = behavior
|
||||||
|
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseFaceBehavior parses a single interface behavior. Indentation level is
|
||||||
|
// assumed.
|
||||||
|
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 {
|
||||||
|
// if we've left the block, stop parsing
|
||||||
|
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.outputs = append (
|
||||||
|
behavior.outputs,
|
||||||
|
declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
@ -192,3 +192,21 @@ enum ro Weekday:Int
|
|||||||
wednesday
|
wednesday
|
||||||
`, test)
|
`, test)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test (test *testing.T) {
|
||||||
|
checkTree ("../tests/parser/face",
|
||||||
|
`:arf
|
||||||
|
---
|
||||||
|
face ro Destroyer:Face
|
||||||
|
destroy
|
||||||
|
face ro ReadWriter:Face
|
||||||
|
read
|
||||||
|
> into:{Byte ..}
|
||||||
|
< read:Int
|
||||||
|
< err:Error
|
||||||
|
write
|
||||||
|
> data:{Byte ..}
|
||||||
|
< wrote:Int
|
||||||
|
< err:Error
|
||||||
|
`, test)
|
||||||
|
}
|
||||||
|
@ -61,6 +61,11 @@ func (tree *SyntaxTree) ToString (indent int) (output string) {
|
|||||||
output += tree.enumSections[name].ToString(indent)
|
output += tree.enumSections[name].ToString(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
faceSectionKeys := sortMapKeysAlphabetically(tree.faceSections)
|
||||||
|
for _, name := range faceSectionKeys {
|
||||||
|
output += tree.faceSections[name].ToString(indent)
|
||||||
|
}
|
||||||
|
|
||||||
dataSectionKeys := sortMapKeysAlphabetically(tree.dataSections)
|
dataSectionKeys := sortMapKeysAlphabetically(tree.dataSections)
|
||||||
for _, name := range dataSectionKeys {
|
for _, name := range dataSectionKeys {
|
||||||
output += tree.dataSections[name].ToString(indent)
|
output += tree.dataSections[name].ToString(indent)
|
||||||
@ -353,3 +358,32 @@ func (section *EnumSection) ToString (indent int) (output string) {
|
|||||||
}
|
}
|
||||||
return
|
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 + 1, "> ", inputItem.ToString(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, outputItem := range behavior.outputs {
|
||||||
|
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@ type SyntaxTree struct {
|
|||||||
typeSections map[string] *TypeSection
|
typeSections map[string] *TypeSection
|
||||||
objtSections map[string] *ObjtSection
|
objtSections map[string] *ObjtSection
|
||||||
enumSections map[string] *EnumSection
|
enumSections map[string] *EnumSection
|
||||||
|
faceSections map[string] *FaceSection
|
||||||
dataSections map[string] *DataSection
|
dataSections map[string] *DataSection
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,3 +204,22 @@ type EnumSection struct {
|
|||||||
// TODO: order matters here we need to store these in an array
|
// TODO: order matters here we need to store these in an array
|
||||||
members map[string] Argument
|
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
|
||||||
|
inherits string
|
||||||
|
|
||||||
|
permission types.Permission
|
||||||
|
behaviors map[string] FaceBehavior
|
||||||
|
}
|
||||||
|
15
tests/parser/face/main.arf
Normal file
15
tests/parser/face/main.arf
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
:arf
|
||||||
|
---
|
||||||
|
|
||||||
|
face ro ReadWriter:Face
|
||||||
|
write
|
||||||
|
> data:{Byte ..}
|
||||||
|
< wrote:Int
|
||||||
|
< err:Error
|
||||||
|
read
|
||||||
|
> into:{Byte ..}
|
||||||
|
< read:Int
|
||||||
|
< err:Error
|
||||||
|
|
||||||
|
face ro Destroyer:Face
|
||||||
|
destroy
|
Reference in New Issue
Block a user