Add access specifiers and link names to parser

This commit is contained in:
Sasha Koshka 2023-12-17 11:23:42 -05:00
parent 6bcbd6aff9
commit 0645e2b43a
2 changed files with 109 additions and 19 deletions

View File

@ -8,26 +8,55 @@ type TopLevel interface {
topLevel ()
}
// Access determines the external access rule for a top-level entity.
type Access int; const (
AccessPrivate = iota
AccessRestricted
AccessPublic
)
func (this *Access) String () string {
switch *this {
case AccessPrivate: return "-"
case AccessRestricted: return "#"
case AccessPublic: return "+"
default: return fmt.Sprintf("entity.Access(%d)", this)
}
}
func (this *Access) Capture (values []string) error {
switch values[0] {
case "-": *this = AccessPrivate
case "#": *this = AccessRestricted
case "+": *this = AccessPublic
}
return nil
}
// Typedef binds a type to a global identifier.
type Typedef struct {
// Syntax
Pos lexer.Position
Public bool `parser:" @'+'? "`
Name string `parser:" @TypeIdent "`
Type Type `parser:" ':' @@ "`
Acc *Access `parser:" @('-' | '#' | '+')? "`
Name string `parser:" @TypeIdent "`
Type Type `parser:" ':' @@ "`
// Semantics
Methods map[string] *Method
}
func (*Typedef) topLevel(){}
func (this *Typedef) String () string {
out := fmt.Sprint(this.Name, ": ", this.Type)
output := ""
if this.Acc != nil {
output += fmt.Sprint(this.Acc, " ")
}
output += fmt.Sprint(this.Name, ": ", this.Type)
if this.Methods != nil {
for _, method := range this.Methods {
out += fmt.Sprint("\n", method)
output += fmt.Sprint("\n", method)
}
}
return out
return output
}
// Function binds a global identifier and argument list to an expression which
@ -38,8 +67,9 @@ func (this *Typedef) String () string {
type Function struct {
// Syntax
Pos lexer.Position
Public bool `parser:" @'+'? "`
Acc *Access `parser:" @('-' | '#' | '+')? "`
Signature *Signature `parser:" @@ "`
LinkName string `parser:" @String? "`
Body Expression `parser:" ( '=' @@ )? "`
// Semantics
@ -47,11 +77,18 @@ type Function struct {
}
func (*Function) topLevel(){}
func (this *Function) String () string {
if this.Body == nil {
return fmt.Sprint(this.Signature)
} else {
return fmt.Sprint(this.Signature, " = ", this.Body)
output := ""
if this.Acc != nil {
output += fmt.Sprint(this.Acc, " ")
}
output += this.Signature.String()
if this.LinkName != "" {
output += fmt.Sprint(" '", this.LinkName, "'")
}
if this.Body != nil {
output += fmt.Sprint(" = ", this.Body)
}
return output
}
// Method is like a function, except localized to a defined type. Methods are
@ -61,9 +98,10 @@ func (this *Function) String () string {
type Method struct {
// Syntax
Pos lexer.Position
Public bool `parser:" @'+'? "`
Acc *Access `parser:" @('-' | '#' | '+')? "`
TypeName string `parser:" @TypeIdent "`
Signature *Signature `parser:" '.' @@ "`
LinkName string `parser:" @String? "`
Body Expression `parser:" ( '=' @@ )? "`
// Semantics
@ -73,12 +111,16 @@ type Method struct {
}
func (*Method) topLevel(){}
func (this *Method) String () string {
if this.Body == nil {
return fmt.Sprint(this.TypeName, ".", this.Signature)
} else {
return fmt.Sprint (
this.TypeName, ".",
this.Signature, " = ",
this.Body)
output := ""
if this.Acc != nil {
output += fmt.Sprint(this.Acc, " ")
}
output += fmt.Sprint(this.TypeName, ".", this.Signature)
if this.LinkName != "" {
output += fmt.Sprint(" '", this.LinkName, "'")
}
if this.Body != nil {
output += fmt.Sprint(" = ", this.Body)
}
return output
}

View File

@ -143,3 +143,51 @@ BopIt.[twist angle:F64] = { }
BopIt.[pull distance:Int] = { }
`)
}
func TestAccess (test *testing.T) {
testString (test,
// correct
`+ PublicType: Int
# RestrictedType: (x:Int y:Int)
- PrivateType: String
AlsoPrivateType: Byte
+ [publicFn]:Int = 0
# [restrictedFn]:(x:Int y:Int) = (x:0 y:0)
- [privateFn]:Rune = 'a'
[alsoPrivateFn]:Byte = 0
T: Int
+ T.[publicFn]:Int = 0
# T.[restrictedFn]:(x:Int y:Int) = (x:0 y:0)
- T.[privateFn]:Rune = 'a'
T.[alsoPrivateFn]:Byte = 0`,
//input
`
+ PublicType: Int
# RestrictedType: (x:Int y:Int)
- PrivateType: String
AlsoPrivateType: Byte
+ [publicFn]: Int = 0
# [restrictedFn]: (x:Int y:Int) = (x:0 y:0)
- [privateFn]: Rune = 'a'
[alsoPrivateFn]: Byte = 0
T: Int
+ T.[publicFn]: Int = 0
# T.[restrictedFn]: (x:Int y:Int) = (x:0 y:0)
- T.[privateFn]: Rune = 'a'
T.[alsoPrivateFn]: Byte = 0
`)
}
func TestLinkName (test *testing.T) {
testString (test,
// correct
`[puts byte:*:Byte]:Index 'puts'
File.[write size:Index nmemb:Index]:Index 'fwrite'
[main]:Int 'main' = 0`,
// input
`
[puts byte:*:Byte]: Index 'puts'
File.[write size:Index nmemb:Index]: Index 'fwrite'
[main]: Int 'main' = 0
`)
}