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