Merge pull request 'revert-complexity' (#7) from revert-complexity into main

Reviewed-on: arf/arf#7
This commit is contained in:
Sasha Koshka 2022-09-29 20:06:53 +00:00
commit b2cc45abec
28 changed files with 779 additions and 839 deletions

View File

@ -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
} }

View File

@ -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)

View File

@ -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 " +

View File

@ -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
} }

View File

@ -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)
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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
View 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)
}

View File

@ -171,7 +171,7 @@ func (parser *ParsingOperation) parseFuncArguments (
if err != nil { return } if err != nil { return }
case lexer.TokenKindLessThan: case lexer.TokenKindLessThan:
output := 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 }
} }

View File

@ -8,13 +8,13 @@ func TestFunc (test *testing.T) {
--- ---
func ro aBasicExternal func ro aBasicExternal
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int:<4> < someOutput:Int 4
--- ---
external external
func ro bMethod func ro bMethod
@ bird:{Bird} @ bird:{Bird}
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int:<4> < someOutput:Int 4
--- ---
external external
func ro cBasicPhrases func ro cBasicPhrases
@ -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
View 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
}

View File

@ -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)
} }

View File

@ -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
} }

View File

@ -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()

View File

@ -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":

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
} }

View File

@ -1,9 +1,9 @@
:arf :arf
--- ---
data ro aInteger:Int:<3202> data ro aInteger:Int 3202
data ro bMutInteger:Int:mut:<3202> data ro bMutInteger:Int:mut 3202
data ro cIntegerPointer:{Int} data ro cIntegerPointer:{Int}
@ -13,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)

View File

@ -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)

View File

@ -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

View File

@ -2,14 +2,14 @@
--- ---
func ro aBasicExternal func ro aBasicExternal
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int:<4> < someOutput:Int 4
--- ---
external external
func ro bMethod func ro bMethod
@ bird:{Bird} @ bird:{Bird}
> someInput:Int:mut > someInput:Int:mut
< someOutput:Int:<4> < someOutput:Int 4
--- ---
external external
@ -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>)

View File

@ -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

View File

@ -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)