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

Reviewed-on: arf/arf#6
This commit is contained in:
Sasha Koshka 2022-09-17 16:36:27 +00:00
commit 844b1562c4
33 changed files with 1025 additions and 907 deletions

View File

@ -4,6 +4,6 @@ require "io"
func ro main func ro main
> arguments:{String ..} > arguments:{String ..}
< status:Int 0 < status:Int:<0>
--- ---
io.println "hello world" io.println "hello world"

View File

@ -5,18 +5,18 @@ require "io"
--- ---
# this is a global variable # this is a global variable
data pv helloText:String "Hello, world!" data pv helloText:String:<"Hello, world!">
# this is a struct definition # this is a struct definition
objt ro Greeter:Obj type ro Greeter:Obj:(
rw text:String "Hi." .rw text:String:<"Hi.">)
# this is a function # this is a function
func ro main func ro main
> arguments:{String ..} > arguments:{String ..}
< status:Int 0 < status:Int:<0>
--- ---
= greeter:Greeter:mut let greeter:Greeter:mut
greeter.setText helloText greeter.setText helloText
greeter.greet greeter.greet

View File

@ -192,6 +192,16 @@ func (lexer *LexingOperation) tokenizeSymbolBeginning () (err error) {
token.kind = TokenKindComma token.kind = TokenKindComma
lexer.addToken(token) lexer.addToken(token)
err = lexer.nextRune() err = lexer.nextRune()
case '(':
token := lexer.newToken()
token.kind = TokenKindLParen
lexer.addToken(token)
err = lexer.nextRune()
case ')':
token := lexer.newToken()
token.kind = TokenKindRParen
lexer.addToken(token)
err = lexer.nextRune()
case '[': case '[':
token := lexer.newToken() token := lexer.newToken()
token.kind = TokenKindLBracket token.kind = TokenKindLBracket

View File

@ -138,6 +138,8 @@ func TestTokenizeAll (test *testing.T) {
quickToken(1, TokenKindDot, nil), quickToken(1, TokenKindDot, nil),
quickToken(1, TokenKindComma, nil), quickToken(1, TokenKindComma, nil),
quickToken(2, TokenKindElipsis, nil), quickToken(2, TokenKindElipsis, nil),
quickToken(1, TokenKindLParen, nil),
quickToken(1, TokenKindRParen, nil),
quickToken(1, TokenKindLBracket, nil), quickToken(1, TokenKindLBracket, nil),
quickToken(1, TokenKindRBracket, nil), quickToken(1, TokenKindRBracket, nil),
quickToken(1, TokenKindLBrace, nil), quickToken(1, TokenKindLBrace, nil),

View File

@ -28,6 +28,8 @@ const (
TokenKindElipsis TokenKindElipsis
TokenKindComma TokenKindComma
TokenKindLParen
TokenKindRParen
TokenKindLBracket TokenKindLBracket
TokenKindRBracket TokenKindRBracket
TokenKindLBrace TokenKindLBrace
@ -166,6 +168,10 @@ func (tokenKind TokenKind) Describe () (description string) {
description = "Elipsis" description = "Elipsis"
case TokenKindComma: case TokenKindComma:
description = "Comma" description = "Comma"
case TokenKindLParen:
description = "LParen"
case TokenKindRParen:
description = "RParen"
case TokenKindLBracket: case TokenKindLBracket:
description = "LBracket" description = "LBracket"
case TokenKindRBracket: case TokenKindRBracket:

View File

@ -29,12 +29,6 @@ func (section TypeSection) Kind () (kind SectionKind) {
return return
} }
// Kind returns the section's kind (SectionKindObjt).
func (section ObjtSection) Kind () (kind SectionKind) {
kind = SectionKindObjt
return
}
// Kind returns the section's kind (SectionKindEnum). // Kind returns the section's kind (SectionKindEnum).
func (section EnumSection) Kind () (kind SectionKind) { func (section EnumSection) Kind () (kind SectionKind) {
kind = SectionKindEnum kind = SectionKindEnum
@ -111,23 +105,23 @@ func (what Type) Points () (points Type) {
return return
} }
// Values returns an iterator for the initialization values. // MembersLength returns the amount of new members the type specifier defines.
func (values ObjectInitializationValues) Sections () ( // If it defines no new members, it returns zero.
iterator types.Iterator[Argument], func (what Type) MembersLength () (length int) {
) { length = len(what.members)
iterator = types.NewIterator(values.attributes)
return return
} }
// Length returns the amount of values. // Member returns the member at index.
func (values ArrayInitializationValues) Length () (length int) { func (what Type) Member (index int) (member TypeMember) {
length = len(values.values) member = what.members[index]
return return
} }
// Item returns the value at index. // BitWidth returns the bit width of the type member. If it is zero, it should
func (values ArrayInitializationValues) Value (index int) (value Argument) { // be treated as unspecified.
value = values.values[index] func (member TypeMember) BitWidth () (width uint64) {
width = member.bitWidth
return return
} }
@ -144,25 +138,6 @@ func (argument Argument) Value () (value any) {
return 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. // Length returns the amount of members in the section.
func (section EnumSection) Length () (length int) { func (section EnumSection) Length () (length int) {
length = len(section.members) length = len(section.members)
@ -272,12 +247,6 @@ func (section FuncSection) OutputsLength () (length int) {
return 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. // Root returns the root block of the section.
func (section FuncSection) Root () (root Block) { func (section FuncSection) Root () (root Block) {
root = section.root root = section.root

View File

@ -23,12 +23,6 @@ func (parser *ParsingOperation) parseBody () (err error) {
if err != nil { return } if err != nil { return }
if parseErr != nil { return parseErr } if parseErr != nil { return parseErr }
case "objt":
section, parseErr := parser.parseObjtSection()
err = parser.tree.addSection(section)
if err != nil { return }
if parseErr != nil { return parseErr }
case "face": case "face":
section, parseErr := parser.parseFaceSection() section, parseErr := parser.parseFaceSection()
err = parser.tree.addSection(section) err = parser.tree.addSection(section)

View File

@ -35,18 +35,18 @@ func (parser *ParsingOperation) parseDataSection () (
return return
} }
if parser.token.Is(lexer.TokenKindNewline) { err = parser.expect(lexer.TokenKindNewline)
err = parser.nextToken() if err != nil { return }
if err != nil { return } err = parser.nextToken()
if err != nil { return }
// check if external
if !parser.token.Is(lexer.TokenKindIndent) { return } // check if data is external
if parser.token.Value().(int) != 1 { return } if parser.token.Is(lexer.TokenKindIndent) &&
parser.token.Value().(int) == 1 {
err = parser.nextToken() err = parser.nextToken(lexer.TokenKindName)
if err != nil { return } if err != nil { return }
if parser.token.Is(lexer.TokenKindName) && if parser.token.Value().(string) == "external" {
parser.token.Value().(string) == "external" {
section.external = true section.external = true
err = parser.nextToken(lexer.TokenKindNewline) err = parser.nextToken(lexer.TokenKindNewline)
@ -56,18 +56,7 @@ func (parser *ParsingOperation) parseDataSection () (
return return
} }
// otherwise, parse initialization values
parser.previousToken() parser.previousToken()
section.value, err = parser.parseInitializationValues(0)
if err != nil { return }
} else {
section.value, err = parser.parseArgument()
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
} }
return return
} }

View File

@ -6,13 +6,14 @@ func TestData (test *testing.T) {
checkTree ("../tests/parser/data", false, checkTree ("../tests/parser/data", false,
`:arf `:arf
--- ---
data ro aInteger:Int 3202 data ro aInteger:Int:<3202>
data ro bMutInteger:Int:mut 3202 data ro bMutInteger:Int:mut:<3202>
data ro cIntegerPointer:{Int} data ro cIntegerPointer:{Int}
data ro dMutIntegerPointer:{Int}:mut data ro dMutIntegerPointer:{Int}:mut
data ro eIntegerArray16:Int:16 data ro eIntegerArray16:Int:16
data ro fIntegerArrayVariable:{Int ..} data ro fIntegerArrayVariable:{Int ..}
data ro gIntegerArrayInitialized:Int:16 data ro gIntegerArrayInitialized:Int:16:
<
3948 3948
293 293
293049 293049
@ -24,20 +25,35 @@ data ro gIntegerArrayInitialized:Int:16
0 0
4785 4785
92 92
data ro jObject:thing.Thing.thing.thing >
.that 2139 data rw hIntegerPointerInit:{Int}:<[& integer]>
.this 324 data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
data ro kNestedObject:Obj data ro jObject:Obj:
.that (
.bird2 123.8439 .that:<324>
.bird3 9328.21348239 .this:<324>
.this )
.bird0 324 data ro kNestedObject:Obj:
.bird1 "hello world" (
.ro newMember:Int:<9023>
):
(
.that:
(
.bird2:<123.8439>
.bird3:<9328.21348239>
)
.this:
(
.bird0:<324>
.bird1:<"hello world">
)
)
data ro lMutIntegerArray16:Int:16:mut data ro lMutIntegerArray16:Int:16:mut
data ro mExternalData:Int:8 data ro mExternalData:Int:8
external external
data ro nIntegerArrayInitialized:Int:16:mut data ro nIntegerArrayInitialized:Int:16:mut:
<
3948 3948
293 293
293049 293049
@ -49,5 +65,6 @@ data ro nIntegerArrayInitialized:Int:16:mut
0 0
4785 4785
92 92
>
`, test) `, test)
} }

180
parser/default-values.go Normal file
View File

@ -0,0 +1,180 @@
package parser
//
// import "git.tebibyte.media/arf/arf/lexer"
// import "git.tebibyte.media/arf/arf/infoerr"
//
// // TODO:
// // (parser *ParsingOperation) parseDefaultValues
//
// // (parser *ParsingOperation) parseDefaultMemberValues (return tree of new members and a tree of member values)
// // (parser *ParsingOperation) parseDefaultArrayValues
//
// // (parser *ParsingOperation) parseDefaultMemberValue
// // (parser *ParsingOperation) parseMemberDeclaration
//
// // parsedefaultValues starts on the line after a = phrase, a data section, a
// // type section, or anywhere else where there can be a default value. It returns
// // a default value in the form of an argument, as well as any defined members
// // that it finds.
// func (parser *ParsingOperation) parseDefaultValues (
// baseIndent int,
// ) (
// argument Argument,
// members []TypeMember,
// 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 }
//
// argument.location = parser.token.Location()
//
// err = parser.nextToken()
// if err != nil { return }
//
// if parser.token.Is(lexer.TokenKindDot) {
//
// // object initialization
// parser.previousToken()
// var values ObjectDefaultValues
// values, err = parser.parseObjectdefaultValues()
// argument.kind = ArgumentKindObjectDefaultValues
// argument.value = values
//
// } else {
//
// // array initialization
// parser.previousToken()
// var values ArrayDefaultValues
// values, err = parser.parseArrayDefaultValues()
// argument.kind = ArgumentKindArrayDefaultValues
// argument.value = values
// }
//
// return
// }
//
// // parseObjectdefaultValues parses a list of object initialization
// // values until the indentation level drops.
// func (parser *ParsingOperation) parseObjectdefaultValues () (
// defaultValues ObjectDefaultValues,
// err error,
// ) {
// defaultValues.attributes = make(map[string] Argument)
//
// 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 {
// defaultValues.location = parser.token.Location()
// 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 member initialization value
// err = parser.nextToken(lexer.TokenKindDot)
// if err != nil { return }
// err = parser.nextToken(lexer.TokenKindName)
// if err != nil { return }
// name := parser.token.Value().(string)
//
// // if the member has already been listed, throw an error
// _, exists := defaultValues.attributes[name]
// if exists {
// err = parser.token.NewError (
// "duplicate member \"" + name + "\" in object " +
// "member initialization",
// infoerr.ErrorKindError)
// return
// }
//
// // parse the argument determining the member initialization
// // value
// err = parser.nextToken()
// if err != nil { return }
// var value Argument
// if parser.token.Is(lexer.TokenKindNewline) {
//
// // recurse
// err = parser.nextToken(lexer.TokenKindIndent)
// if err != nil { return }
//
// value, err = parser.parseDefaultValues(baseIndent)
// defaultValues.attributes[name] = value
// if err != nil { return }
//
// } else {
//
// // parse as normal argument
// value, err = parser.parseArgument()
// defaultValues.attributes[name] = value
// if err != nil { return }
//
// err = parser.expect(lexer.TokenKindNewline)
// if err != nil { return }
// err = parser.nextToken()
// if err != nil { return }
// }
// }
//
// return
// }
//
// // parseArrayDefaultValues parses a list of array initialization values until
// // the indentation lexel drops.
// func (parser *ParsingOperation) parseArrayDefaultValues () (
// defaultValues ArrayDefaultValues,
// 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 {
// defaultValues.location = parser.token.Location()
// 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
// // arguments
// err = parser.nextToken(validArgumentStartTokens...)
// if err != nil { return }
//
// for {
// // stop parsing this line and go on to the next if a
// // newline token is encountered
// if parser.token.Is(lexer.TokenKindNewline) {
// err = parser.nextToken()
// if err != nil { return }
// break
// }
//
// // otherwise, parse the argument
// var argument Argument
// argument, err = parser.parseArgument()
// if err != nil { return }
// defaultValues.values = append (
// defaultValues.values,
// argument)
// }
// }
//
// return
// }

View File

@ -61,34 +61,62 @@ func (parser *ParsingOperation) parseEnumMembers (
// if we've left the block, stop parsing // if we've left the block, stop parsing
if !parser.token.Is(lexer.TokenKindIndent) { return } if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 1 { return } if parser.token.Value().(int) != 1 { return }
err = parser.nextToken(lexer.TokenKindMinus)
member := EnumMember { } if err != nil { return }
// get name var member EnumMember
err = parser.nextToken(lexer.TokenKindName) member, err = parser.parseEnumMember()
into.members = append(into.members, member)
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return } if err != nil { return }
member.location = parser.token.Location()
member.name = parser.token.Value().(string)
err = parser.nextToken() err = parser.nextToken()
if err != nil { return } if err != nil { return }
}
// parse default value }
if parser.token.Is(lexer.TokenKindNewline) {
err = parser.nextToken()
if err != nil { return }
member.value, err = parser.parseInitializationValues(1) // parseEnumMember parses a single enum member. Indenttion level is assumed.
into.members = append(into.members, member) func (parser *ParsingOperation) parseEnumMember () (
if err != nil { return } member EnumMember,
} else { err error,
member.value, err = parser.parseArgument() ) {
into.members = append(into.members, member) err = parser.expect(lexer.TokenKindMinus)
if err != nil { return } if err != nil { return }
err = parser.expect(lexer.TokenKindNewline) // get name
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
member.location = parser.token.Location()
member.name = parser.token.Value().(string)
// see if value exists
err = parser.nextToken (
lexer.TokenKindColon,
lexer.TokenKindNewline)
if err != nil { return }
if parser.token.Is(lexer.TokenKindColon) {
err = parser.nextToken()
if err != nil { return }
err = parser.skipWhitespace()
if err != nil { return }
err = parser.expect (
lexer.TokenKindLessThan,
lexer.TokenKindLParen)
if err != nil { return }
if parser.token.Is(lexer.TokenKindLessThan) {
// parse value
member.value, err = parser.parseBasicDefaultValue()
if err != nil { return } if err != nil { return }
err = parser.nextToken()
} else if parser.token.Is(lexer.TokenKindLParen) {
// parse default values
member.value, err = parser.parseObjectDefaultValue()
if err != nil { return } if err != nil { return }
} }
} }
return
} }

View File

@ -7,32 +7,63 @@ func TestEnum (test *testing.T) {
`:arf `:arf
--- ---
enum ro AffrontToGod:Int:4 enum ro AffrontToGod:Int:4
bird0 - bird0:
<
28394 28394
9328 9328
398 398
9 9
bird1 >
- bird1:
<
23 23
932832 932832
398 398
2349 2349
bird2 >
- bird2:
<
1 1
2 2
3 3
4 4
>
enum ro NamedColor:U32 enum ro NamedColor:U32
red 16711680 - red:<16711680>
green 65280 - green:<65280>
blue 255 - blue:<255>
enum ro ThisIsTerrible:Obj:
(
.rw x:Int
.rw y:Int
)
- up:
(
.x:<0>
.y:<-1>
)
- down:
(
.x:<0>
.y:<1>
)
- left:
(
.x:<-1>
.y:<0>
)
- right:
(
.x:<1>
.y:<0>
)
enum ro Weekday:Int enum ro Weekday:Int
sunday - sunday
monday - monday
tuesday - tuesday
wednesday - wednesday
thursday - thursday
friday - friday
saturday - saturday
`, test) `, test)
} }

View File

@ -171,7 +171,7 @@ func (parser *ParsingOperation) parseFuncArguments (
if err != nil { return } if err != nil { return }
case lexer.TokenKindLessThan: case lexer.TokenKindLessThan:
output := FuncOutput { } output := Declaration { }
output.location = parser.token.Location() output.location = parser.token.Location()
// get name // get name
@ -186,34 +186,13 @@ func (parser *ParsingOperation) parseFuncArguments (
if err != nil { return } if err != nil { return }
output.what, err = parser.parseType() output.what, err = parser.parseType()
if err != nil { return } if err != nil { return }
// skip the default value if we are skimming
if parser.skimming {
err = parser.skipIndentLevel(2)
into.outputs = append(into.outputs, output)
return
}
// parse default value into.outputs = append(into.outputs, output)
if parser.token.Is(lexer.TokenKindNewline) {
err = parser.nextToken()
if err != nil { return }
output.value, err = parser.expect(lexer.TokenKindNewline)
parser.parseInitializationValues(1) if err != nil { return }
into.outputs = append(into.outputs, output) err = parser.nextToken()
if err != nil { return } if err != nil { return }
} else {
output.value, err =
parser.parseArgument()
into.outputs = append(into.outputs, output)
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
}
} }
} }
} }

View File

@ -8,13 +8,13 @@ func TestFunc (test *testing.T) {
--- ---
func ro aBasicExternal func ro aBasicExternal
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int 4 < someOutput:Int:<4>
--- ---
external external
func ro bMethod func ro bMethod
@ bird:{Bird} @ bird:{Bird}
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int 4 < someOutput:Int:<4>
--- ---
external external
func ro cBasicPhrases func ro cBasicPhrases
@ -101,20 +101,9 @@ func ro gControlFlow
[otherThing] [otherThing]
func ro hSetPhrase func ro hSetPhrase
--- ---
[= x:Int 3] [let x:Int:<3>]
[= y:{Int} [loc x]] [let y:{Int}:<[loc x]>]
[= z:Int:8] [let z:Int:8:<398 9 2309 983 -2387 478 555 123>]
398 [let bird:Bird:(.that:(.whenYou:<99999>) .this:<324>)]
9
2309
983
-2387
478
555
123
[= bird:Bird]
.that
.whenYou 99999
.this 324
`, test) `, test)
} }

View File

@ -1,170 +0,0 @@
package parser
import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
// parseInitializationValues starts on the line after a data section, or a set
// phrase. It checks for an indent greater than the indent of the aforementioned
// data section or set phrase (passed through baseIndent), and if there is,
// it parses initialization values.
func (parser *ParsingOperation) parseInitializationValues (
baseIndent int,
) (
initializationArgument Argument,
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 }
initializationArgument.location = parser.token.Location()
err = parser.nextToken()
if err != nil { return }
if parser.token.Is(lexer.TokenKindDot) {
// object initialization
parser.previousToken()
var initializationValues ObjectInitializationValues
initializationValues, err = parser.parseObjectInitializationValues()
initializationArgument.kind = ArgumentKindObjectInitializationValues
initializationArgument.value = initializationValues
} else {
// array initialization
parser.previousToken()
var initializationValues ArrayInitializationValues
initializationValues, err = parser.parseArrayInitializationValues()
initializationArgument.kind = ArgumentKindArrayInitializationValues
initializationArgument.value = initializationValues
}
return
}
// parseObjectInitializationValues parses a list of object initialization
// values until the indentation level drops.
func (parser *ParsingOperation) parseObjectInitializationValues () (
initializationValues ObjectInitializationValues,
err error,
) {
initializationValues.attributes = make(map[string] Argument)
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 {
initializationValues.location = parser.token.Location()
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 member initialization value
err = parser.nextToken(lexer.TokenKindDot)
if err != nil { return }
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
name := parser.token.Value().(string)
// if the member has already been listed, throw an error
_, exists := initializationValues.attributes[name]
if exists {
err = parser.token.NewError (
"duplicate member \"" + name + "\" in object " +
"member initialization",
infoerr.ErrorKindError)
return
}
// parse the argument determining the member initialization
// value
err = parser.nextToken()
if err != nil { return }
var value Argument
if parser.token.Is(lexer.TokenKindNewline) {
// recurse
err = parser.nextToken(lexer.TokenKindIndent)
if err != nil { return }
value, err = parser.parseInitializationValues(baseIndent)
initializationValues.attributes[name] = value
if err != nil { return }
} else {
// parse as normal argument
value, err = parser.parseArgument()
initializationValues.attributes[name] = value
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
}
}
return
}
// parseArrayInitializationValues parses a list of array initialization values
// until the indentation lexel drops.
func (parser *ParsingOperation) parseArrayInitializationValues () (
initializationValues ArrayInitializationValues,
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 {
initializationValues.location = parser.token.Location()
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
// arguments
err = parser.nextToken(validArgumentStartTokens...)
if err != nil { return }
for {
// stop parsing this line and go on to the next if a
// newline token is encountered
if parser.token.Is(lexer.TokenKindNewline) {
err = parser.nextToken()
if err != nil { return }
break
}
// otherwise, parse the argument
var argument Argument
argument, err = parser.parseArgument()
if err != nil { return }
initializationValues.values = append (
initializationValues.values,
argument)
}
}
return
}

View File

@ -12,7 +12,7 @@ author "Sasha Koshka"
license "GPLv3" license "GPLv3"
require "` + filepath.Join(cwd, "./some/local/module") + `" require "` + filepath.Join(cwd, "./some/local/module") + `"
require "/some/absolute/path/to/someModule" require "/some/absolute/path/to/someModule"
require "/usr/include/arf/someLibraryInstalledInStandardLocation" require "/usr/local/include/arf/someLibraryInstalledInStandardLocation"
--- ---
`, test) `, test)
} }

View File

@ -1,74 +1,6 @@
package parser package parser
import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
// parseType parses a type notation of the form Name, {Name}, etc.
func (parser *ParsingOperation) parseType () (what Type, err error) {
err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace)
if err != nil { return }
what.location = parser.token.Location()
if parser.token.Is(lexer.TokenKindLBrace) {
what.kind = TypeKindPointer
err = parser.nextToken()
if err != nil { return }
var points Type
points, err = parser.parseType()
if err != nil { return }
what.points = &points
err = parser.expect (
lexer.TokenKindRBrace,
lexer.TokenKindElipsis)
if err != nil { return }
if parser.token.Is(lexer.TokenKindElipsis) {
what.kind = TypeKindVariableArray
err = parser.nextToken(lexer.TokenKindRBrace)
if err != nil { return }
}
err = parser.nextToken()
if err != nil { return }
} else {
what.name, err = parser.parseIdentifier()
if err != nil { return }
}
for {
if !parser.token.Is(lexer.TokenKindColon) { break }
err = parser.nextToken(lexer.TokenKindName, lexer.TokenKindUInt)
if err != nil { return }
if parser.token.Is(lexer.TokenKindName) {
// parse type qualifier
qualifier := parser.token.Value().(string)
switch qualifier {
case "mut":
what.mutable = true
default:
err = parser.token.NewError (
"unknown type qualifier \"" +
qualifier + "\"",
infoerr.ErrorKindError)
return
}
} else {
// parse fixed array length
what.length = parser.token.Value().(uint64)
}
err = parser.nextToken()
if err != nil { return }
}
return
}
// parseIdentifier parses an identifier made out of dot separated names. // parseIdentifier parses an identifier made out of dot separated names.
func (parser *ParsingOperation) parseIdentifier () ( func (parser *ParsingOperation) parseIdentifier () (
@ -80,7 +12,10 @@ func (parser *ParsingOperation) parseIdentifier () (
identifier.location = parser.token.Location() identifier.location = parser.token.Location()
for { for {
if !parser.token.Is(lexer.TokenKindName) { break } if !parser.token.Is(lexer.TokenKindName) {
parser.previousToken()
break
}
identifier.trail = append ( identifier.trail = append (
identifier.trail, identifier.trail,

View File

@ -1,125 +0,0 @@
package parser
import "git.tebibyte.media/arf/arf/types"
import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
// parseObjtSection parses an object type definition. This allows for structured
// types to be defined, and for member variables to be added and overridden.
func (parser *ParsingOperation) parseObjtSection () (
section ObjtSection,
err error,
) {
err = parser.expect(lexer.TokenKindName)
if err != nil { return }
section.location = parser.token.Location()
// 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.inherits, err = parser.parseIdentifier()
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
// parse members
err = parser.parseObjtMembers(&section)
if err != nil { return }
if len(section.members) == 0 {
infoerr.NewError (
section.location,
"defining an object with no members",
infoerr.ErrorKindWarn).Print()
}
return
}
// parseObjtMembers parses a list of members for an object section. Indentation
// level is assumed.
func (parser *ParsingOperation) parseObjtMembers (
into *ObjtSection,
) (
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 }
// add member to object section
var member ObjtMember
member, err = parser.parseObjtMember()
into.members = append(into.members, member)
if err != nil { return }
}
}
// parseObjtMember parses a single member of an object section. Indentation
// level is assumed.
func (parser *ParsingOperation) parseObjtMember () (
member ObjtMember,
err error,
) {
// get permission
err = parser.nextToken(lexer.TokenKindPermission)
if err != nil { return }
member.permission = parser.token.Value().(types.Permission)
// get name
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
member.name = parser.token.Value().(string)
// get type
err = parser.nextToken(lexer.TokenKindColon)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
member.what, err = parser.parseType()
if err != nil { return }
// if there is a bit width, get it
if parser.token.Is(lexer.TokenKindBinaryAnd) {
err = parser.nextToken(lexer.TokenKindUInt)
if err != nil { return }
member.bitWidth = parser.token.Value().(uint64)
err = parser.nextToken()
if err != nil { return }
}
// parse default value
if parser.token.Is(lexer.TokenKindNewline) {
err = parser.nextToken()
if err != nil { return }
member.value,
err = parser.parseInitializationValues(1)
if err != nil { return }
} else {
member.value, err = parser.parseArgument()
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
}
return
}

View File

@ -1,31 +0,0 @@
package parser
import "testing"
func TestObjt (test *testing.T) {
checkTree ("../tests/parser/objt", false,
`:arf
---
objt ro Basic:Obj
ro that:Basic
ro this:Basic
objt ro BitFields:Obj
ro that:Int & 1
ro this:Int & 24 298
objt ro ComplexInit:Obj
ro whatever:Int:3
230984
849
394580
ro complex0:Bird
.that 98
.this 2
ro complex1:Bird
.that 98902
.this 235
ro basic:Int 87
objt ro Init:Obj
ro that:String "hello world"
ro this:Int 23
`, test)
}

View File

@ -166,3 +166,21 @@ func (parser *ParsingOperation) skipIndentLevel (indent int) (err error) {
if err != nil { return } if err != nil { return }
} }
} }
// skipWhitespace skips over newlines and indent tokens.
func (parser *ParsingOperation) skipWhitespace () (err error) {
for {
isWhitespace :=
parser.token.Is(lexer.TokenKindIndent) ||
parser.token.Is(lexer.TokenKindNewline)
if !isWhitespace {
break
}
err = parser.nextToken()
if err != nil { return }
}
return
}

View File

@ -139,25 +139,16 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
err = parser.expect(validDelimitedPhraseTokens...) err = parser.expect(validDelimitedPhraseTokens...)
if err != nil { return } if err != nil { return }
// we are delimited so we can safely skip whitespace
err = parser.skipWhitespace()
if err != nil { return }
if parser.token.Is(lexer.TokenKindRBracket) { if parser.token.Is(lexer.TokenKindRBracket) {
// this is an ending delimiter // this is an ending delimiter
err = parser.nextToken() err = parser.nextToken()
if err != nil { return } if err != nil { return }
break break
} else if parser.token.Is(lexer.TokenKindNewline) {
// we are delimited, so we can safely skip
// newlines
err = parser.nextToken()
if err != nil { return }
continue
} else if parser.token.Is(lexer.TokenKindIndent) {
// we are delimited, so we can safely skip
// indents
err = parser.nextToken()
if err != nil { return }
continue
} }
} else { } else {
// not delimited // not delimited
@ -176,7 +167,7 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
} }
} }
// this is an argument // if we've got this far, we are parsing an argument
var argument Argument var argument Argument
argument, err = parser.parseArgument() argument, err = parser.parseArgument()
phrase.arguments = append(phrase.arguments, argument) phrase.arguments = append(phrase.arguments, argument)
@ -213,18 +204,6 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
err = parser.nextToken() err = parser.nextToken()
if err != nil { return } if err != nil { return }
// if this is a set phrase, parse initialization values under it
if phrase.kind == PhraseKindAssign {
var values Argument
values, err = parser.parseInitializationValues(indent)
if values.kind != ArgumentKindNil {
phrase.arguments = append(phrase.arguments, values)
}
return
}
// if this is a control flow phrase, parse block under it // if this is a control flow phrase, parse block under it
isControlFlow := false isControlFlow := false
for _, kind := range controlFlowKinds { for _, kind := range controlFlowKinds {
@ -234,10 +213,9 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
} }
} }
if !isControlFlow { return } if isControlFlow {
phrase.block, err = parser.parseBlock(indent + 1)
// if it is any of those, parse the block under it }
phrase.block, err = parser.parseBlock(indent + 1)
return return
} }
@ -330,6 +308,8 @@ func (parser *ParsingOperation) parsePhraseCommand () (
identifier := command.value.(Identifier) identifier := command.value.(Identifier)
if len(identifier.trail) == 1 { if len(identifier.trail) == 1 {
switch identifier.trail[0] { switch identifier.trail[0] {
case "let":
kind = PhraseKindLet
case "loc": case "loc":
kind = PhraseKindReference kind = PhraseKindReference
case "defer": case "defer":

View File

@ -66,12 +66,84 @@ func (identifier Identifier) ToString () (output string) {
return return
} }
func (what Type) ToString () (output string) { func (values ObjectDefaultValues) ToString (
indent int,
breakLine bool,
) (
output string,
) {
if !breakLine { indent = 0 }
output += doIndent(indent, "(")
if breakLine { output += "\n" }
for index, name := range sortMapKeysAlphabetically(values) {
if index > 0 && !breakLine { output += " " }
value := values[name]
output += doIndent(indent, "." + name + ":")
isComplexDefaultValue :=
value.kind == ArgumentKindObjectDefaultValues ||
value.kind == ArgumentKindArrayDefaultValues
if isComplexDefaultValue {
if breakLine { output += "\n" }
output += value.ToString(indent + 1, breakLine)
} else {
output += "<"
output += value.ToString(indent + 1, false)
output += ">"
}
if breakLine { output += "\n" }
}
output += doIndent(indent, ")")
return
}
func (values ArrayDefaultValues) ToString (
indent int,
breakLine bool,
) (
output string,
) {
if !breakLine { indent = 0 }
output += doIndent(indent, "<")
if breakLine { output += "\n" }
for index, value := range values {
if index > 0 && !breakLine { output += " " }
output += value.ToString(indent, breakLine)
}
output += doIndent(indent, ">")
return
}
func (member TypeMember) ToString (indent int, breakLine bool) (output string) {
output += doIndent(indent, ".")
output += member.permission.ToString() + " "
output += member.name + ":"
output += member.what.ToString(indent + 1, breakLine)
if member.bitWidth > 0 {
output += fmt.Sprint(" & ", member.bitWidth)
}
if breakLine {
output += "\n"
}
return
}
func (what Type) ToString (indent int, breakLine bool) (output string) {
if what.kind == TypeKindBasic { if what.kind == TypeKindBasic {
output += what.name.ToString() output += what.name.ToString()
} else { } else {
output += "{" output += "{"
output += what.points.ToString() output += what.points.ToString(indent, breakLine)
if what.kind == TypeKindVariableArray { if what.kind == TypeKindVariableArray {
output += " .." output += " .."
@ -87,45 +159,46 @@ func (what Type) ToString () (output string) {
if what.mutable { if what.mutable {
output += ":mut" output += ":mut"
} }
return
}
func (declaration Declaration) ToString () (output string) { if what.members != nil {
output += declaration.name + ":" if breakLine {
output += declaration.what.ToString() output += ":\n" + doIndent(indent, "(\n")
return for _, member := range what.members {
} output += member.ToString(indent, breakLine)
}
func (attributes ObjectInitializationValues) ToString ( output += doIndent(indent, ")")
indent int,
) (
output string,
) {
for _, name := range sortMapKeysAlphabetically(attributes.attributes) {
value := attributes.attributes[name]
output += doIndent(indent, ".", name)
if value.kind == ArgumentKindObjectInitializationValues {
output += "\n"
output += value.ToString(indent + 1, true)
} else { } else {
output += " " + value.ToString(0, false) + "\n" output += ":("
for index, member := range what.members {
if index > 0 { output += " " }
output += member.ToString(indent, breakLine)
}
output += ")"
}
}
defaultValueKind := what.defaultValue.kind
if defaultValueKind != ArgumentKindNil {
isComplexDefaultValue :=
defaultValueKind == ArgumentKindObjectDefaultValues ||
defaultValueKind == ArgumentKindArrayDefaultValues
if isComplexDefaultValue {
output += ":"
if breakLine { output += "\n" }
output += what.defaultValue.ToString(indent, breakLine)
} else {
output += ":<"
output += what.defaultValue.ToString(indent, false)
output += ">"
} }
} }
return return
} }
func (values ArrayInitializationValues) ToString ( func (declaration Declaration) ToString (indent int) (output string) {
indent int, output += declaration.name + ":"
) ( output += declaration.what.ToString(indent, false)
output string,
) {
for _, value := range values.values {
output += value.ToString(indent, true)
}
return return
} }
@ -143,15 +216,13 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
indent, indent,
breakLine) breakLine)
case ArgumentKindObjectInitializationValues: case ArgumentKindObjectDefaultValues:
// this should only appear in contexts where breakLine is true output += argument.value.(ObjectDefaultValues).
output += argument.value.(ObjectInitializationValues). ToString(indent, breakLine)
ToString(indent)
case ArgumentKindArrayInitializationValues: case ArgumentKindArrayDefaultValues:
// this should only appear in contexts where breakLine is true output += argument.value.(ArrayDefaultValues).
output += argument.value.(ArrayInitializationValues). ToString(indent, breakLine)
ToString(indent)
case ArgumentKindIdentifier: case ArgumentKindIdentifier:
output += doIndent ( output += doIndent (
@ -162,7 +233,7 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
case ArgumentKindDeclaration: case ArgumentKindDeclaration:
output += doIndent ( output += doIndent (
indent, indent,
argument.value.(Declaration).ToString()) argument.value.(Declaration).ToString(indent))
if breakLine { output += "\n" } if breakLine { output += "\n" }
case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat: case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat:
@ -260,24 +331,12 @@ func (section DataSection) ToString (indent int) (output string) {
"data ", "data ",
section.permission.ToString(), " ", section.permission.ToString(), " ",
section.name, ":", section.name, ":",
section.what.ToString()) section.what.ToString(indent + 1, true), "\n")
isComplexInitialization :=
section.value.kind == ArgumentKindObjectInitializationValues ||
section.value.kind == ArgumentKindArrayInitializationValues
if section.external { if section.external {
output += "\n"
output += doIndent(indent + 1, "external\n") output += doIndent(indent + 1, "external\n")
} else if section.value.value == nil {
output += "\n"
} else if isComplexInitialization {
output += "\n"
output += section.value.ToString(indent + 1, true)
} else {
output += " " + section.value.ToString(0, false)
output += "\n"
} }
return return
} }
@ -287,65 +346,10 @@ func (section TypeSection) ToString (indent int) (output string) {
"type ", "type ",
section.permission.ToString(), " ", section.permission.ToString(), " ",
section.name, ":", section.name, ":",
section.what.ToString()) section.what.ToString(indent + 1, true), "\n")
isComplexInitialization :=
section.value.kind == ArgumentKindObjectInitializationValues ||
section.value.kind == ArgumentKindArrayInitializationValues
if section.value.value == nil {
output += "\n"
} else if isComplexInitialization {
output += "\n"
output += section.value.ToString(indent + 1, true)
} else {
output += " " + section.value.ToString(0, false)
output += "\n"
}
return return
} }
func (member ObjtMember) ToString (indent int) (output string) {
output += doIndent(indent)
output += member.permission.ToString() + " "
output += member.name + ":"
output += member.what.ToString()
if member.bitWidth > 0 {
output += fmt.Sprint(" & ", member.bitWidth)
}
isComplexInitialization :=
member.value.kind == ArgumentKindObjectInitializationValues ||
member.value.kind == ArgumentKindArrayInitializationValues
if member.value.value == nil {
output += "\n"
} else if isComplexInitialization {
output += "\n"
output += member.value.ToString(indent + 1, true)
} else {
output += " " + member.value.ToString(0, false)
output += "\n"
}
return
}
func (section ObjtSection) ToString (indent int) (output string) {
output += doIndent (
indent,
"objt ",
section.permission.ToString(), " ",
section.name, ":",
section.inherits.ToString(), "\n")
for _, member := range section.members {
output += member.ToString(indent + 1)
}
return
}
func (section EnumSection) ToString (indent int) (output string) { func (section EnumSection) ToString (indent int) (output string) {
output += doIndent ( output += doIndent (
@ -353,24 +357,22 @@ func (section EnumSection) ToString (indent int) (output string) {
"enum ", "enum ",
section.permission.ToString(), " ", section.permission.ToString(), " ",
section.name, ":", section.name, ":",
section.what.ToString(), "\n") section.what.ToString(indent + 1, true), "\n")
for _, member := range section.members { for _, member := range section.members {
output += doIndent(indent + 1, member.name) output += doIndent(indent + 1, "- ", member.name)
isComplexInitialization := isComplexInitialization :=
member.value.kind == ArgumentKindObjectInitializationValues || member.value.kind == ArgumentKindObjectDefaultValues ||
member.value.kind == ArgumentKindArrayInitializationValues member.value.kind == ArgumentKindArrayDefaultValues
if member.value.value == nil { if isComplexInitialization {
output += "\n" output += ":\n"
} else if isComplexInitialization {
output += "\n"
output += member.value.ToString(indent + 2, true) output += member.value.ToString(indent + 2, true)
} else { } else if member.value.kind != ArgumentKindNil {
output += " " + member.value.ToString(0, false) output += ":<" + member.value.ToString(0, false) + ">"
output += "\n"
} }
output += "\n"
} }
return return
} }
@ -394,11 +396,11 @@ 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 {
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n") output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n")
} }
for _, outputItem := range behavior.outputs { for _, outputItem := range behavior.outputs {
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n") output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
} }
return return
@ -409,18 +411,9 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
output += doIndent(indent) output += doIndent(indent)
} }
var initializationValues Argument
output += "[" + phrase.command.ToString(0, false) output += "[" + phrase.command.ToString(0, false)
for _, argument := range phrase.arguments { for _, argument := range phrase.arguments {
isInitializationValue := output += " " + argument.ToString(0, false)
argument.kind == ArgumentKindObjectInitializationValues ||
argument.kind == ArgumentKindArrayInitializationValues
if isInitializationValue {
initializationValues = argument
} else {
output += " " + argument.ToString(0, false)
}
} }
output += "]" output += "]"
@ -433,10 +426,9 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
if ownLine { if ownLine {
output += "\n" output += "\n"
if initializationValues.kind != ArgumentKindNil {
output += initializationValues.ToString(indent + 1, true)
}
output += phrase.block.ToString(indent + 1) output += phrase.block.ToString(indent + 1)
} else if len(phrase.block) > 0 {
output += "NON-BLOCK-LEVEL-PHRASE-HAS-BLOCK"
} }
return return
} }
@ -449,14 +441,6 @@ func (block Block) ToString (indent int) (output string) {
return return
} }
func (funcOutput FuncOutput) ToString () (output string) {
output += funcOutput.Declaration.ToString()
if funcOutput.value.kind != ArgumentKindNil {
output += " " + funcOutput.value.ToString(0, false)
}
return
}
func (section FuncSection) ToString (indent int) (output string) { func (section FuncSection) ToString (indent int) (output string) {
output += doIndent ( output += doIndent (
indent, indent,
@ -467,15 +451,15 @@ func (section FuncSection) ToString (indent int) (output string) {
if section.receiver != nil { if section.receiver != nil {
output += doIndent ( output += doIndent (
indent + 1, indent + 1,
"@ ", section.receiver.ToString(), "\n") "@ ", section.receiver.ToString(indent), "\n")
} }
for _, inputItem := range section.inputs { for _, inputItem := range section.inputs {
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n") output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n")
} }
for _, outputItem := range section.outputs { for _, outputItem := range section.outputs {
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n") output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
} }
output += doIndent(indent + 1, "---\n") output += doIndent(indent + 1, "---\n")

View File

@ -20,7 +20,6 @@ type SectionKind int
const ( const (
SectionKindType = iota SectionKindType = iota
SectionKindObjt
SectionKindEnum SectionKindEnum
SectionKindFace SectionKindFace
SectionKindData SectionKindData
@ -48,17 +47,27 @@ type Identifier struct {
type TypeKind int type TypeKind int
const ( const (
// TypeKindBasic either means it's a primitive, or it inherits from // TypeKindBasic means its a normal type and inherits from something.
// something. // Basic types can define new members on their parent types.
TypeKindBasic TypeKind = iota TypeKindBasic TypeKind = iota
// TypeKindPointer means it's a pointer // TypeKindPointer means it's a pointer.
TypeKindPointer TypeKindPointer
// TypeKindVariableArray means it's an array of variable length. // TypeKindVariableArray means it's an array of variable length.
TypeKindVariableArray TypeKindVariableArray
) )
// TypeMember represents a member variable of a type specifier.
type TypeMember struct {
locatable
nameable
typeable
permissionable
bitWidth uint64
}
// Type represents a type specifier // Type represents a type specifier
type Type struct { type Type struct {
locatable locatable
@ -72,6 +81,12 @@ type Type struct {
// not applicable for basic. // not applicable for basic.
points *Type points *Type
// if non-nil, this type defines new members.
members []TypeMember
// the default value of the type.
defaultValue Argument
} }
// Declaration represents a variable declaration. // Declaration represents a variable declaration.
@ -81,19 +96,12 @@ type Declaration struct {
typeable typeable
} }
// ObjectInitializationValues represents a list of object member initialization // ObjectDefaultValues represents a list of object member initialization
// attributes. // attributes.
type ObjectInitializationValues struct { type ObjectDefaultValues map[string] Argument
locatable
attributes map[string] Argument
}
// ArrayInitializationValues represents a list of attributes initializing an // ArrayDefaultValues represents a list of elements initializing an array.
// array. type ArrayDefaultValues []Argument
type ArrayInitializationValues struct {
locatable
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
// cast to. // cast to.
@ -113,12 +121,12 @@ const (
// {name 23} // {name 23}
ArgumentKindSubscript ArgumentKindSubscript
// .name value // (.name <value>)
// but like, a lot of them // (.name <value> .name (.name <value))
ArgumentKindObjectInitializationValues ArgumentKindObjectDefaultValues
// value value... // <4 32 98 5>
ArgumentKindArrayInitializationValues ArgumentKindArrayDefaultValues
// name.name // name.name
// name.name.name // name.name.name
@ -168,39 +176,16 @@ type DataSection struct {
nameable nameable
typeable typeable
permissionable permissionable
valuable
external bool external bool
} }
// TypeSection represents a blind type definition. // TypeSection represents a type definition.
type TypeSection struct { type TypeSection struct {
locatable locatable
nameable nameable
typeable typeable
permissionable permissionable
valuable
}
// ObjtMember represents a part of an object type definition.
type ObjtMember struct {
locatable
nameable
typeable
permissionable
valuable
bitWidth uint64
}
// ObjtSection represents an object type definition.
type ObjtSection struct {
locatable
nameable
permissionable
inherits Identifier
members []ObjtMember
} }
// EnumMember represents a member of an enum section. // EnumMember represents a member of an enum section.
@ -246,6 +231,7 @@ const (
PhraseKindCall = iota PhraseKindCall = iota
PhraseKindCallExternal PhraseKindCallExternal
PhraseKindOperator PhraseKindOperator
PhraseKindLet
PhraseKindAssign PhraseKindAssign
PhraseKindReference PhraseKindReference
PhraseKindDefer PhraseKindDefer
@ -275,13 +261,6 @@ type Phrase struct {
// Block represents a scoped/indented block of code. // Block represents a scoped/indented block of code.
type Block []Phrase type Block []Phrase
// FuncOutput represents an input a function section. It is unlike an input in
// that it can have a default value.
type FuncOutput struct {
Declaration
valuable
}
// FuncSection represents a function section. // FuncSection represents a function section.
type FuncSection struct { type FuncSection struct {
locatable locatable
@ -290,7 +269,7 @@ type FuncSection struct {
receiver *Declaration receiver *Declaration
inputs []Declaration inputs []Declaration
outputs []FuncOutput outputs []Declaration
root Block root Block
external bool external bool

318
parser/type-notation.go Normal file
View File

@ -0,0 +1,318 @@
package parser
import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
import "git.tebibyte.media/arf/arf/types"
// parseType parses a type notation of the form Name, {Name}, etc.
func (parser *ParsingOperation) parseType () (what Type, err error) {
err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace)
if err != nil { return }
what.location = parser.token.Location()
if parser.token.Is(lexer.TokenKindLBrace) {
what.kind = TypeKindPointer
err = parser.nextToken()
if err != nil { return }
var points Type
points, err = parser.parseType()
if err != nil { return }
what.points = &points
err = parser.expect (
lexer.TokenKindRBrace,
lexer.TokenKindElipsis)
if err != nil { return }
if parser.token.Is(lexer.TokenKindElipsis) {
what.kind = TypeKindVariableArray
err = parser.nextToken(lexer.TokenKindRBrace)
if err != nil { return }
}
err = parser.nextToken()
if err != nil { return }
} else {
what.name, err = parser.parseIdentifier()
if err != nil { return }
}
for {
if !parser.token.Is(lexer.TokenKindColon) { break }
err = parser.nextToken()
if err != nil { return }
err = parser.skipWhitespace()
if err != nil { return }
err = parser.expect(
lexer.TokenKindName,
lexer.TokenKindUInt,
lexer.TokenKindLParen,
lexer.TokenKindLessThan)
if err != nil { return }
if parser.token.Is(lexer.TokenKindName) {
// parse type qualifier
qualifier := parser.token.Value().(string)
switch qualifier {
case "mut":
what.mutable = true
default:
err = parser.token.NewError (
"unknown type qualifier \"" +
qualifier + "\"",
infoerr.ErrorKindError)
return
}
err = parser.nextToken()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindUInt) {
// parse fixed array length
what.length = parser.token.Value().(uint64)
err = parser.nextToken()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindLessThan) {
// parse default value
what.defaultValue, err = parser.parseBasicDefaultValue()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindLParen) {
// parse members and member default values
what.defaultValue,
what.members,
err = parser.parseObjectDefaultValueAndMembers()
if err != nil { return }
}
}
return
}
// parseBasicDefaultValue parses a default value of a non-object type.
func (parser *ParsingOperation) parseBasicDefaultValue () (
value Argument,
err error,
) {
value.location = parser.token.Location()
err = parser.expect(lexer.TokenKindLessThan)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
var attributes []Argument
defer func () {
// if we have multiple values, we need to return the full array
// instead.
if len(attributes) > 1 {
value.kind = ArgumentKindArrayDefaultValues
value.value = ArrayDefaultValues(attributes)
}
} ()
for {
err = parser.skipWhitespace()
if err != nil { return }
if parser.token.Is(lexer.TokenKindGreaterThan) { break }
value, err = parser.parseArgument()
if err != nil { return }
attributes = append(attributes, value)
}
err = parser.nextToken()
if err != nil { return }
return
}
// parseObjectDefaultValueAndMembers parses default values and new members of an
// object type.
func (parser *ParsingOperation) parseObjectDefaultValueAndMembers () (
value Argument,
members []TypeMember,
err error,
) {
value.location = parser.token.Location()
err = parser.expect(lexer.TokenKindLParen)
if err != nil { return }
parser.nextToken()
if err != nil { return }
var attributes ObjectDefaultValues
for {
err = parser.skipWhitespace()
if err != nil { return }
if parser.token.Is(lexer.TokenKindRParen) { break }
err = parser.expect(lexer.TokenKindDot)
if err != nil { return }
parser.nextToken(lexer.TokenKindName, lexer.TokenKindPermission)
if err != nil { return }
if parser.token.Is(lexer.TokenKindName) {
// parsing a defalut value for an inherited member
var memberName string
var memberValue Argument
memberName,
memberValue, err = parser.parseObjectInheritedMember()
if err != nil { return }
if value.kind == ArgumentKindNil {
// create default value map if it doesn't
// already exist
value.kind = ArgumentKindObjectDefaultValues
attributes = make(ObjectDefaultValues)
value.value = attributes
}
// TODO: error on duplicate
if memberValue.kind != ArgumentKindNil {
attributes[memberName] = memberValue
}
} else if parser.token.Is(lexer.TokenKindPermission) {
// parsing a member declaration
var member TypeMember
member, err = parser.parseObjectNewMember()
// TODO: error on duplicate
members = append(members, member)
if err != nil { return }
}
}
err = parser.nextToken()
if err != nil { return }
return
}
// parseObjectDefaultValue parses member default values only, and will throw an
// error when it encounteres a new member definition.
func (parser *ParsingOperation) parseObjectDefaultValue () (
value Argument,
err error,
) {
value.location = parser.token.Location()
err = parser.expect(lexer.TokenKindLParen)
if err != nil { return }
parser.nextToken()
if err != nil { return }
var attributes ObjectDefaultValues
for {
err = parser.skipWhitespace()
if err != nil { return }
if parser.token.Is(lexer.TokenKindRParen) { break }
err = parser.expect(lexer.TokenKindDot)
if err != nil { return }
parser.nextToken(lexer.TokenKindName)
if err != nil { return }
if value.kind == ArgumentKindNil {
value.kind = ArgumentKindObjectDefaultValues
attributes = make(ObjectDefaultValues)
value.value = attributes
}
var memberName string
var memberValue Argument
memberName,
memberValue, err = parser.parseObjectInheritedMember()
attributes[memberName] = memberValue
}
err = parser.nextToken()
if err != nil { return }
return
}
// .name:<value>
// parseObjectInheritedMember parses a new default value for an inherited
// member.
func (parser *ParsingOperation) parseObjectInheritedMember () (
name string,
value Argument,
err error,
) {
// get the name of the inherited member
err = parser.expect(lexer.TokenKindName)
value.location = parser.token.Location()
if err != nil { return }
name = parser.token.Value().(string)
// we require a default value to be present
err = parser.nextToken(lexer.TokenKindColon)
if err != nil { return }
err = parser.nextToken(lexer.TokenKindLParen, lexer.TokenKindLessThan)
if err != nil { return }
if parser.token.Is(lexer.TokenKindLessThan) {
// parse default value
value, err = parser.parseBasicDefaultValue()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindLParen) {
// parse member default values
value, err = parser.parseObjectDefaultValue()
if err != nil { return }
}
return
}
// .ro name:Type:qualifier:<value>
// parseObjectNewMember parses an object member declaration, and its
// default value if it exists.
func (parser *ParsingOperation) parseObjectNewMember () (
member TypeMember,
err error,
) {
// get member permission
err = parser.expect(lexer.TokenKindPermission)
member.location = parser.token.Location()
if err != nil { return }
member.permission = parser.token.Value().(types.Permission)
// get member name
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
member.name = parser.token.Value().(string)
// get type
err = parser.nextToken(lexer.TokenKindColon)
if err != nil { return }
err = parser.nextToken(lexer.TokenKindName, lexer.TokenKindLBrace)
if err != nil { return }
member.what, err = parser.parseType()
if err != nil { return }
// get bit width
if parser.token.Is(lexer.TokenKindBinaryAnd) {
err = parser.nextToken(lexer.TokenKindUInt)
if err != nil { return }
member.bitWidth = parser.token.Value().(uint64)
err = parser.nextToken()
if err != nil { return }
}
return
}

View File

@ -32,21 +32,10 @@ func (parser *ParsingOperation) parseTypeSection () (
section.what, err = parser.parseType() section.what, err = parser.parseType()
if err != nil { return } if err != nil { return }
// parse default values parser.expect(lexer.TokenKindNewline)
if parser.token.Is(lexer.TokenKindNewline) { if err != nil { return }
err = parser.nextToken() err = parser.nextToken()
if err != nil { return } if err != nil { return }
section.value, err = parser.parseInitializationValues(0)
if err != nil { return }
} else {
section.value, err = parser.parseArgument()
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
}
return return
} }

View File

@ -6,12 +6,55 @@ func TestType (test *testing.T) {
checkTree ("../tests/parser/type", false, checkTree ("../tests/parser/type", false,
`:arf `:arf
--- ---
type ro Basic:Int type ro aBasic:Obj:
type ro BasicInit:Int 6 (
type ro IntArray:{Int ..} .ro that:Int
type ro IntArrayInit:Int:3 .ro this:Int
)
type ro bBitFields:Obj:
(
.ro that:Int & 1
.ro this:Int:<298> & 24
)
type ro cInit:Obj:
(
.ro that:String:<"hello world">
.ro this:Int:<23>
)
type ro dInitInherit:aBasic:
(
.that:<9384>
.this:<389>
)
type ro eInitAndDefine:aBasic:
(
.ro these:aBasic:
(
.ro born:Int:<4>
.ro in:Int
.ro the:Int:3:
<
9348
92384
92834
>
):
(
.this:<98>
)
):
(
.that:<9384>
.this:<389>
)
type ro fBasic:Int
type ro gBasicInit:Int:<6>
type ro hIntArray:{Int ..}
type ro iIntArrayInit:Int:3:
<
3298 3298
923 923
92 92
>
`, test) `, test)
} }

View File

@ -1,3 +1,3 @@
:arf :arf
--- rw -> -349820394 932748397 239485.37520 "hello world!\n" 'E' helloWorld:.,..[]{} --- rw -> -349820394 932748397 239485.37520 "hello world!\n" 'E' helloWorld:.,..()[]{}
+ - ++ -- * / @ ! % %= ~ ~= = == != < <= << <<= > >= >> >>= | |= || & &= && ^ ^= + - ++ -- * / @ ! % %= ~ ~= = == != < <= << <<= > >= >> >>= | |= || & &= && ^ ^=

View File

@ -1,9 +1,9 @@
:arf :arf
--- ---
data ro aInteger:Int 3202 data ro aInteger:Int:<3202>
data ro bMutInteger:Int:mut 3202 data ro bMutInteger:Int:mut:<3202>
data ro cIntegerPointer:{Int} data ro cIntegerPointer:{Int}
@ -13,34 +13,33 @@ data ro eIntegerArray16:Int:16
data ro fIntegerArrayVariable:{Int ..} data ro fIntegerArrayVariable:{Int ..}
data ro gIntegerArrayInitialized:Int:16 data ro gIntegerArrayInitialized:Int:16:<
3948 293 293049 948 912 3948 293 293049 948 912
340 0 2304 0 4785 92 340 0 2304 0 4785 92
>
# TODO: reinstate these two after phrase parsing is implemented data rw hIntegerPointerInit:{Int}:<[& integer]>
# data wr hIntegerPointerInit:{Int} [& integer]
# data wr iMutIntegerPointerInit:{Int}:mut [& integer] data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
# TODO: maybe test identifiers somewhere else? data ro jObject:Obj:(
data ro jObject:thing.Thing. .this:<324>
thing.thing .that:<324>)
.this 324
.that 2139
data ro kNestedObject:Obj data ro kNestedObject:Obj:(
.this .this:(
.bird0 324 .bird0:<324>
.bird1 "hello world" .bird1:<"hello world">)
.that .ro newMember:Int:<9023>
.bird2 123.8439 .that:(
.bird3 9328.21348239 .bird2:<123.8439>
.bird3:<9328.21348239>))
data ro lMutIntegerArray16:Int:16:mut data ro lMutIntegerArray16:Int:16:mut
data ro mExternalData:Int:8 data ro mExternalData:Int:8
external external
data ro nIntegerArrayInitialized:Int:16:mut data ro nIntegerArrayInitialized:Int:16:mut:
3948 293 293049 948 912 <3948 293 293049 948 912
340 0 2304 0 4785 92 340 0 2304 0 4785 92>

View File

@ -2,29 +2,35 @@
--- ---
enum ro Weekday:Int enum ro Weekday:Int
sunday - sunday
monday - monday
tuesday - tuesday
wednesday - wednesday
thursday - thursday
friday - friday
saturday - saturday
enum ro NamedColor:U32 enum ro NamedColor:U32
red 0xFF0000 - red: <0xFF0000>
green 0x00FF00 - green: <0x00FF00>
blue 0x0000FF - blue: <0x0000FF>
enum ro AffrontToGod:Int:4 enum ro AffrontToGod:Int:4
bird0 - bird0:
28394 9328 <28394 9328
398 9 398 9>
bird1 - bird1:
23 932832 <23 932832
398 398
2349 2349>
bird2 - bird2:
1 <1
2 2
3 3
4 4>
enum ro ThisIsTerrible:Obj:(.rw x:Int .rw y:Int)
- up: (.x:< 0> .y:<-1>)
- down: (.x:< 0> .y:< 1>)
- left: (.x:<-1> .y:< 0>)
- right: (.x:< 1> .y:< 0>)

View File

@ -2,14 +2,14 @@
--- ---
func ro aBasicExternal func ro aBasicExternal
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int 4 < someOutput:Int:<4>
--- ---
external external
func ro bMethod func ro bMethod
@ bird:{Bird} @ bird:{Bird}
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int 4 < someOutput:Int:<4>
--- ---
external external
@ -124,13 +124,12 @@ func ro gControlFlow
func ro hSetPhrase func ro hSetPhrase
--- ---
= x:Int 3 let x:Int:<3>
# loc is a reference, similar to * in C # loc is a reference, similar to * in C
= y:{Int} [loc x] let y:{Int}:<[loc x]>
= z:Int:8 let z:Int:8:
398 9 2309 983 -2387 <398 9 2309 983 -2387
478 555 123 478 555 123>
= bird:Bird let bird:Bird:(
.that .that:(.whenYou:<99999>)
.whenYou 99999 .this:<324>)
.this 324

View File

@ -1,25 +0,0 @@
:arf
---
objt ro Basic:Obj
ro that:Basic
ro this:Basic
objt ro BitFields:Obj
ro that:Int & 1
ro this:Int & 24 298
objt ro Init:Obj
ro that:String "hello world"
ro this:Int 23
objt ro ComplexInit:Obj
ro whatever:Int:3
230984
849 394580
ro complex0:Bird
.that 98
.this 2
ro complex1:Bird
.that 98902
.this 235
ro basic:Int 87

View File

@ -7,12 +7,12 @@ data ro aExternalData:Int
data ro bSingleValue:Int 342 data ro bSingleValue:Int 342
data ro cNestedObject:Obj data ro cNestedObject:Obj
.this -- this
.bird0 324 -- bird0 324
.bird1 "hello world" -- bird1 "hello world"
.that -- that
.bird2 123.8439 -- bird2 123.8439
.bird3 9328.21348239 -- bird3 9328.21348239
data ro dUninitialized:Int:16:mut data ro dUninitialized:Int:16:mut
@ -28,9 +28,9 @@ func ro fComplexFunction
398 9 2309 983 -2387 398 9 2309 983 -2387
478 555 123 478 555 123
= bird:Bird = bird:Bird
.that -- that
.whenYou 99999 -- whenYou 99999
.this 324 -- this 324
func ro gExternalFunction func ro gExternalFunction
> x:Int > x:Int

View File

@ -1,10 +1,35 @@
:arf :arf
--- ---
type ro Basic:Int type ro aBasic:Obj:(
.ro that:Int
.ro this:Int)
type ro BasicInit:Int 6 type ro bBitFields:Obj:(
.ro that:Int & 1
.ro this:Int:<298> & 24)
type ro IntArray:{Int ..} type ro cInit:Obj:(
.ro that:String:<"hello world">
.ro this:Int:<23>)
type ro IntArrayInit:Int:3 type ro dInitInherit:aBasic:(
3298 923 92 .that:<9384>
.this:<389>)
type ro eInitAndDefine:aBasic:(
.this:<389>
.ro these:aBasic:(
.ro born:Int:<4>
.ro in:Int
.ro the:Int:3:<9348 92384 92834>
.this:<98>)
.that:<9384>)
type ro fBasic:Int
type ro gBasicInit:Int:<6>
type ro hIntArray:{Int ..}
type ro iIntArrayInit:Int:3:
<3298 923 92>