revert-complexity #7
|
@ -29,33 +29,49 @@ func (analyzer AnalysisOperation) analyzeArgument (
|
||||||
) {
|
) {
|
||||||
switch inputArgument.Kind() {
|
switch inputArgument.Kind() {
|
||||||
case parser.ArgumentKindNil:
|
case parser.ArgumentKindNil:
|
||||||
|
panic (
|
||||||
|
"invalid state: attempt to analyze nil argument")
|
||||||
|
|
||||||
case parser.ArgumentKindPhrase:
|
case parser.ArgumentKindPhrase:
|
||||||
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindDereference:
|
case parser.ArgumentKindDereference:
|
||||||
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindSubscript:
|
case parser.ArgumentKindSubscript:
|
||||||
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindObjectDefaultValues:
|
case parser.ArgumentKindObjectDefaultValues:
|
||||||
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindArrayDefaultValues:
|
case parser.ArgumentKindArrayDefaultValues:
|
||||||
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindIdentifier:
|
case parser.ArgumentKindIdentifier:
|
||||||
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindDeclaration:
|
case parser.ArgumentKindDeclaration:
|
||||||
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindInt:
|
case parser.ArgumentKindInt:
|
||||||
|
outputArgument = IntLiteral(inputArgument.Value().(int64))
|
||||||
|
|
||||||
case parser.ArgumentKindUInt:
|
case parser.ArgumentKindUInt:
|
||||||
|
outputArgument = UIntLiteral(inputArgument.Value().(uint64))
|
||||||
|
|
||||||
case parser.ArgumentKindFloat:
|
case parser.ArgumentKindFloat:
|
||||||
|
outputArgument = FloatLiteral(inputArgument.Value().(float64))
|
||||||
|
|
||||||
case parser.ArgumentKindString:
|
case parser.ArgumentKindString:
|
||||||
|
outputArgument = StringLiteral(inputArgument.Value().(string))
|
||||||
|
|
||||||
case parser.ArgumentKindRune:
|
case parser.ArgumentKindRune:
|
||||||
|
outputArgument = RuneLiteral(inputArgument.Value().(rune))
|
||||||
|
|
||||||
case parser.ArgumentKindOperator:
|
case parser.ArgumentKindOperator:
|
||||||
|
panic (
|
||||||
|
"invalid state: attempt to analyze operator argument " +
|
||||||
|
"directly")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,22 +82,22 @@ func (what Type) Points () (points Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// MembersLength returns the amount of new members the type specifier defines.
|
// MembersLength returns the amount of new members the type section defines.
|
||||||
// If it defines no new members, it returns zero.
|
// If it defines no new members, it returns zero.
|
||||||
func (what Type) MembersLength () (length int) {
|
func (section TypeSection) MembersLength () (length int) {
|
||||||
length = len(what.members)
|
length = len(section.members)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Member returns the member at index.
|
// Member returns the member at index.
|
||||||
func (what Type) Member (index int) (member TypeMember) {
|
func (section TypeSection) Member (index int) (member TypeSectionMember) {
|
||||||
member = what.members[index]
|
member = section.members[index]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// BitWidth returns the bit width of the type member. If it is zero, it should
|
// BitWidth returns the bit width of the type member. If it is zero, it should
|
||||||
// be treated as unspecified.
|
// be treated as unspecified.
|
||||||
func (member TypeMember) BitWidth () (width uint64) {
|
func (member TypeSectionMember) BitWidth () (width uint64) {
|
||||||
width = member.bitWidth
|
width = member.bitWidth
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -169,18 +169,6 @@ func (phrase Phrase) Kind () (kind PhraseKind) {
|
||||||
return
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReturneesLength returns the amount of things the phrase returns to.
|
// ReturneesLength returns the amount of things the phrase returns to.
|
||||||
func (phrase Phrase) ReturneesLength () (length int) {
|
func (phrase Phrase) ReturneesLength () (length int) {
|
||||||
length = len(phrase.returnees)
|
length = len(phrase.returnees)
|
||||||
|
|
|
@ -3,6 +3,8 @@ 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: add support for dereferences and subscripts
|
||||||
|
|
||||||
var validArgumentStartTokens = []lexer.TokenKind {
|
var validArgumentStartTokens = []lexer.TokenKind {
|
||||||
lexer.TokenKindName,
|
lexer.TokenKindName,
|
||||||
|
|
||||||
|
@ -13,6 +15,7 @@ var validArgumentStartTokens = []lexer.TokenKind {
|
||||||
lexer.TokenKindRune,
|
lexer.TokenKindRune,
|
||||||
|
|
||||||
lexer.TokenKindLBracket,
|
lexer.TokenKindLBracket,
|
||||||
|
lexer.TokenKindLParen,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (parser *ParsingOperation) parseArgument () (argument Argument, err error) {
|
func (parser *ParsingOperation) parseArgument () (argument Argument, err error) {
|
||||||
|
@ -84,6 +87,10 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error)
|
||||||
argument.kind = ArgumentKindPhrase
|
argument.kind = ArgumentKindPhrase
|
||||||
argument.value, err = parser.parseArgumentLevelPhrase()
|
argument.value, err = parser.parseArgumentLevelPhrase()
|
||||||
|
|
||||||
|
case lexer.TokenKindLParen:
|
||||||
|
argument.kind = ArgumentKindList
|
||||||
|
argument.value, err = parser.parseList()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic (
|
panic (
|
||||||
"unimplemented argument kind " +
|
"unimplemented argument kind " +
|
||||||
|
|
|
@ -35,28 +35,37 @@ func (parser *ParsingOperation) parseDataSection () (
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = parser.expect(lexer.TokenKindNewline)
|
// see if value exists
|
||||||
if err != nil { return }
|
if parser.token.Is(lexer.TokenKindNewline) {
|
||||||
err = parser.nextToken()
|
parser.nextToken()
|
||||||
if err != nil { return }
|
// if we have exited the section, return
|
||||||
|
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(lexer.TokenKindName)
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if external
|
||||||
|
if parser.token.Is(lexer.TokenKindName) {
|
||||||
if parser.token.Value().(string) == "external" {
|
if parser.token.Value().(string) == "external" {
|
||||||
|
|
||||||
section.external = true
|
section.external = true
|
||||||
|
|
||||||
err = parser.nextToken(lexer.TokenKindNewline)
|
err = parser.nextToken(lexer.TokenKindNewline)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.previousToken()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get value
|
||||||
|
section.argument, err = parser.parseArgument()
|
||||||
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,16 @@ 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
|
||||||
data ro bMutInteger:Int:mut:<3202>
|
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
|
||||||
|
@ -25,35 +27,21 @@ data ro gIntegerArrayInitialized:Int:16:
|
||||||
0
|
0
|
||||||
4785
|
4785
|
||||||
92
|
92
|
||||||
>
|
|
||||||
data rw hIntegerPointerInit:{Int}:<[& integer]>
|
|
||||||
data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
|
|
||||||
data ro jObject:Obj:
|
|
||||||
(
|
|
||||||
.that:<324>
|
|
||||||
.this:<324>
|
|
||||||
)
|
)
|
||||||
data ro kNestedObject:Obj:
|
data rw hIntegerPointerInit:{Int}
|
||||||
|
[& integer]
|
||||||
|
data rw iMutIntegerPointerInit:{Int}:mut
|
||||||
|
[& integer]
|
||||||
|
data ro jObject:Obj
|
||||||
(
|
(
|
||||||
.ro newMember:Int:<9023>
|
324
|
||||||
):
|
438
|
||||||
(
|
|
||||||
.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
|
||||||
|
@ -65,6 +53,6 @@ data ro nIntegerArrayInitialized:Int:16:mut:
|
||||||
0
|
0
|
||||||
4785
|
4785
|
||||||
92
|
92
|
||||||
>
|
)
|
||||||
`, test)
|
`, test)
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,18 +61,11 @@ 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)
|
|
||||||
if err != nil { return }
|
|
||||||
|
|
||||||
var member EnumMember
|
var member EnumMember
|
||||||
member, err = parser.parseEnumMember()
|
member, err = parser.parseEnumMember()
|
||||||
into.members = append(into.members, member)
|
into.members = append(into.members, member)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
err = parser.expect(lexer.TokenKindNewline)
|
|
||||||
if err != nil { return }
|
|
||||||
err = parser.nextToken()
|
|
||||||
if err != nil { return }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +74,7 @@ func (parser *ParsingOperation) parseEnumMember () (
|
||||||
member EnumMember,
|
member EnumMember,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindMinus)
|
err = parser.nextToken(lexer.TokenKindMinus)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
// get name
|
// get name
|
||||||
|
@ -91,32 +84,25 @@ func (parser *ParsingOperation) parseEnumMember () (
|
||||||
member.name = parser.token.Value().(string)
|
member.name = parser.token.Value().(string)
|
||||||
|
|
||||||
// see if value exists
|
// see if value exists
|
||||||
err = parser.nextToken (
|
err = parser.nextToken()
|
||||||
lexer.TokenKindColon,
|
|
||||||
lexer.TokenKindNewline)
|
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
if parser.token.Is(lexer.TokenKindNewline) {
|
||||||
if parser.token.Is(lexer.TokenKindColon) {
|
parser.nextToken()
|
||||||
|
// if we have exited the member, return
|
||||||
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
|
if parser.token.Value().(int) != 2 { return }
|
||||||
|
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
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 }
|
|
||||||
|
|
||||||
} else if parser.token.Is(lexer.TokenKindLParen) {
|
|
||||||
// parse default values
|
|
||||||
member.value, err = parser.parseObjectDefaultValue()
|
|
||||||
if err != nil { return }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get value
|
||||||
|
member.argument, err = parser.parseArgument()
|
||||||
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,56 +7,18 @@ func TestEnum (test *testing.T) {
|
||||||
`:arf
|
`:arf
|
||||||
---
|
---
|
||||||
enum ro AffrontToGod:Int:4
|
enum ro AffrontToGod:Int:4
|
||||||
- bird0:
|
- bird0 (28394 9328 398 9)
|
||||||
<
|
- bird1 (23 932832 398 2349)
|
||||||
28394
|
- bird2 (1 2 3 4)
|
||||||
9328
|
|
||||||
398
|
|
||||||
9
|
|
||||||
>
|
|
||||||
- bird1:
|
|
||||||
<
|
|
||||||
23
|
|
||||||
932832
|
|
||||||
398
|
|
||||||
2349
|
|
||||||
>
|
|
||||||
- bird2:
|
|
||||||
<
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
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:
|
enum ro ThisIsTerrible:Vector
|
||||||
(
|
- up (0 -1)
|
||||||
.rw x:Int
|
- down (0 1)
|
||||||
.rw y:Int
|
- left (-1 0)
|
||||||
)
|
- right (1 0)
|
||||||
- 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
|
||||||
|
|
|
@ -12,8 +12,7 @@ func (parser *ParsingOperation) parseFaceSection () (
|
||||||
err = parser.expect(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
section.behaviors = make(map[string] FaceBehavior)
|
section.location = parser.token.Location()
|
||||||
section.location = parser.token.Location()
|
|
||||||
|
|
||||||
// get permission
|
// get permission
|
||||||
err = parser.nextToken(lexer.TokenKindPermission)
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
|
@ -32,24 +31,61 @@ func (parser *ParsingOperation) parseFaceSection () (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
section.inherits, err = parser.parseIdentifier()
|
section.inherits, err = parser.parseIdentifier()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.nextToken(lexer.TokenKindNewline)
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
|
if parser.token.Value().(int) != 1 { return }
|
||||||
|
|
||||||
|
err = parser.nextToken (
|
||||||
|
lexer.TokenKindName,
|
||||||
|
lexer.TokenKindGreaterThan,
|
||||||
|
lexer.TokenKindLessThan)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
if parser.token.Is(lexer.TokenKindName) {
|
||||||
|
// parse type interface
|
||||||
|
section.kind = FaceKindType
|
||||||
|
parser.previousToken()
|
||||||
|
section.behaviors, err = parser.parseFaceBehaviors()
|
||||||
|
if err != nil { return }
|
||||||
|
} else {
|
||||||
|
// parse function interface
|
||||||
|
section.kind = FaceKindFunc
|
||||||
|
parser.previousToken()
|
||||||
|
section.inputs,
|
||||||
|
section.outputs, err = parser.parseFaceBehaviorArguments(1)
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseFaceBehaviors parses a list of interface behaviors for an object
|
||||||
|
// interface.
|
||||||
|
func (parser *ParsingOperation) parseFaceBehaviors () (
|
||||||
|
behaviors map[string] FaceBehavior,
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
// parse members
|
// parse members
|
||||||
|
behaviors = make(map[string] FaceBehavior)
|
||||||
for {
|
for {
|
||||||
// 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.TokenKindName)
|
||||||
|
behaviorBeginning := parser.token.Location()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
// parse behavior
|
// parse behavior
|
||||||
behaviorBeginning := parser.token.Location()
|
|
||||||
var behavior FaceBehavior
|
var behavior FaceBehavior
|
||||||
behavior, err = parser.parseFaceBehavior()
|
behavior, err = parser.parseFaceBehavior(1)
|
||||||
|
|
||||||
// add to section
|
// add to section
|
||||||
_, exists := section.behaviors[behavior.name]
|
_, exists := behaviors[behavior.name]
|
||||||
if exists {
|
if exists {
|
||||||
err = infoerr.NewError (
|
err = infoerr.NewError (
|
||||||
behaviorBeginning,
|
behaviorBeginning,
|
||||||
|
@ -58,23 +94,21 @@ func (parser *ParsingOperation) parseFaceSection () (
|
||||||
infoerr.ErrorKindError)
|
infoerr.ErrorKindError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
section.behaviors[behavior.name] = behavior
|
behaviors[behavior.name] = behavior
|
||||||
|
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseFaceBehavior parses a single interface behavior. Indentation level is
|
// parseFaceBehavior parses a single interface behavior.
|
||||||
// assumed.
|
func (parser *ParsingOperation) parseFaceBehavior (
|
||||||
func (parser *ParsingOperation) parseFaceBehavior () (
|
indent int,
|
||||||
|
) (
|
||||||
behavior FaceBehavior,
|
behavior FaceBehavior,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = parser.expect(lexer.TokenKindIndent)
|
|
||||||
if err != nil { return }
|
|
||||||
|
|
||||||
// get name
|
// get name
|
||||||
err = parser.nextToken(lexer.TokenKindName)
|
err = parser.expect(lexer.TokenKindName)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
behavior.name = parser.token.Value().(string)
|
behavior.name = parser.token.Value().(string)
|
||||||
|
|
||||||
|
@ -82,11 +116,27 @@ func (parser *ParsingOperation) parseFaceBehavior () (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
|
behavior.inputs,
|
||||||
|
behavior.outputs,
|
||||||
|
err = parser.parseFaceBehaviorArguments(indent + 1)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (parser *ParsingOperation) parseFaceBehaviorArguments (
|
||||||
|
indent int,
|
||||||
|
) (
|
||||||
|
inputs []Declaration,
|
||||||
|
outputs []Declaration,
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// if we've left the block, stop parsing
|
// if we've left the behavior, stop parsing
|
||||||
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
if parser.token.Value().(int) != 2 { return }
|
if parser.token.Value().(int) != indent { return }
|
||||||
|
|
||||||
// get preceding symbol
|
// get preceding symbol
|
||||||
err = parser.nextToken (
|
err = parser.nextToken (
|
||||||
|
@ -109,19 +159,16 @@ func (parser *ParsingOperation) parseFaceBehavior () (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
declaration.what, err = parser.parseType()
|
declaration.what, err = parser.parseType()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
|
if kind == lexer.TokenKindGreaterThan {
|
||||||
|
inputs = append(inputs, declaration)
|
||||||
|
} else {
|
||||||
|
outputs = append(outputs, declaration)
|
||||||
|
}
|
||||||
|
|
||||||
err = parser.expect(lexer.TokenKindNewline)
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
if kind == lexer.TokenKindGreaterThan {
|
|
||||||
behavior.inputs = append (
|
|
||||||
behavior.inputs,
|
|
||||||
declaration)
|
|
||||||
} else {
|
|
||||||
behavior.outputs = append (
|
|
||||||
behavior.outputs,
|
|
||||||
declaration)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
parser/face_test.go
Normal file
25
parser/face_test.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestFace (test *testing.T) {
|
||||||
|
checkTree ("../tests/parser/face", false,
|
||||||
|
`:arf
|
||||||
|
---
|
||||||
|
face ro aReadWriter:Face
|
||||||
|
read
|
||||||
|
> into:{Byte ..}
|
||||||
|
< read:Int
|
||||||
|
< err:Error
|
||||||
|
write
|
||||||
|
> data:{Byte ..}
|
||||||
|
< wrote:Int
|
||||||
|
< err:Error
|
||||||
|
face ro bDestroyer:Face
|
||||||
|
destroy
|
||||||
|
face ro cFuncInterface:Func
|
||||||
|
> something:Int
|
||||||
|
< someOutput:Int
|
||||||
|
< otherOutput:String
|
||||||
|
`, test)
|
||||||
|
}
|
|
@ -171,7 +171,7 @@ func (parser *ParsingOperation) parseFuncArguments (
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
case lexer.TokenKindLessThan:
|
case lexer.TokenKindLessThan:
|
||||||
output := Declaration { }
|
output := FuncOutput { }
|
||||||
output.location = parser.token.Location()
|
output.location = parser.token.Location()
|
||||||
|
|
||||||
// get name
|
// get name
|
||||||
|
@ -186,11 +186,32 @@ 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 }
|
||||||
|
|
||||||
into.outputs = append(into.outputs, output)
|
|
||||||
|
|
||||||
parser.expect(lexer.TokenKindNewline)
|
// skip newline if it is there
|
||||||
|
if parser.token.Is(lexer.TokenKindNewline) {
|
||||||
|
parser.nextToken()
|
||||||
|
// if we have exited the output, break
|
||||||
|
exited :=
|
||||||
|
!parser.token.Is(lexer.TokenKindIndent) ||
|
||||||
|
parser.token.Value().(int) != 2
|
||||||
|
|
||||||
|
if exited {
|
||||||
|
into.outputs = append(into.outputs, output)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
// get default value
|
||||||
|
output.argument, err = parser.parseArgument()
|
||||||
|
into.outputs = append(into.outputs, output)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -99,11 +99,11 @@ func ro gControlFlow
|
||||||
[nestedThing]
|
[nestedThing]
|
||||||
[else]
|
[else]
|
||||||
[otherThing]
|
[otherThing]
|
||||||
func ro hSetPhrase
|
func ro hDataInit
|
||||||
---
|
---
|
||||||
[let x:Int:<3>]
|
[= x:Int 3]
|
||||||
[let y:{Int}:<[loc x]>]
|
[= y:{Int} [loc x]]
|
||||||
[let z:Int:8:<398 9 2309 983 -2387 478 555 123>]
|
[= z:Int:8 (398 9 2309 983 -2387 478 555 123)]
|
||||||
[let bird:Bird:(.that:(.whenYou:<99999>) .this:<324>)]
|
[= bird:Bird ((99999) 324)]
|
||||||
`, test)
|
`, test)
|
||||||
}
|
}
|
||||||
|
|
32
parser/list.go
Normal file
32
parser/list.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import "git.tebibyte.media/arf/arf/lexer"
|
||||||
|
|
||||||
|
// parseList parses a parenthetically delimited list of arguments.
|
||||||
|
func (parser *ParsingOperation) parseList () (list List, err error) {
|
||||||
|
list.location = parser.token.Location()
|
||||||
|
|
||||||
|
err = parser.expect(lexer.TokenKindLParen)
|
||||||
|
if err != nil { return }
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
for {
|
||||||
|
err = parser.skipWhitespace()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
// if we have reached the end of the list, stop
|
||||||
|
if parser.token.Is(lexer.TokenKindRParen) { break }
|
||||||
|
|
||||||
|
// otherwise, parse argument
|
||||||
|
var argument Argument
|
||||||
|
argument, err = parser.parseArgument()
|
||||||
|
list.arguments = append(list.arguments, argument)
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
|
@ -11,8 +11,8 @@ func TestMeta (test *testing.T) {
|
||||||
author "Sasha Koshka"
|
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 "/usr/local/include/arf/someLibraryInstalledInStandardLocation"
|
require "/usr/local/include/arf/someLibraryInstalledInStandardLocation"
|
||||||
|
require "/some/absolute/path/to/someModule"
|
||||||
---
|
---
|
||||||
`, test)
|
`, test)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,19 +10,19 @@ type locatable struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Location returns the location of the node.
|
// Location returns the location of the node.
|
||||||
func (trait locatable) Location () (location file.Location) {
|
func (node locatable) Location () (location file.Location) {
|
||||||
location = trait.location
|
location = node.location
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewError creates a new error at the node's location.
|
// NewError creates a new error at the node's location.
|
||||||
func (trait locatable) NewError (
|
func (node locatable) NewError (
|
||||||
message string,
|
message string,
|
||||||
kind infoerr.ErrorKind,
|
kind infoerr.ErrorKind,
|
||||||
) (
|
) (
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
err = infoerr.NewError(trait.location, message, kind)
|
err = infoerr.NewError(node.location, message, kind)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ type nameable struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the node.
|
// Name returns the name of the node.
|
||||||
func (trait nameable) Name () (name string) {
|
func (node nameable) Name () (name string) {
|
||||||
name = trait.name
|
name = node.name
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// typeable allows a node to have a type.
|
// typeable allows a node to have a type.
|
||||||
|
@ -42,8 +42,8 @@ type typeable struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the type of the node.
|
// Type returns the type of the node.
|
||||||
func (trait typeable) Type () (what Type) {
|
func (node typeable) Type () (what Type) {
|
||||||
what = trait.what
|
what = node.what
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,18 +53,35 @@ type permissionable struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permission returns the permision of the node.
|
// Permission returns the permision of the node.
|
||||||
func (trait permissionable) Permission () (permission types.Permission) {
|
func (node permissionable) Permission () (permission types.Permission) {
|
||||||
permission = trait.permission
|
permission = node.permission
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// valuable allows a node to have an argument value.
|
// valuable allows a node to have an argument value.
|
||||||
type valuable struct {
|
type valuable struct {
|
||||||
value Argument
|
argument Argument
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returns the value argument of the node.
|
// Argument returns the value argument of the node.
|
||||||
func (trait valuable) Value () (value Argument) {
|
func (node valuable) Argument () (argument Argument) {
|
||||||
value = trait.value
|
argument = node.argument
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiValuable allows a node to have several argument values.
|
||||||
|
type multiValuable struct {
|
||||||
|
arguments []Argument
|
||||||
|
}
|
||||||
|
|
||||||
|
// Argument returns the argument at index.
|
||||||
|
func (node multiValuable) Argument (index int) (argument Argument) {
|
||||||
|
argument = node.arguments[index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length returns the amount of arguments in the mode.
|
||||||
|
func (node multiValuable) Length () (length int) {
|
||||||
|
length = len(node.arguments)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,16 +150,35 @@ func (parser *ParsingOperation) previousToken () {
|
||||||
// skipIndentLevel advances the parser, ignoring every line with an indentation
|
// skipIndentLevel advances the parser, ignoring every line with an indentation
|
||||||
// equal to or greater than the specified indent.
|
// equal to or greater than the specified indent.
|
||||||
func (parser *ParsingOperation) skipIndentLevel (indent int) (err error) {
|
func (parser *ParsingOperation) skipIndentLevel (indent int) (err error) {
|
||||||
|
braceLevel := 0
|
||||||
|
parenLevel := 0
|
||||||
|
bracketLevel := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if parser.token.Is(lexer.TokenKindNewline) {
|
if parser.token.Is(lexer.TokenKindNewline) {
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
if !parser.token.Is(lexer.TokenKindIndent) ||
|
shouldBreak :=
|
||||||
parser.token.Value().(int) < indent {
|
!parser.token.Is(lexer.TokenKindIndent) ||
|
||||||
|
parser.token.Value().(int) < indent
|
||||||
|
|
||||||
|
shouldBreak =
|
||||||
|
shouldBreak &&
|
||||||
|
braceLevel < 1 &&
|
||||||
|
parenLevel < 1 &&
|
||||||
|
bracketLevel < 1
|
||||||
|
|
||||||
return
|
if shouldBreak { return }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch parser.token.Kind() {
|
||||||
|
case lexer.TokenKindLBrace: braceLevel ++
|
||||||
|
case lexer.TokenKindRBrace: braceLevel --
|
||||||
|
case lexer.TokenKindLParen: parenLevel ++
|
||||||
|
case lexer.TokenKindRParen: parenLevel --
|
||||||
|
case lexer.TokenKindLBracket: bracketLevel ++
|
||||||
|
case lexer.TokenKindRBracket: bracketLevel --
|
||||||
}
|
}
|
||||||
|
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
|
|
|
@ -129,7 +129,10 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
|
||||||
// get command
|
// get command
|
||||||
err = parser.expect(validPhraseStartTokens...)
|
err = parser.expect(validPhraseStartTokens...)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
phrase.command, phrase.kind, err = parser.parsePhraseCommand()
|
phrase.command,
|
||||||
|
phrase.kind,
|
||||||
|
phrase.operator,
|
||||||
|
err = parser.parsePhraseCommand()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -233,7 +236,10 @@ func (parser *ParsingOperation) parseArgumentLevelPhrase () (
|
||||||
// get command
|
// get command
|
||||||
err = parser.nextToken(validPhraseStartTokens...)
|
err = parser.nextToken(validPhraseStartTokens...)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
phrase.command, phrase.kind, err = parser.parsePhraseCommand()
|
phrase.command,
|
||||||
|
phrase.kind,
|
||||||
|
phrase.operator,
|
||||||
|
err = parser.parsePhraseCommand()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -272,24 +278,22 @@ func (parser *ParsingOperation) parseArgumentLevelPhrase () (
|
||||||
|
|
||||||
// parsePhraseCommand parses the command argument of a phrase.
|
// parsePhraseCommand parses the command argument of a phrase.
|
||||||
func (parser *ParsingOperation) parsePhraseCommand () (
|
func (parser *ParsingOperation) parsePhraseCommand () (
|
||||||
command Argument,
|
command Argument,
|
||||||
kind PhraseKind,
|
kind PhraseKind,
|
||||||
err error,
|
operator lexer.TokenKind,
|
||||||
|
err error,
|
||||||
) {
|
) {
|
||||||
if isTokenOperator(parser.token) {
|
if isTokenOperator(parser.token) {
|
||||||
err = parser.expect(operatorTokens...)
|
err = parser.expect(operatorTokens...)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
command.location = parser.token.Location()
|
|
||||||
command.kind = ArgumentKindOperator
|
|
||||||
command.value = parser.token.Kind()
|
|
||||||
|
|
||||||
if parser.token.Is(lexer.TokenKindColon) {
|
if parser.token.Is(lexer.TokenKindColon) {
|
||||||
kind = PhraseKindCase
|
kind = PhraseKindCase
|
||||||
} else if parser.token.Is(lexer.TokenKindAssignment) {
|
} else if parser.token.Is(lexer.TokenKindAssignment) {
|
||||||
kind = PhraseKindAssign
|
kind = PhraseKindAssign
|
||||||
} else {
|
} else {
|
||||||
kind = PhraseKindOperator
|
kind = PhraseKindOperator
|
||||||
|
operator = parser.token.Kind()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
|
@ -308,8 +312,6 @@ 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":
|
||||||
|
|
|
@ -21,7 +21,7 @@ func ro fComplexFunction
|
||||||
external
|
external
|
||||||
func ro gExternalFunction
|
func ro gExternalFunction
|
||||||
> x:Int
|
> x:Int
|
||||||
< arr:Int
|
< arr:Int 5
|
||||||
---
|
---
|
||||||
external
|
external
|
||||||
`, test)
|
`, test)
|
||||||
|
|
|
@ -41,7 +41,8 @@ func (tree SyntaxTree) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, "license \"", tree.license, "\"\n")
|
output += doIndent(indent, "license \"", tree.license, "\"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, require := range tree.requires {
|
for _, name := range sortMapKeysAlphabetically(tree.requires) {
|
||||||
|
require := tree.requires[name]
|
||||||
output += doIndent(indent, "require \"", require, "\"\n")
|
output += doIndent(indent, "require \"", require, "\"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,84 +67,17 @@ func (identifier Identifier) ToString () (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (values ObjectDefaultValues) ToString (
|
func (what Type) ToString () (output string) {
|
||||||
indent int,
|
if what.kind == TypeKindNil {
|
||||||
breakLine bool,
|
output += "NIL-TYPE"
|
||||||
) (
|
return
|
||||||
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(indent, breakLine)
|
output += what.points.ToString()
|
||||||
|
|
||||||
if what.kind == TypeKindVariableArray {
|
if what.kind == TypeKindVariableArray {
|
||||||
output += " .."
|
output += " .."
|
||||||
|
@ -159,46 +93,27 @@ func (what Type) ToString (indent int, breakLine bool) (output string) {
|
||||||
if what.mutable {
|
if what.mutable {
|
||||||
output += ":mut"
|
output += ":mut"
|
||||||
}
|
}
|
||||||
|
|
||||||
if what.members != nil {
|
|
||||||
if breakLine {
|
|
||||||
output += ":\n" + doIndent(indent, "(\n")
|
|
||||||
for _, member := range what.members {
|
|
||||||
output += member.ToString(indent, breakLine)
|
|
||||||
}
|
|
||||||
output += doIndent(indent, ")")
|
|
||||||
} else {
|
|
||||||
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 (declaration Declaration) ToString (indent int) (output string) {
|
func (declaration Declaration) ToString () (output string) {
|
||||||
output += declaration.name + ":"
|
output += declaration.name + ":"
|
||||||
output += declaration.what.ToString(indent, false)
|
output += declaration.what.ToString()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list List) ToString (indent int, breakline bool) (output string) {
|
||||||
|
if !breakline { indent = 0 }
|
||||||
|
output += doIndent(indent, "(")
|
||||||
|
if breakline { output += "\n" }
|
||||||
|
|
||||||
|
for index, argument := range list.arguments {
|
||||||
|
if !breakline && index > 0 { output += " "}
|
||||||
|
output += argument.ToString(indent, breakline)
|
||||||
|
}
|
||||||
|
|
||||||
|
output += doIndent(indent, ")")
|
||||||
|
if breakline { output += "\n" }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,13 +131,8 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
|
||||||
indent,
|
indent,
|
||||||
breakLine)
|
breakLine)
|
||||||
|
|
||||||
case ArgumentKindObjectDefaultValues:
|
case ArgumentKindList:
|
||||||
output += argument.value.(ObjectDefaultValues).
|
output += argument.value.(List).ToString(indent, breakLine)
|
||||||
ToString(indent, breakLine)
|
|
||||||
|
|
||||||
case ArgumentKindArrayDefaultValues:
|
|
||||||
output += argument.value.(ArrayDefaultValues).
|
|
||||||
ToString(indent, breakLine)
|
|
||||||
|
|
||||||
case ArgumentKindIdentifier:
|
case ArgumentKindIdentifier:
|
||||||
output += doIndent (
|
output += doIndent (
|
||||||
|
@ -233,7 +143,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(indent))
|
argument.value.(Declaration).ToString())
|
||||||
if breakLine { output += "\n" }
|
if breakLine { output += "\n" }
|
||||||
|
|
||||||
case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat:
|
case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat:
|
||||||
|
@ -251,75 +161,6 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
|
||||||
indent,
|
indent,
|
||||||
"'" + string(argument.value.(rune)) + "'")
|
"'" + string(argument.value.(rune)) + "'")
|
||||||
if breakLine { output += "\n" }
|
if breakLine { output += "\n" }
|
||||||
|
|
||||||
case ArgumentKindOperator:
|
|
||||||
var stringValue string
|
|
||||||
switch argument.value.(lexer.TokenKind) {
|
|
||||||
case lexer.TokenKindColon:
|
|
||||||
stringValue = ":"
|
|
||||||
case lexer.TokenKindPlus:
|
|
||||||
stringValue = "+"
|
|
||||||
case lexer.TokenKindMinus:
|
|
||||||
stringValue = "-"
|
|
||||||
case lexer.TokenKindIncrement:
|
|
||||||
stringValue = "++"
|
|
||||||
case lexer.TokenKindDecrement:
|
|
||||||
stringValue = "--"
|
|
||||||
case lexer.TokenKindAsterisk:
|
|
||||||
stringValue = "*"
|
|
||||||
case lexer.TokenKindSlash:
|
|
||||||
stringValue = "/"
|
|
||||||
case lexer.TokenKindExclamation:
|
|
||||||
stringValue = "!"
|
|
||||||
case lexer.TokenKindPercent:
|
|
||||||
stringValue = "%"
|
|
||||||
case lexer.TokenKindPercentAssignment:
|
|
||||||
stringValue = "%="
|
|
||||||
case lexer.TokenKindTilde:
|
|
||||||
stringValue = "~"
|
|
||||||
case lexer.TokenKindTildeAssignment:
|
|
||||||
stringValue = "~="
|
|
||||||
case lexer.TokenKindAssignment:
|
|
||||||
stringValue = "="
|
|
||||||
case lexer.TokenKindEqualTo:
|
|
||||||
stringValue = "=="
|
|
||||||
case lexer.TokenKindNotEqualTo:
|
|
||||||
stringValue = "!="
|
|
||||||
case lexer.TokenKindLessThanEqualTo:
|
|
||||||
stringValue = "<="
|
|
||||||
case lexer.TokenKindLessThan:
|
|
||||||
stringValue = "<"
|
|
||||||
case lexer.TokenKindLShift:
|
|
||||||
stringValue = "<<"
|
|
||||||
case lexer.TokenKindLShiftAssignment:
|
|
||||||
stringValue = "<<="
|
|
||||||
case lexer.TokenKindGreaterThan:
|
|
||||||
stringValue = ">"
|
|
||||||
case lexer.TokenKindGreaterThanEqualTo:
|
|
||||||
stringValue = ">="
|
|
||||||
case lexer.TokenKindRShift:
|
|
||||||
stringValue = ">>"
|
|
||||||
case lexer.TokenKindRShiftAssignment:
|
|
||||||
stringValue = ">>="
|
|
||||||
case lexer.TokenKindBinaryOr:
|
|
||||||
stringValue = "|"
|
|
||||||
case lexer.TokenKindBinaryOrAssignment:
|
|
||||||
stringValue = "|="
|
|
||||||
case lexer.TokenKindLogicalOr:
|
|
||||||
stringValue = "||"
|
|
||||||
case lexer.TokenKindBinaryAnd:
|
|
||||||
stringValue = "&"
|
|
||||||
case lexer.TokenKindBinaryAndAssignment:
|
|
||||||
stringValue = "&="
|
|
||||||
case lexer.TokenKindLogicalAnd:
|
|
||||||
stringValue = "&&"
|
|
||||||
case lexer.TokenKindBinaryXor:
|
|
||||||
stringValue = "^"
|
|
||||||
case lexer.TokenKindBinaryXorAssignment:
|
|
||||||
stringValue = "^="
|
|
||||||
}
|
|
||||||
output += doIndent(indent, stringValue)
|
|
||||||
if breakLine { output += "\n" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -331,7 +172,11 @@ func (section DataSection) ToString (indent int) (output string) {
|
||||||
"data ",
|
"data ",
|
||||||
section.permission.ToString(), " ",
|
section.permission.ToString(), " ",
|
||||||
section.name, ":",
|
section.name, ":",
|
||||||
section.what.ToString(indent + 1, true), "\n")
|
section.what.ToString(), "\n")
|
||||||
|
|
||||||
|
if section.argument.kind != ArgumentKindNil {
|
||||||
|
output += section.argument.ToString(indent + 1, true)
|
||||||
|
}
|
||||||
|
|
||||||
if section.external {
|
if section.external {
|
||||||
output += doIndent(indent + 1, "external\n")
|
output += doIndent(indent + 1, "external\n")
|
||||||
|
@ -340,37 +185,57 @@ func (section DataSection) ToString (indent int) (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (member TypeSectionMember) ToString (indent int) (output string) {
|
||||||
|
output += doIndent(indent, member.permission.ToString())
|
||||||
|
output += " " + member.name
|
||||||
|
|
||||||
|
if member.what.kind != TypeKindNil {
|
||||||
|
output += ":" + member.what.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if member.argument.kind != ArgumentKindNil {
|
||||||
|
output += " " + member.argument.ToString(indent, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if member.bitWidth > 0 {
|
||||||
|
output += fmt.Sprint(" & ", member.bitWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "\n"
|
||||||
|
|
||||||
|
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.what.ToString(indent + 1, true), "\n")
|
section.what.ToString(), "\n")
|
||||||
|
|
||||||
|
if section.argument.kind != ArgumentKindNil {
|
||||||
|
output += section.argument.ToString(indent + 1, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, member := range section.members {
|
||||||
|
output += member.ToString(indent + 1)
|
||||||
|
}
|
||||||
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 ",
|
||||||
section.permission.ToString(), " ",
|
section.permission.ToString(), " ",
|
||||||
section.name, ":",
|
section.name, ":",
|
||||||
section.what.ToString(indent + 1, true), "\n")
|
section.what.ToString(), "\n")
|
||||||
|
|
||||||
for _, member := range section.members {
|
for _, member := range section.members {
|
||||||
output += doIndent(indent + 1, "- ", member.name)
|
output += doIndent(indent + 1, "- ", member.name)
|
||||||
|
if member.argument.kind != ArgumentKindNil {
|
||||||
isComplexInitialization :=
|
output += " " + member.argument.ToString(indent, false)
|
||||||
member.value.kind == ArgumentKindObjectDefaultValues ||
|
|
||||||
member.value.kind == ArgumentKindArrayDefaultValues
|
|
||||||
|
|
||||||
if isComplexInitialization {
|
|
||||||
output += ":\n"
|
|
||||||
output += member.value.ToString(indent + 2, true)
|
|
||||||
} else if member.value.kind != ArgumentKindNil {
|
|
||||||
output += ":<" + member.value.ToString(0, false) + ">"
|
|
||||||
}
|
}
|
||||||
output += "\n"
|
output += "\n"
|
||||||
}
|
}
|
||||||
|
@ -385,10 +250,21 @@ func (section FaceSection) ToString (indent int) (output string) {
|
||||||
section.name, ":",
|
section.name, ":",
|
||||||
section.inherits.ToString(), "\n")
|
section.inherits.ToString(), "\n")
|
||||||
|
|
||||||
for _, name := range sortMapKeysAlphabetically(section.behaviors) {
|
if section.kind == FaceKindType {
|
||||||
behavior := section.behaviors[name]
|
for _, name := range sortMapKeysAlphabetically(section.behaviors) {
|
||||||
output += behavior.ToString(indent + 1)
|
behavior := section.behaviors[name]
|
||||||
|
output += behavior.ToString(indent + 1)
|
||||||
|
}
|
||||||
|
} else if section.kind == FaceKindFunc {
|
||||||
|
for _, inputItem := range section.inputs {
|
||||||
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, outputItem := range section.outputs {
|
||||||
|
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,11 +272,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(indent), "\n")
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, outputItem := range behavior.outputs {
|
for _, outputItem := range behavior.outputs {
|
||||||
output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
|
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -411,7 +287,86 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
|
||||||
output += doIndent(indent)
|
output += doIndent(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
output += "[" + phrase.command.ToString(0, false)
|
output += "["
|
||||||
|
|
||||||
|
switch phrase.kind {
|
||||||
|
case PhraseKindCase:
|
||||||
|
output += ":"
|
||||||
|
|
||||||
|
case PhraseKindAssign:
|
||||||
|
output += "="
|
||||||
|
|
||||||
|
case PhraseKindOperator:
|
||||||
|
|
||||||
|
switch phrase.operator {
|
||||||
|
case lexer.TokenKindColon:
|
||||||
|
output += ":"
|
||||||
|
case lexer.TokenKindPlus:
|
||||||
|
output += "+"
|
||||||
|
case lexer.TokenKindMinus:
|
||||||
|
output += "-"
|
||||||
|
case lexer.TokenKindIncrement:
|
||||||
|
output += "++"
|
||||||
|
case lexer.TokenKindDecrement:
|
||||||
|
output += "--"
|
||||||
|
case lexer.TokenKindAsterisk:
|
||||||
|
output += "*"
|
||||||
|
case lexer.TokenKindSlash:
|
||||||
|
output += "/"
|
||||||
|
case lexer.TokenKindExclamation:
|
||||||
|
output += "!"
|
||||||
|
case lexer.TokenKindPercent:
|
||||||
|
output += "%"
|
||||||
|
case lexer.TokenKindPercentAssignment:
|
||||||
|
output += "%="
|
||||||
|
case lexer.TokenKindTilde:
|
||||||
|
output += "~"
|
||||||
|
case lexer.TokenKindTildeAssignment:
|
||||||
|
output += "~="
|
||||||
|
case lexer.TokenKindAssignment:
|
||||||
|
output += "="
|
||||||
|
case lexer.TokenKindEqualTo:
|
||||||
|
output += "=="
|
||||||
|
case lexer.TokenKindNotEqualTo:
|
||||||
|
output += "!="
|
||||||
|
case lexer.TokenKindLessThanEqualTo:
|
||||||
|
output += "<="
|
||||||
|
case lexer.TokenKindLessThan:
|
||||||
|
output += "<"
|
||||||
|
case lexer.TokenKindLShift:
|
||||||
|
output += "<<"
|
||||||
|
case lexer.TokenKindLShiftAssignment:
|
||||||
|
output += "<<="
|
||||||
|
case lexer.TokenKindGreaterThan:
|
||||||
|
output += ">"
|
||||||
|
case lexer.TokenKindGreaterThanEqualTo:
|
||||||
|
output += ">="
|
||||||
|
case lexer.TokenKindRShift:
|
||||||
|
output += ">>"
|
||||||
|
case lexer.TokenKindRShiftAssignment:
|
||||||
|
output += ">>="
|
||||||
|
case lexer.TokenKindBinaryOr:
|
||||||
|
output += "|"
|
||||||
|
case lexer.TokenKindBinaryOrAssignment:
|
||||||
|
output += "|="
|
||||||
|
case lexer.TokenKindLogicalOr:
|
||||||
|
output += "||"
|
||||||
|
case lexer.TokenKindBinaryAnd:
|
||||||
|
output += "&"
|
||||||
|
case lexer.TokenKindBinaryAndAssignment:
|
||||||
|
output += "&="
|
||||||
|
case lexer.TokenKindLogicalAnd:
|
||||||
|
output += "&&"
|
||||||
|
case lexer.TokenKindBinaryXor:
|
||||||
|
output += "^"
|
||||||
|
case lexer.TokenKindBinaryXorAssignment:
|
||||||
|
output += "^="
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
output += phrase.command.ToString(0, false)
|
||||||
|
}
|
||||||
|
|
||||||
for _, argument := range phrase.arguments {
|
for _, argument := range phrase.arguments {
|
||||||
output += " " + argument.ToString(0, false)
|
output += " " + argument.ToString(0, false)
|
||||||
}
|
}
|
||||||
|
@ -433,6 +388,17 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (funcOutput FuncOutput) ToString (indent int) (output string) {
|
||||||
|
output += doIndent(indent + 1)
|
||||||
|
output += "< " + funcOutput.Declaration.ToString()
|
||||||
|
if funcOutput.argument.kind != ArgumentKindNil {
|
||||||
|
output += " " + funcOutput.argument.ToString(indent, false)
|
||||||
|
}
|
||||||
|
output += "\n"
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (block Block) ToString (indent int) (output string) {
|
func (block Block) ToString (indent int) (output string) {
|
||||||
for _, phrase := range block {
|
for _, phrase := range block {
|
||||||
output += phrase.ToString(indent, true)
|
output += phrase.ToString(indent, true)
|
||||||
|
@ -451,15 +417,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(indent), "\n")
|
"@ ", section.receiver.ToString(), "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, inputItem := range section.inputs {
|
for _, inputItem := range section.inputs {
|
||||||
output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n")
|
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, outputItem := range section.outputs {
|
for _, outputItem := range section.outputs {
|
||||||
output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
|
output += outputItem.ToString(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
output += doIndent(indent + 1, "---\n")
|
output += doIndent(indent + 1, "---\n")
|
||||||
|
|
101
parser/tree.go
101
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/lexer"
|
||||||
import "git.tebibyte.media/arf/arf/infoerr"
|
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
|
||||||
|
@ -35,9 +36,12 @@ type Identifier struct {
|
||||||
type TypeKind int
|
type TypeKind int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// TypeKindNil means that the type is unspecified.
|
||||||
|
TypeKindNil TypeKind = iota
|
||||||
|
|
||||||
// TypeKindBasic means its a normal type and inherits from something.
|
// TypeKindBasic means its a normal type and inherits from something.
|
||||||
// Basic types can define new members on their parent types.
|
// Basic types can define new members on their parent types.
|
||||||
TypeKindBasic TypeKind = iota
|
TypeKindBasic
|
||||||
|
|
||||||
// TypeKindPointer means it's a pointer.
|
// TypeKindPointer means it's a pointer.
|
||||||
TypeKindPointer
|
TypeKindPointer
|
||||||
|
@ -46,16 +50,6 @@ const (
|
||||||
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
|
||||||
|
@ -69,12 +63,6 @@ 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.
|
||||||
|
@ -84,12 +72,14 @@ type Declaration struct {
|
||||||
typeable
|
typeable
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectDefaultValues represents a list of object member initialization
|
// List represents an array or object literal.
|
||||||
// attributes.
|
type List struct {
|
||||||
type ObjectDefaultValues map[string] Argument
|
locatable
|
||||||
|
|
||||||
// ArrayDefaultValues represents a list of elements initializing an array.
|
// TODO: have an array of unnamed arguments, and a map of named
|
||||||
type ArrayDefaultValues []Argument
|
// arguments
|
||||||
|
multiValuable
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -103,19 +93,15 @@ const (
|
||||||
// etc...
|
// etc...
|
||||||
ArgumentKindPhrase
|
ArgumentKindPhrase
|
||||||
|
|
||||||
|
// (argument argument argument)
|
||||||
|
ArgumentKindList
|
||||||
|
|
||||||
// {name}
|
// {name}
|
||||||
ArgumentKindDereference
|
ArgumentKindDereference
|
||||||
|
|
||||||
// {name 23}
|
// {name 23}
|
||||||
ArgumentKindSubscript
|
ArgumentKindSubscript
|
||||||
|
|
||||||
// (.name <value>)
|
|
||||||
// (.name <value> .name (.name <value))
|
|
||||||
ArgumentKindObjectDefaultValues
|
|
||||||
|
|
||||||
// <4 32 98 5>
|
|
||||||
ArgumentKindArrayDefaultValues
|
|
||||||
|
|
||||||
// name.name
|
// name.name
|
||||||
// name.name.name
|
// name.name.name
|
||||||
// etc...
|
// etc...
|
||||||
|
@ -142,10 +128,6 @@ const (
|
||||||
|
|
||||||
// 'S'
|
// 'S'
|
||||||
ArgumentKindRune
|
ArgumentKindRune
|
||||||
|
|
||||||
// + - * / etc...
|
|
||||||
// this is only used as a phrase command
|
|
||||||
ArgumentKindOperator
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -164,16 +146,32 @@ type DataSection struct {
|
||||||
nameable
|
nameable
|
||||||
typeable
|
typeable
|
||||||
permissionable
|
permissionable
|
||||||
|
valuable
|
||||||
|
|
||||||
external bool
|
external bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TypeSectionMember represents a member variable of a type section.
|
||||||
|
type TypeSectionMember struct {
|
||||||
|
locatable
|
||||||
|
nameable
|
||||||
|
typeable
|
||||||
|
permissionable
|
||||||
|
valuable
|
||||||
|
|
||||||
|
bitWidth uint64
|
||||||
|
}
|
||||||
|
|
||||||
// TypeSection represents a type definition.
|
// TypeSection represents a type definition.
|
||||||
type TypeSection struct {
|
type TypeSection struct {
|
||||||
locatable
|
locatable
|
||||||
nameable
|
nameable
|
||||||
typeable
|
typeable
|
||||||
permissionable
|
permissionable
|
||||||
|
valuable
|
||||||
|
|
||||||
|
// if non-nil, this type defines new members.
|
||||||
|
members []TypeSectionMember
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumMember represents a member of an enum section.
|
// EnumMember represents a member of an enum section.
|
||||||
|
@ -193,6 +191,16 @@ type EnumSection struct {
|
||||||
members []EnumMember
|
members []EnumMember
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FaceKind determines if an interface is a type interface or an function
|
||||||
|
// interface.
|
||||||
|
type FaceKind int
|
||||||
|
|
||||||
|
const (
|
||||||
|
FaceKindEmpty FaceKind = iota
|
||||||
|
FaceKindType
|
||||||
|
FaceKindFunc
|
||||||
|
)
|
||||||
|
|
||||||
// FaceBehavior represents a behavior of an interface section.
|
// FaceBehavior represents a behavior of an interface section.
|
||||||
type FaceBehavior struct {
|
type FaceBehavior struct {
|
||||||
locatable
|
locatable
|
||||||
|
@ -208,8 +216,11 @@ type FaceSection struct {
|
||||||
nameable
|
nameable
|
||||||
permissionable
|
permissionable
|
||||||
inherits Identifier
|
inherits Identifier
|
||||||
|
|
||||||
|
kind FaceKind
|
||||||
|
|
||||||
behaviors map[string] FaceBehavior
|
behaviors map[string] FaceBehavior
|
||||||
|
FaceBehavior
|
||||||
}
|
}
|
||||||
|
|
||||||
// PhraseKind determines what semantic role a phrase plays.
|
// PhraseKind determines what semantic role a phrase plays.
|
||||||
|
@ -219,7 +230,6 @@ const (
|
||||||
PhraseKindCall = iota
|
PhraseKindCall = iota
|
||||||
PhraseKindCallExternal
|
PhraseKindCallExternal
|
||||||
PhraseKindOperator
|
PhraseKindOperator
|
||||||
PhraseKindLet
|
|
||||||
PhraseKindAssign
|
PhraseKindAssign
|
||||||
PhraseKindReference
|
PhraseKindReference
|
||||||
PhraseKindDefer
|
PhraseKindDefer
|
||||||
|
@ -236,12 +246,18 @@ const (
|
||||||
// syntactical concept.
|
// syntactical concept.
|
||||||
type Phrase struct {
|
type Phrase struct {
|
||||||
location file.Location
|
location file.Location
|
||||||
command Argument
|
|
||||||
arguments []Argument
|
|
||||||
returnees []Argument
|
returnees []Argument
|
||||||
|
multiValuable
|
||||||
|
|
||||||
kind PhraseKind
|
kind PhraseKind
|
||||||
|
|
||||||
|
// TODO: do not have this be an argument. make a string version, and
|
||||||
|
// and identifier version.
|
||||||
|
command Argument
|
||||||
|
|
||||||
|
// only applicable for PhraseKindOperator
|
||||||
|
operator lexer.TokenKind
|
||||||
|
|
||||||
// only applicable for control flow phrases
|
// only applicable for control flow phrases
|
||||||
block Block
|
block Block
|
||||||
}
|
}
|
||||||
|
@ -249,6 +265,13 @@ 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 a function output declaration. It allows for 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
|
||||||
|
@ -257,7 +280,7 @@ type FuncSection struct {
|
||||||
|
|
||||||
receiver *Declaration
|
receiver *Declaration
|
||||||
inputs []Declaration
|
inputs []Declaration
|
||||||
outputs []Declaration
|
outputs []FuncOutput
|
||||||
root Block
|
root Block
|
||||||
|
|
||||||
external bool
|
external bool
|
||||||
|
|
|
@ -2,13 +2,13 @@ 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"
|
||||||
import "git.tebibyte.media/arf/arf/types"
|
|
||||||
|
|
||||||
// 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)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
what.location = parser.token.Location()
|
what.location = parser.token.Location()
|
||||||
|
what.kind = TypeKindBasic
|
||||||
|
|
||||||
if parser.token.Is(lexer.TokenKindLBrace) {
|
if parser.token.Is(lexer.TokenKindLBrace) {
|
||||||
what.kind = TypeKindPointer
|
what.kind = TypeKindPointer
|
||||||
|
@ -48,11 +48,7 @@ func (parser *ParsingOperation) parseType () (what Type, err error) {
|
||||||
err = parser.skipWhitespace()
|
err = parser.skipWhitespace()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
err = parser.expect(
|
err = parser.expect(lexer.TokenKindName, lexer.TokenKindUInt)
|
||||||
lexer.TokenKindName,
|
|
||||||
lexer.TokenKindUInt,
|
|
||||||
lexer.TokenKindLParen,
|
|
||||||
lexer.TokenKindLessThan)
|
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
if parser.token.Is(lexer.TokenKindName) {
|
if parser.token.Is(lexer.TokenKindName) {
|
||||||
|
@ -77,242 +73,8 @@ func (parser *ParsingOperation) parseType () (what Type, err error) {
|
||||||
err = parser.nextToken()
|
err = parser.nextToken()
|
||||||
if err != nil { return }
|
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
|
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
|
|
||||||
}
|
|
||||||
|
|
105
parser/type.go
105
parser/type.go
|
@ -3,8 +3,8 @@ 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"
|
||||||
|
|
||||||
// parseTypeSection parses a blind type definition, meaning it can inherit from
|
// parseTypeSection parses a type definition. It can inherit from other types,
|
||||||
// anything including primitives, but cannot define structure.
|
// and define new members on them.
|
||||||
func (parser *ParsingOperation) parseTypeSection () (
|
func (parser *ParsingOperation) parseTypeSection () (
|
||||||
section TypeSection,
|
section TypeSection,
|
||||||
err error,
|
err error,
|
||||||
|
@ -32,10 +32,103 @@ func (parser *ParsingOperation) parseTypeSection () (
|
||||||
section.what, err = parser.parseType()
|
section.what, err = parser.parseType()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
parser.expect(lexer.TokenKindNewline)
|
// see if value exists
|
||||||
if err != nil { return }
|
if parser.token.Is(lexer.TokenKindNewline) {
|
||||||
err = parser.nextToken()
|
parser.nextToken()
|
||||||
if err != nil { return }
|
// if we have exited the section, return
|
||||||
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
|
if parser.token.Value().(int) != 1 { return }
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have not encountered members, get value and return.
|
||||||
|
if !parser.token.Is(lexer.TokenKindPermission) {
|
||||||
|
section.argument, err = parser.parseArgument()
|
||||||
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.previousToken()
|
||||||
|
|
||||||
|
for {
|
||||||
|
// if we have exited the section, return
|
||||||
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
|
if parser.token.Value().(int) != 1 { return }
|
||||||
|
|
||||||
|
err = parser.nextToken(lexer.TokenKindPermission)
|
||||||
|
if err != nil { return }
|
||||||
|
var member TypeSectionMember
|
||||||
|
member, err = parser.parseTypeSectionMember()
|
||||||
|
section.members = append(section.members, member)
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseTypeSectionMember parses a type section member variable.
|
||||||
|
func (parser *ParsingOperation) parseTypeSectionMember () (
|
||||||
|
member TypeSectionMember,
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
// get permission
|
||||||
|
err = parser.expect(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)
|
||||||
|
|
||||||
|
// if there is a type, get it
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
if parser.token.Is(lexer.TokenKindColon) {
|
||||||
|
err = parser.nextToken(lexer.TokenKindName)
|
||||||
|
if err != nil { return }
|
||||||
|
member.what, err = parser.parseType()
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if value exists
|
||||||
|
if parser.token.Is(lexer.TokenKindNewline) {
|
||||||
|
parser.nextToken()
|
||||||
|
// if we have exited the member, return
|
||||||
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
|
if parser.token.Value().(int) != 2 { return }
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
// if default value exists, get it
|
||||||
|
if !parser.token.Is(lexer.TokenKindBinaryAnd) {
|
||||||
|
member.argument, err = parser.parseArgument()
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is a bit width specifier, 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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -6,55 +6,34 @@ func TestType (test *testing.T) {
|
||||||
checkTree ("../tests/parser/type", false,
|
checkTree ("../tests/parser/type", false,
|
||||||
`:arf
|
`:arf
|
||||||
---
|
---
|
||||||
type ro aBasic:Obj:
|
type ro aBasic:Obj
|
||||||
(
|
ro that:Int
|
||||||
.ro that:Int
|
ro this:Int
|
||||||
.ro this:Int
|
type ro bBitFields:Obj
|
||||||
)
|
ro that:Int & 1
|
||||||
type ro bBitFields:Obj:
|
ro this:Int 298 & 24
|
||||||
(
|
type ro cInit:Obj
|
||||||
.ro that:Int & 1
|
ro that:String "hello world"
|
||||||
.ro this:Int:<298> & 24
|
ro this:Int 23
|
||||||
)
|
type ro dInitInherit:aBasic
|
||||||
type ro cInit:Obj:
|
ro that 9384
|
||||||
(
|
ro this 389
|
||||||
.ro that:String:<"hello world">
|
type ro eInitAndDefine:aBasic
|
||||||
.ro this:Int:<23>
|
ro this 389
|
||||||
)
|
ro that 9384
|
||||||
type ro dInitInherit:aBasic:
|
ro born:Int 4
|
||||||
(
|
ro in:Int
|
||||||
.that:<9384>
|
ro the:Int:3 (9348 92384 92834)
|
||||||
.this:<389>
|
ro walls:String "live in the walls, die in the walls."
|
||||||
)
|
|
||||||
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 fBasic:Int
|
||||||
type ro gBasicInit:Int:<6>
|
type ro gBasicInit:Int
|
||||||
|
6
|
||||||
type ro hIntArray:{Int ..}
|
type ro hIntArray:{Int ..}
|
||||||
type ro iIntArrayInit:Int:3:
|
type ro iIntArrayInit:Int:3
|
||||||
<
|
(
|
||||||
3298
|
3298
|
||||||
923
|
923
|
||||||
92
|
92
|
||||||
>
|
)
|
||||||
`, test)
|
`, test)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,33 +13,30 @@ 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)
|
||||||
>
|
|
||||||
|
|
||||||
data rw hIntegerPointerInit:{Int}:<[& integer]>
|
data rw hIntegerPointerInit:{Int} [& integer]
|
||||||
|
|
||||||
data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
|
data rw iMutIntegerPointerInit:{Int}:mut
|
||||||
|
[& integer]
|
||||||
|
|
||||||
data ro jObject:Obj:(
|
data ro jObject:Obj
|
||||||
.this:<324>
|
(324
|
||||||
.that:<324>)
|
438)
|
||||||
|
|
||||||
data ro kNestedObject:Obj:(
|
# TODO: at some point, have this syntax for object literals. terminate members
|
||||||
.this:(
|
# with newlines.
|
||||||
.bird0:<324>
|
# data ro jObject:Bird (
|
||||||
.bird1:<"hello world">)
|
# .this 324
|
||||||
.ro newMember:Int:<9023>
|
# .that 438)
|
||||||
.that:(
|
|
||||||
.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)
|
||||||
|
|
|
@ -11,26 +11,26 @@ enum ro Weekday:Int
|
||||||
- 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)
|
enum ro ThisIsTerrible:Vector
|
||||||
- up: (.x:< 0> .y:<-1>)
|
- up ( 0 -1)
|
||||||
- down: (.x:< 0> .y:< 1>)
|
- down ( 0 1)
|
||||||
- left: (.x:<-1> .y:< 0>)
|
- left (-1 0)
|
||||||
- right: (.x:< 1> .y:< 0>)
|
- right ( 1 0)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
:arf
|
:arf
|
||||||
---
|
---
|
||||||
|
|
||||||
face ro ReadWriter:Face
|
face ro aReadWriter:Face
|
||||||
write
|
write
|
||||||
> data:{Byte ..}
|
> data:{Byte ..}
|
||||||
< wrote:Int
|
< wrote:Int
|
||||||
|
@ -11,5 +11,10 @@ face ro ReadWriter:Face
|
||||||
< read:Int
|
< read:Int
|
||||||
< err:Error
|
< err:Error
|
||||||
|
|
||||||
face ro Destroyer:Face
|
face ro bDestroyer:Face
|
||||||
destroy
|
destroy
|
||||||
|
|
||||||
|
face ro cFuncInterface:Func
|
||||||
|
> something:Int
|
||||||
|
< someOutput:Int
|
||||||
|
< otherOutput:String
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
@ -122,14 +122,13 @@ func ro gControlFlow
|
||||||
else
|
else
|
||||||
otherThing
|
otherThing
|
||||||
|
|
||||||
func ro hSetPhrase
|
func ro hDataInit
|
||||||
---
|
---
|
||||||
let x:Int:<3>
|
= x:Int 3
|
||||||
# loc is a reference, similar to * in C
|
# loc is a reference, similar to * in C
|
||||||
let y:{Int}:<[loc x]>
|
= y:{Int} [loc x]
|
||||||
let z:Int:8:
|
= z:Int:8 (398 9 2309 983 -2387
|
||||||
<398 9 2309 983 -2387
|
478 555 123)
|
||||||
478 555 123>
|
= bird:Bird (
|
||||||
let bird:Bird:(
|
(99999)
|
||||||
.that:(.whenYou:<99999>)
|
324)
|
||||||
.this:<324>)
|
|
||||||
|
|
|
@ -6,37 +6,33 @@ data ro aExternalData:Int
|
||||||
|
|
||||||
data ro bSingleValue:Int 342
|
data ro bSingleValue:Int 342
|
||||||
|
|
||||||
data ro cNestedObject:Obj
|
data ro cNestedObject:Obj (
|
||||||
-- this
|
(324 "hello world")
|
||||||
-- bird0 324
|
(123.8439 9328.21348239)
|
||||||
-- bird1 "hello world"
|
)
|
||||||
-- that
|
|
||||||
-- bird2 123.8439
|
|
||||||
-- bird3 9328.21348239
|
|
||||||
|
|
||||||
data ro dUninitialized:Int:16:mut
|
data ro dUninitialized:Int:16:mut
|
||||||
|
|
||||||
data ro eIntegerArrayInitialized:Int:16:mut
|
data ro eIntegerArrayInitialized: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)
|
||||||
|
|
||||||
func ro fComplexFunction
|
func ro fComplexFunction
|
||||||
---
|
---
|
||||||
= x:Int 3
|
= x:Int 3
|
||||||
= y:{Int} [loc x]
|
= y:{Int
|
||||||
= z:Int:8
|
} [loc x
|
||||||
|
]
|
||||||
|
= z:Int:8 (
|
||||||
398 9 2309 983 -2387
|
398 9 2309 983 -2387
|
||||||
478 555 123
|
478 555 123)
|
||||||
= bird:Bird
|
= bird:Bird ((99999) 324)
|
||||||
-- that
|
|
||||||
-- whenYou 99999
|
|
||||||
-- this 324
|
|
||||||
|
|
||||||
func ro gExternalFunction
|
func ro gExternalFunction
|
||||||
> x:Int
|
> x:Int
|
||||||
< arr:Int 5
|
< arr:Int 5
|
||||||
34908
|
(34908
|
||||||
39 3498
|
39 3498
|
||||||
38 219
|
38 219)
|
||||||
---
|
---
|
||||||
external
|
external
|
||||||
|
|
|
@ -1,35 +1,36 @@
|
||||||
:arf
|
:arf
|
||||||
---
|
---
|
||||||
type ro aBasic:Obj:(
|
type ro aBasic:Obj
|
||||||
.ro that:Int
|
ro that:Int
|
||||||
.ro this:Int)
|
ro this:Int
|
||||||
|
|
||||||
type ro bBitFields:Obj:(
|
type ro bBitFields:Obj
|
||||||
.ro that:Int & 1
|
ro that:Int & 1
|
||||||
.ro this:Int:<298> & 24)
|
ro this:Int 298 & 24
|
||||||
|
|
||||||
type ro cInit:Obj:(
|
type ro cInit:Obj
|
||||||
.ro that:String:<"hello world">
|
ro that:String "hello world"
|
||||||
.ro this:Int:<23>)
|
ro this:Int 23
|
||||||
|
|
||||||
type ro dInitInherit:aBasic:(
|
# the semantic analyzer should let these sections restrict the permissions of
|
||||||
.that:<9384>
|
# inherited members, but it should not let the sections lessen the permissions.
|
||||||
.this:<389>)
|
type ro dInitInherit:aBasic
|
||||||
|
ro that 9384
|
||||||
|
ro this 389
|
||||||
|
|
||||||
type ro eInitAndDefine:aBasic:(
|
type ro eInitAndDefine:aBasic
|
||||||
.this:<389>
|
ro this 389
|
||||||
.ro these:aBasic:(
|
ro that 9384
|
||||||
.ro born:Int:<4>
|
ro born:Int 4
|
||||||
.ro in:Int
|
ro in:Int
|
||||||
.ro the:Int:3:<9348 92384 92834>
|
ro the:Int:3 (9348 92384 92834)
|
||||||
.this:<98>)
|
ro walls:String "live in the walls, die in the walls."
|
||||||
.that:<9384>)
|
|
||||||
|
|
||||||
type ro fBasic:Int
|
type ro fBasic:Int
|
||||||
|
|
||||||
type ro gBasicInit:Int:<6>
|
type ro gBasicInit:Int 6
|
||||||
|
|
||||||
type ro hIntArray:{Int ..}
|
type ro hIntArray:{Int ..}
|
||||||
|
|
||||||
type ro iIntArrayInit:Int:3:
|
type ro iIntArrayInit:Int:3
|
||||||
<3298 923 92>
|
(3298 923 92)
|
||||||
|
|
Reference in New Issue
Block a user