type-section-rework #6
@ -4,6 +4,6 @@ require "io"
|
||||
|
||||
func ro main
|
||||
> arguments:{String ..}
|
||||
< status:Int 0
|
||||
< status:Int:<0>
|
||||
---
|
||||
io.println "hello world"
|
||||
|
@ -5,18 +5,18 @@ require "io"
|
||||
---
|
||||
|
||||
# this is a global variable
|
||||
data pv helloText:String "Hello, world!"
|
||||
data pv helloText:String:<"Hello, world!">
|
||||
|
||||
# this is a struct definition
|
||||
objt ro Greeter:Obj
|
||||
rw text:String "Hi."
|
||||
type ro Greeter:Obj:(
|
||||
.rw text:String:<"Hi.">)
|
||||
|
||||
# this is a function
|
||||
func ro main
|
||||
> arguments:{String ..}
|
||||
< status:Int 0
|
||||
< status:Int:<0>
|
||||
---
|
||||
= greeter:Greeter:mut
|
||||
let greeter:Greeter:mut
|
||||
greeter.setText helloText
|
||||
greeter.greet
|
||||
|
||||
|
@ -192,6 +192,16 @@ func (lexer *LexingOperation) tokenizeSymbolBeginning () (err error) {
|
||||
token.kind = TokenKindComma
|
||||
lexer.addToken(token)
|
||||
err = lexer.nextRune()
|
||||
case '(':
|
||||
token := lexer.newToken()
|
||||
token.kind = TokenKindLParen
|
||||
lexer.addToken(token)
|
||||
err = lexer.nextRune()
|
||||
case ')':
|
||||
token := lexer.newToken()
|
||||
token.kind = TokenKindRParen
|
||||
lexer.addToken(token)
|
||||
err = lexer.nextRune()
|
||||
case '[':
|
||||
token := lexer.newToken()
|
||||
token.kind = TokenKindLBracket
|
||||
|
@ -138,6 +138,8 @@ func TestTokenizeAll (test *testing.T) {
|
||||
quickToken(1, TokenKindDot, nil),
|
||||
quickToken(1, TokenKindComma, nil),
|
||||
quickToken(2, TokenKindElipsis, nil),
|
||||
quickToken(1, TokenKindLParen, nil),
|
||||
quickToken(1, TokenKindRParen, nil),
|
||||
quickToken(1, TokenKindLBracket, nil),
|
||||
quickToken(1, TokenKindRBracket, nil),
|
||||
quickToken(1, TokenKindLBrace, nil),
|
||||
|
@ -28,6 +28,8 @@ const (
|
||||
TokenKindElipsis
|
||||
TokenKindComma
|
||||
|
||||
TokenKindLParen
|
||||
TokenKindRParen
|
||||
TokenKindLBracket
|
||||
TokenKindRBracket
|
||||
TokenKindLBrace
|
||||
@ -166,6 +168,10 @@ func (tokenKind TokenKind) Describe () (description string) {
|
||||
description = "Elipsis"
|
||||
case TokenKindComma:
|
||||
description = "Comma"
|
||||
case TokenKindLParen:
|
||||
description = "LParen"
|
||||
case TokenKindRParen:
|
||||
description = "RParen"
|
||||
case TokenKindLBracket:
|
||||
description = "LBracket"
|
||||
case TokenKindRBracket:
|
||||
|
@ -29,12 +29,6 @@ func (section TypeSection) Kind () (kind SectionKind) {
|
||||
return
|
||||
}
|
||||
|
||||
// Kind returns the section's kind (SectionKindObjt).
|
||||
func (section ObjtSection) Kind () (kind SectionKind) {
|
||||
kind = SectionKindObjt
|
||||
return
|
||||
}
|
||||
|
||||
// Kind returns the section's kind (SectionKindEnum).
|
||||
func (section EnumSection) Kind () (kind SectionKind) {
|
||||
kind = SectionKindEnum
|
||||
@ -111,23 +105,23 @@ func (what Type) Points () (points Type) {
|
||||
return
|
||||
}
|
||||
|
||||
// Values returns an iterator for the initialization values.
|
||||
func (values ObjectInitializationValues) Sections () (
|
||||
iterator types.Iterator[Argument],
|
||||
) {
|
||||
iterator = types.NewIterator(values.attributes)
|
||||
// MembersLength returns the amount of new members the type specifier defines.
|
||||
// If it defines no new members, it returns zero.
|
||||
func (what Type) MembersLength () (length int) {
|
||||
length = len(what.members)
|
||||
return
|
||||
}
|
||||
|
||||
// Length returns the amount of values.
|
||||
func (values ArrayInitializationValues) Length () (length int) {
|
||||
length = len(values.values)
|
||||
// Member returns the member at index.
|
||||
func (what Type) Member (index int) (member TypeMember) {
|
||||
member = what.members[index]
|
||||
return
|
||||
}
|
||||
|
||||
// Item returns the value at index.
|
||||
func (values ArrayInitializationValues) Value (index int) (value Argument) {
|
||||
value = values.values[index]
|
||||
// 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) {
|
||||
width = member.bitWidth
|
||||
return
|
||||
}
|
||||
|
||||
@ -144,25 +138,6 @@ func (argument Argument) Value () (value any) {
|
||||
return
|
||||
}
|
||||
|
||||
// BitWidth returns the bit width of the object member. If it is zero, it should
|
||||
// be treated as unspecified.
|
||||
func (member ObjtMember) BitWidth () (width uint64) {
|
||||
width = member.bitWidth
|
||||
return
|
||||
}
|
||||
|
||||
// Length returns the amount of members in the section.
|
||||
func (section ObjtSection) Length () (length int) {
|
||||
length = len(section.members)
|
||||
return
|
||||
}
|
||||
|
||||
// Item returns the member at index.
|
||||
func (section ObjtSection) Item (index int) (member ObjtMember) {
|
||||
member = section.members[index]
|
||||
return
|
||||
}
|
||||
|
||||
// Length returns the amount of members in the section.
|
||||
func (section EnumSection) Length () (length int) {
|
||||
length = len(section.members)
|
||||
@ -272,12 +247,6 @@ func (section FuncSection) OutputsLength () (length int) {
|
||||
return
|
||||
}
|
||||
|
||||
// Output returns the output at index.
|
||||
func (section FuncSection) Output (index int) (output FuncOutput) {
|
||||
output = section.outputs[index]
|
||||
return
|
||||
}
|
||||
|
||||
// Root returns the root block of the section.
|
||||
func (section FuncSection) Root () (root Block) {
|
||||
root = section.root
|
||||
|
@ -23,12 +23,6 @@ func (parser *ParsingOperation) parseBody () (err error) {
|
||||
if err != nil { return }
|
||||
if parseErr != nil { return parseErr }
|
||||
|
||||
case "objt":
|
||||
section, parseErr := parser.parseObjtSection()
|
||||
err = parser.tree.addSection(section)
|
||||
if err != nil { return }
|
||||
if parseErr != nil { return parseErr }
|
||||
|
||||
case "face":
|
||||
section, parseErr := parser.parseFaceSection()
|
||||
err = parser.tree.addSection(section)
|
||||
|
@ -35,18 +35,18 @@ func (parser *ParsingOperation) parseDataSection () (
|
||||
return
|
||||
}
|
||||
|
||||
if parser.token.Is(lexer.TokenKindNewline) {
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
// check if external
|
||||
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||
if parser.token.Value().(int) != 1 { 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 {
|
||||
|
||||
err = parser.nextToken()
|
||||
err = parser.nextToken(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
if parser.token.Is(lexer.TokenKindName) &&
|
||||
parser.token.Value().(string) == "external" {
|
||||
if parser.token.Value().(string) == "external" {
|
||||
|
||||
section.external = true
|
||||
err = parser.nextToken(lexer.TokenKindNewline)
|
||||
@ -56,18 +56,7 @@ func (parser *ParsingOperation) parseDataSection () (
|
||||
return
|
||||
}
|
||||
|
||||
// otherwise, parse initialization values
|
||||
parser.previousToken()
|
||||
section.value, err = parser.parseInitializationValues(0)
|
||||
if err != nil { return }
|
||||
} else {
|
||||
section.value, err = parser.parseArgument()
|
||||
if err != nil { return }
|
||||
|
||||
err = parser.expect(lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -6,13 +6,14 @@ 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
|
||||
@ -24,20 +25,35 @@ data ro gIntegerArrayInitialized:Int:16
|
||||
0
|
||||
4785
|
||||
92
|
||||
data ro jObject:thing.Thing.thing.thing
|
||||
.that 2139
|
||||
.this 324
|
||||
data ro kNestedObject:Obj
|
||||
.that
|
||||
.bird2 123.8439
|
||||
.bird3 9328.21348239
|
||||
.this
|
||||
.bird0 324
|
||||
.bird1 "hello world"
|
||||
>
|
||||
data rw hIntegerPointerInit:{Int}:<[& integer]>
|
||||
data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
|
||||
data ro jObject:Obj:
|
||||
(
|
||||
.that:<324>
|
||||
.this:<324>
|
||||
)
|
||||
data ro kNestedObject:Obj:
|
||||
(
|
||||
.ro newMember:Int:<9023>
|
||||
):
|
||||
(
|
||||
.that:
|
||||
(
|
||||
.bird2:<123.8439>
|
||||
.bird3:<9328.21348239>
|
||||
)
|
||||
.this:
|
||||
(
|
||||
.bird0:<324>
|
||||
.bird1:<"hello world">
|
||||
)
|
||||
)
|
||||
data ro lMutIntegerArray16:Int:16:mut
|
||||
data ro mExternalData:Int:8
|
||||
external
|
||||
data ro nIntegerArrayInitialized:Int:16:mut
|
||||
data ro nIntegerArrayInitialized:Int:16:mut:
|
||||
<
|
||||
3948
|
||||
293
|
||||
293049
|
||||
@ -49,5 +65,6 @@ data ro nIntegerArrayInitialized:Int:16:mut
|
||||
0
|
||||
4785
|
||||
92
|
||||
>
|
||||
`, test)
|
||||
}
|
||||
|
180
parser/default-values.go
Normal file
180
parser/default-values.go
Normal file
@ -0,0 +1,180 @@
|
||||
package parser
|
||||
//
|
||||
// import "git.tebibyte.media/arf/arf/lexer"
|
||||
// import "git.tebibyte.media/arf/arf/infoerr"
|
||||
//
|
||||
// // TODO:
|
||||
// // (parser *ParsingOperation) parseDefaultValues
|
||||
//
|
||||
// // (parser *ParsingOperation) parseDefaultMemberValues (return tree of new members and a tree of member values)
|
||||
// // (parser *ParsingOperation) parseDefaultArrayValues
|
||||
//
|
||||
// // (parser *ParsingOperation) parseDefaultMemberValue
|
||||
// // (parser *ParsingOperation) parseMemberDeclaration
|
||||
//
|
||||
// // parsedefaultValues starts on the line after a = phrase, a data section, a
|
||||
// // type section, or anywhere else where there can be a default value. It returns
|
||||
// // a default value in the form of an argument, as well as any defined members
|
||||
// // that it finds.
|
||||
// func (parser *ParsingOperation) parseDefaultValues (
|
||||
// baseIndent int,
|
||||
// ) (
|
||||
// argument Argument,
|
||||
// members []TypeMember,
|
||||
// err error,
|
||||
// ) {
|
||||
// // check if line is indented one more than baseIndent
|
||||
// if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||
// if parser.token.Value().(int) != baseIndent + 1 { return }
|
||||
//
|
||||
// argument.location = parser.token.Location()
|
||||
//
|
||||
// err = parser.nextToken()
|
||||
// if err != nil { return }
|
||||
//
|
||||
// if parser.token.Is(lexer.TokenKindDot) {
|
||||
//
|
||||
// // object initialization
|
||||
// parser.previousToken()
|
||||
// var values ObjectDefaultValues
|
||||
// values, err = parser.parseObjectdefaultValues()
|
||||
// argument.kind = ArgumentKindObjectDefaultValues
|
||||
// argument.value = values
|
||||
//
|
||||
// } else {
|
||||
//
|
||||
// // array initialization
|
||||
// parser.previousToken()
|
||||
// var values ArrayDefaultValues
|
||||
// values, err = parser.parseArrayDefaultValues()
|
||||
// argument.kind = ArgumentKindArrayDefaultValues
|
||||
// argument.value = values
|
||||
// }
|
||||
//
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // parseObjectdefaultValues parses a list of object initialization
|
||||
// // values until the indentation level drops.
|
||||
// func (parser *ParsingOperation) parseObjectdefaultValues () (
|
||||
// defaultValues ObjectDefaultValues,
|
||||
// err error,
|
||||
// ) {
|
||||
// defaultValues.attributes = make(map[string] Argument)
|
||||
//
|
||||
// baseIndent := 0
|
||||
// begin := true
|
||||
//
|
||||
// for {
|
||||
// // if there is no indent we can just stop parsing
|
||||
// if !parser.token.Is(lexer.TokenKindIndent) { break}
|
||||
// indent := parser.token.Value().(int)
|
||||
//
|
||||
// if begin == true {
|
||||
// defaultValues.location = parser.token.Location()
|
||||
// baseIndent = indent
|
||||
// begin = false
|
||||
// }
|
||||
//
|
||||
// // do not parse any further if the indent has changed
|
||||
// if indent != baseIndent { break }
|
||||
//
|
||||
// // move on to the beginning of the line, which must contain
|
||||
// // a member initialization value
|
||||
// err = parser.nextToken(lexer.TokenKindDot)
|
||||
// if err != nil { return }
|
||||
// err = parser.nextToken(lexer.TokenKindName)
|
||||
// if err != nil { return }
|
||||
// name := parser.token.Value().(string)
|
||||
//
|
||||
// // if the member has already been listed, throw an error
|
||||
// _, exists := defaultValues.attributes[name]
|
||||
// if exists {
|
||||
// err = parser.token.NewError (
|
||||
// "duplicate member \"" + name + "\" in object " +
|
||||
// "member initialization",
|
||||
// infoerr.ErrorKindError)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // parse the argument determining the member initialization
|
||||
// // value
|
||||
// err = parser.nextToken()
|
||||
// if err != nil { return }
|
||||
// var value Argument
|
||||
// if parser.token.Is(lexer.TokenKindNewline) {
|
||||
//
|
||||
// // recurse
|
||||
// err = parser.nextToken(lexer.TokenKindIndent)
|
||||
// if err != nil { return }
|
||||
//
|
||||
// value, err = parser.parseDefaultValues(baseIndent)
|
||||
// defaultValues.attributes[name] = value
|
||||
// if err != nil { return }
|
||||
//
|
||||
// } else {
|
||||
//
|
||||
// // parse as normal argument
|
||||
// value, err = parser.parseArgument()
|
||||
// defaultValues.attributes[name] = value
|
||||
// if err != nil { return }
|
||||
//
|
||||
// err = parser.expect(lexer.TokenKindNewline)
|
||||
// if err != nil { return }
|
||||
// err = parser.nextToken()
|
||||
// if err != nil { return }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // parseArrayDefaultValues parses a list of array initialization values until
|
||||
// // the indentation lexel drops.
|
||||
// func (parser *ParsingOperation) parseArrayDefaultValues () (
|
||||
// defaultValues ArrayDefaultValues,
|
||||
// err error,
|
||||
// ) {
|
||||
// baseIndent := 0
|
||||
// begin := true
|
||||
//
|
||||
// for {
|
||||
// // if there is no indent we can just stop parsing
|
||||
// if !parser.token.Is(lexer.TokenKindIndent) { break}
|
||||
// indent := parser.token.Value().(int)
|
||||
//
|
||||
// if begin == true {
|
||||
// defaultValues.location = parser.token.Location()
|
||||
// baseIndent = indent
|
||||
// begin = false
|
||||
// }
|
||||
//
|
||||
// // do not parse any further if the indent has changed
|
||||
// if indent != baseIndent { break }
|
||||
//
|
||||
// // move on to the beginning of the line, which must contain
|
||||
// // arguments
|
||||
// err = parser.nextToken(validArgumentStartTokens...)
|
||||
// if err != nil { return }
|
||||
//
|
||||
// for {
|
||||
// // stop parsing this line and go on to the next if a
|
||||
// // newline token is encountered
|
||||
// if parser.token.Is(lexer.TokenKindNewline) {
|
||||
// err = parser.nextToken()
|
||||
// if err != nil { return }
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// // otherwise, parse the argument
|
||||
// var argument Argument
|
||||
// argument, err = parser.parseArgument()
|
||||
// if err != nil { return }
|
||||
// defaultValues.values = append (
|
||||
// defaultValues.values,
|
||||
// argument)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return
|
||||
// }
|
@ -61,34 +61,62 @@ 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 }
|
||||
|
||||
member := EnumMember { }
|
||||
|
||||
// get name
|
||||
err = parser.nextToken(lexer.TokenKindName)
|
||||
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 }
|
||||
member.location = parser.token.Location()
|
||||
member.name = parser.token.Value().(string)
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
// parse default value
|
||||
if parser.token.Is(lexer.TokenKindNewline) {
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
}
|
||||
|
||||
member.value, err = parser.parseInitializationValues(1)
|
||||
into.members = append(into.members, member)
|
||||
if err != nil { return }
|
||||
} else {
|
||||
member.value, err = parser.parseArgument()
|
||||
into.members = append(into.members, member)
|
||||
if err != nil { return }
|
||||
// parseEnumMember parses a single enum member. Indenttion level is assumed.
|
||||
func (parser *ParsingOperation) parseEnumMember () (
|
||||
member EnumMember,
|
||||
err error,
|
||||
) {
|
||||
err = parser.expect(lexer.TokenKindMinus)
|
||||
if err != nil { return }
|
||||
|
||||
err = parser.expect(lexer.TokenKindNewline)
|
||||
// get name
|
||||
err = parser.nextToken(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
member.location = parser.token.Location()
|
||||
member.name = parser.token.Value().(string)
|
||||
|
||||
// see if value exists
|
||||
err = parser.nextToken (
|
||||
lexer.TokenKindColon,
|
||||
lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindColon) {
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
err = parser.skipWhitespace()
|
||||
if err != nil { return }
|
||||
err = parser.expect (
|
||||
lexer.TokenKindLessThan,
|
||||
lexer.TokenKindLParen)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindLessThan) {
|
||||
// parse value
|
||||
member.value, err = parser.parseBasicDefaultValue()
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindLParen) {
|
||||
// parse default values
|
||||
member.value, err = parser.parseObjectDefaultValue()
|
||||
if err != nil { return }
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -7,32 +7,63 @@ func TestEnum (test *testing.T) {
|
||||
`:arf
|
||||
---
|
||||
enum ro AffrontToGod:Int:4
|
||||
bird0
|
||||
- bird0:
|
||||
<
|
||||
28394
|
||||
9328
|
||||
398
|
||||
9
|
||||
bird1
|
||||
>
|
||||
- bird1:
|
||||
<
|
||||
23
|
||||
932832
|
||||
398
|
||||
2349
|
||||
bird2
|
||||
>
|
||||
- bird2:
|
||||
<
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
>
|
||||
enum ro NamedColor:U32
|
||||
red 16711680
|
||||
green 65280
|
||||
blue 255
|
||||
- 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>
|
||||
)
|
||||
enum ro Weekday:Int
|
||||
sunday
|
||||
monday
|
||||
tuesday
|
||||
wednesday
|
||||
thursday
|
||||
friday
|
||||
saturday
|
||||
- sunday
|
||||
- monday
|
||||
- tuesday
|
||||
- wednesday
|
||||
- thursday
|
||||
- friday
|
||||
- saturday
|
||||
`, test)
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ func (parser *ParsingOperation) parseFuncArguments (
|
||||
if err != nil { return }
|
||||
|
||||
case lexer.TokenKindLessThan:
|
||||
output := FuncOutput { }
|
||||
output := Declaration { }
|
||||
output.location = parser.token.Location()
|
||||
|
||||
// get name
|
||||
@ -186,34 +186,13 @@ func (parser *ParsingOperation) parseFuncArguments (
|
||||
if err != nil { return }
|
||||
output.what, err = parser.parseType()
|
||||
if err != nil { return }
|
||||
|
||||
// skip the default value if we are skimming
|
||||
if parser.skimming {
|
||||
err = parser.skipIndentLevel(2)
|
||||
into.outputs = append(into.outputs, output)
|
||||
return
|
||||
}
|
||||
|
||||
// parse default value
|
||||
if parser.token.Is(lexer.TokenKindNewline) {
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
into.outputs = append(into.outputs, output)
|
||||
|
||||
output.value, err =
|
||||
parser.parseInitializationValues(1)
|
||||
into.outputs = append(into.outputs, output)
|
||||
if err != nil { return }
|
||||
} else {
|
||||
output.value, err =
|
||||
parser.parseArgument()
|
||||
into.outputs = append(into.outputs, output)
|
||||
if err != nil { return }
|
||||
|
||||
err = parser.expect(lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
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
|
||||
@ -101,20 +101,9 @@ func ro gControlFlow
|
||||
[otherThing]
|
||||
func ro hSetPhrase
|
||||
---
|
||||
[= x:Int 3]
|
||||
[= y:{Int} [loc x]]
|
||||
[= z:Int:8]
|
||||
398
|
||||
9
|
||||
2309
|
||||
983
|
||||
-2387
|
||||
478
|
||||
555
|
||||
123
|
||||
[= bird:Bird]
|
||||
.that
|
||||
.whenYou 99999
|
||||
.this 324
|
||||
[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>)]
|
||||
`, test)
|
||||
}
|
||||
|
@ -1,170 +0,0 @@
|
||||
package parser
|
||||
|
||||
import "git.tebibyte.media/arf/arf/lexer"
|
||||
import "git.tebibyte.media/arf/arf/infoerr"
|
||||
|
||||
// parseInitializationValues starts on the line after a data section, or a set
|
||||
// phrase. It checks for an indent greater than the indent of the aforementioned
|
||||
// data section or set phrase (passed through baseIndent), and if there is,
|
||||
// it parses initialization values.
|
||||
func (parser *ParsingOperation) parseInitializationValues (
|
||||
baseIndent int,
|
||||
) (
|
||||
initializationArgument Argument,
|
||||
err error,
|
||||
) {
|
||||
// check if line is indented one more than baseIndent
|
||||
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||
if parser.token.Value().(int) != baseIndent + 1 { return }
|
||||
|
||||
initializationArgument.location = parser.token.Location()
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindDot) {
|
||||
|
||||
// object initialization
|
||||
parser.previousToken()
|
||||
var initializationValues ObjectInitializationValues
|
||||
initializationValues, err = parser.parseObjectInitializationValues()
|
||||
initializationArgument.kind = ArgumentKindObjectInitializationValues
|
||||
initializationArgument.value = initializationValues
|
||||
|
||||
} else {
|
||||
|
||||
// array initialization
|
||||
parser.previousToken()
|
||||
var initializationValues ArrayInitializationValues
|
||||
initializationValues, err = parser.parseArrayInitializationValues()
|
||||
initializationArgument.kind = ArgumentKindArrayInitializationValues
|
||||
initializationArgument.value = initializationValues
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseObjectInitializationValues parses a list of object initialization
|
||||
// values until the indentation level drops.
|
||||
func (parser *ParsingOperation) parseObjectInitializationValues () (
|
||||
initializationValues ObjectInitializationValues,
|
||||
err error,
|
||||
) {
|
||||
initializationValues.attributes = make(map[string] Argument)
|
||||
|
||||
baseIndent := 0
|
||||
begin := true
|
||||
|
||||
for {
|
||||
// if there is no indent we can just stop parsing
|
||||
if !parser.token.Is(lexer.TokenKindIndent) { break}
|
||||
indent := parser.token.Value().(int)
|
||||
|
||||
if begin == true {
|
||||
initializationValues.location = parser.token.Location()
|
||||
baseIndent = indent
|
||||
begin = false
|
||||
}
|
||||
|
||||
// do not parse any further if the indent has changed
|
||||
if indent != baseIndent { break }
|
||||
|
||||
// move on to the beginning of the line, which must contain
|
||||
// a member initialization value
|
||||
err = parser.nextToken(lexer.TokenKindDot)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
name := parser.token.Value().(string)
|
||||
|
||||
// if the member has already been listed, throw an error
|
||||
_, exists := initializationValues.attributes[name]
|
||||
if exists {
|
||||
err = parser.token.NewError (
|
||||
"duplicate member \"" + name + "\" in object " +
|
||||
"member initialization",
|
||||
infoerr.ErrorKindError)
|
||||
return
|
||||
}
|
||||
|
||||
// parse the argument determining the member initialization
|
||||
// value
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
var value Argument
|
||||
if parser.token.Is(lexer.TokenKindNewline) {
|
||||
|
||||
// recurse
|
||||
err = parser.nextToken(lexer.TokenKindIndent)
|
||||
if err != nil { return }
|
||||
|
||||
value, err = parser.parseInitializationValues(baseIndent)
|
||||
initializationValues.attributes[name] = value
|
||||
if err != nil { return }
|
||||
|
||||
} else {
|
||||
|
||||
// parse as normal argument
|
||||
value, err = parser.parseArgument()
|
||||
initializationValues.attributes[name] = value
|
||||
if err != nil { return }
|
||||
|
||||
err = parser.expect(lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseArrayInitializationValues parses a list of array initialization values
|
||||
// until the indentation lexel drops.
|
||||
func (parser *ParsingOperation) parseArrayInitializationValues () (
|
||||
initializationValues ArrayInitializationValues,
|
||||
err error,
|
||||
) {
|
||||
baseIndent := 0
|
||||
begin := true
|
||||
|
||||
for {
|
||||
// if there is no indent we can just stop parsing
|
||||
if !parser.token.Is(lexer.TokenKindIndent) { break}
|
||||
indent := parser.token.Value().(int)
|
||||
|
||||
if begin == true {
|
||||
initializationValues.location = parser.token.Location()
|
||||
baseIndent = indent
|
||||
begin = false
|
||||
}
|
||||
|
||||
// do not parse any further if the indent has changed
|
||||
if indent != baseIndent { break }
|
||||
|
||||
// move on to the beginning of the line, which must contain
|
||||
// arguments
|
||||
err = parser.nextToken(validArgumentStartTokens...)
|
||||
if err != nil { return }
|
||||
|
||||
for {
|
||||
// stop parsing this line and go on to the next if a
|
||||
// newline token is encountered
|
||||
if parser.token.Is(lexer.TokenKindNewline) {
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
break
|
||||
}
|
||||
|
||||
// otherwise, parse the argument
|
||||
var argument Argument
|
||||
argument, err = parser.parseArgument()
|
||||
if err != nil { return }
|
||||
initializationValues.values = append (
|
||||
initializationValues.values,
|
||||
argument)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -12,7 +12,7 @@ author "Sasha Koshka"
|
||||
license "GPLv3"
|
||||
require "` + filepath.Join(cwd, "./some/local/module") + `"
|
||||
require "/some/absolute/path/to/someModule"
|
||||
require "/usr/include/arf/someLibraryInstalledInStandardLocation"
|
||||
require "/usr/local/include/arf/someLibraryInstalledInStandardLocation"
|
||||
---
|
||||
`, test)
|
||||
}
|
||||
|
@ -1,74 +1,6 @@
|
||||
package parser
|
||||
|
||||
import "git.tebibyte.media/arf/arf/lexer"
|
||||
import "git.tebibyte.media/arf/arf/infoerr"
|
||||
|
||||
// parseType parses a type notation of the form Name, {Name}, etc.
|
||||
func (parser *ParsingOperation) parseType () (what Type, err error) {
|
||||
err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace)
|
||||
if err != nil { return }
|
||||
what.location = parser.token.Location()
|
||||
|
||||
if parser.token.Is(lexer.TokenKindLBrace) {
|
||||
what.kind = TypeKindPointer
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
var points Type
|
||||
points, err = parser.parseType()
|
||||
if err != nil { return }
|
||||
what.points = &points
|
||||
|
||||
err = parser.expect (
|
||||
lexer.TokenKindRBrace,
|
||||
lexer.TokenKindElipsis)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindElipsis) {
|
||||
what.kind = TypeKindVariableArray
|
||||
|
||||
err = parser.nextToken(lexer.TokenKindRBrace)
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
} else {
|
||||
what.name, err = parser.parseIdentifier()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
for {
|
||||
if !parser.token.Is(lexer.TokenKindColon) { break }
|
||||
|
||||
err = parser.nextToken(lexer.TokenKindName, lexer.TokenKindUInt)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindName) {
|
||||
// parse type qualifier
|
||||
qualifier := parser.token.Value().(string)
|
||||
switch qualifier {
|
||||
case "mut":
|
||||
what.mutable = true
|
||||
default:
|
||||
err = parser.token.NewError (
|
||||
"unknown type qualifier \"" +
|
||||
qualifier + "\"",
|
||||
infoerr.ErrorKindError)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// parse fixed array length
|
||||
what.length = parser.token.Value().(uint64)
|
||||
}
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseIdentifier parses an identifier made out of dot separated names.
|
||||
func (parser *ParsingOperation) parseIdentifier () (
|
||||
@ -80,7 +12,10 @@ func (parser *ParsingOperation) parseIdentifier () (
|
||||
identifier.location = parser.token.Location()
|
||||
|
||||
for {
|
||||
if !parser.token.Is(lexer.TokenKindName) { break }
|
||||
if !parser.token.Is(lexer.TokenKindName) {
|
||||
parser.previousToken()
|
||||
break
|
||||
}
|
||||
|
||||
identifier.trail = append (
|
||||
identifier.trail,
|
||||
|
125
parser/objt.go
125
parser/objt.go
@ -1,125 +0,0 @@
|
||||
package parser
|
||||
|
||||
import "git.tebibyte.media/arf/arf/types"
|
||||
import "git.tebibyte.media/arf/arf/lexer"
|
||||
import "git.tebibyte.media/arf/arf/infoerr"
|
||||
|
||||
// parseObjtSection parses an object type definition. This allows for structured
|
||||
// types to be defined, and for member variables to be added and overridden.
|
||||
func (parser *ParsingOperation) parseObjtSection () (
|
||||
section ObjtSection,
|
||||
err error,
|
||||
) {
|
||||
err = parser.expect(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
|
||||
section.location = parser.token.Location()
|
||||
|
||||
// get permission
|
||||
err = parser.nextToken(lexer.TokenKindPermission)
|
||||
if err != nil { return }
|
||||
section.permission = parser.token.Value().(types.Permission)
|
||||
|
||||
// get name
|
||||
err = parser.nextToken(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
section.name = parser.token.Value().(string)
|
||||
|
||||
// parse inherited type
|
||||
err = parser.nextToken(lexer.TokenKindColon)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
section.inherits, err = parser.parseIdentifier()
|
||||
if err != nil { return }
|
||||
err = parser.expect(lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
// parse members
|
||||
err = parser.parseObjtMembers(§ion)
|
||||
if err != nil { return }
|
||||
|
||||
if len(section.members) == 0 {
|
||||
infoerr.NewError (
|
||||
section.location,
|
||||
"defining an object with no members",
|
||||
infoerr.ErrorKindWarn).Print()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// parseObjtMembers parses a list of members for an object section. Indentation
|
||||
// level is assumed.
|
||||
func (parser *ParsingOperation) parseObjtMembers (
|
||||
into *ObjtSection,
|
||||
) (
|
||||
err error,
|
||||
) {
|
||||
for {
|
||||
// if we've left the block, stop parsing
|
||||
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||
if parser.token.Value().(int) != 1 { return }
|
||||
|
||||
// add member to object section
|
||||
var member ObjtMember
|
||||
member, err = parser.parseObjtMember()
|
||||
into.members = append(into.members, member)
|
||||
if err != nil { return }
|
||||
}
|
||||
}
|
||||
|
||||
// parseObjtMember parses a single member of an object section. Indentation
|
||||
// level is assumed.
|
||||
func (parser *ParsingOperation) parseObjtMember () (
|
||||
member ObjtMember,
|
||||
err error,
|
||||
) {
|
||||
// get permission
|
||||
err = parser.nextToken(lexer.TokenKindPermission)
|
||||
if err != nil { return }
|
||||
member.permission = parser.token.Value().(types.Permission)
|
||||
|
||||
// get name
|
||||
err = parser.nextToken(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
member.name = parser.token.Value().(string)
|
||||
|
||||
// get type
|
||||
err = parser.nextToken(lexer.TokenKindColon)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
member.what, err = parser.parseType()
|
||||
if err != nil { return }
|
||||
|
||||
// if there is a bit width, get it
|
||||
if parser.token.Is(lexer.TokenKindBinaryAnd) {
|
||||
err = parser.nextToken(lexer.TokenKindUInt)
|
||||
if err != nil { return }
|
||||
member.bitWidth = parser.token.Value().(uint64)
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
// parse default value
|
||||
if parser.token.Is(lexer.TokenKindNewline) {
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
member.value,
|
||||
err = parser.parseInitializationValues(1)
|
||||
if err != nil { return }
|
||||
} else {
|
||||
member.value, err = parser.parseArgument()
|
||||
if err != nil { return }
|
||||
|
||||
err = parser.expect(lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package parser
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestObjt (test *testing.T) {
|
||||
checkTree ("../tests/parser/objt", false,
|
||||
`:arf
|
||||
---
|
||||
objt ro Basic:Obj
|
||||
ro that:Basic
|
||||
ro this:Basic
|
||||
objt ro BitFields:Obj
|
||||
ro that:Int & 1
|
||||
ro this:Int & 24 298
|
||||
objt ro ComplexInit:Obj
|
||||
ro whatever:Int:3
|
||||
230984
|
||||
849
|
||||
394580
|
||||
ro complex0:Bird
|
||||
.that 98
|
||||
.this 2
|
||||
ro complex1:Bird
|
||||
.that 98902
|
||||
.this 235
|
||||
ro basic:Int 87
|
||||
objt ro Init:Obj
|
||||
ro that:String "hello world"
|
||||
ro this:Int 23
|
||||
`, test)
|
||||
}
|
@ -166,3 +166,21 @@ func (parser *ParsingOperation) skipIndentLevel (indent int) (err error) {
|
||||
if err != nil { return }
|
||||
}
|
||||
}
|
||||
|
||||
// skipWhitespace skips over newlines and indent tokens.
|
||||
func (parser *ParsingOperation) skipWhitespace () (err error) {
|
||||
for {
|
||||
isWhitespace :=
|
||||
parser.token.Is(lexer.TokenKindIndent) ||
|
||||
parser.token.Is(lexer.TokenKindNewline)
|
||||
|
||||
if !isWhitespace {
|
||||
break
|
||||
}
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -139,25 +139,16 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
|
||||
err = parser.expect(validDelimitedPhraseTokens...)
|
||||
if err != nil { return }
|
||||
|
||||
// we are delimited so we can safely skip whitespace
|
||||
err = parser.skipWhitespace()
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindRBracket) {
|
||||
// this is an ending delimiter
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
break
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindNewline) {
|
||||
// we are delimited, so we can safely skip
|
||||
// newlines
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
continue
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindIndent) {
|
||||
// we are delimited, so we can safely skip
|
||||
// indents
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// not delimited
|
||||
@ -176,7 +167,7 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
|
||||
}
|
||||
}
|
||||
|
||||
// this is an argument
|
||||
// if we've got this far, we are parsing an argument
|
||||
var argument Argument
|
||||
argument, err = parser.parseArgument()
|
||||
phrase.arguments = append(phrase.arguments, argument)
|
||||
@ -213,18 +204,6 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
// if this is a set phrase, parse initialization values under it
|
||||
if phrase.kind == PhraseKindAssign {
|
||||
var values Argument
|
||||
values, err = parser.parseInitializationValues(indent)
|
||||
|
||||
if values.kind != ArgumentKindNil {
|
||||
phrase.arguments = append(phrase.arguments, values)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// if this is a control flow phrase, parse block under it
|
||||
isControlFlow := false
|
||||
for _, kind := range controlFlowKinds {
|
||||
@ -234,10 +213,9 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
|
||||
}
|
||||
}
|
||||
|
||||
if !isControlFlow { return }
|
||||
|
||||
// if it is any of those, parse the block under it
|
||||
phrase.block, err = parser.parseBlock(indent + 1)
|
||||
if isControlFlow {
|
||||
phrase.block, err = parser.parseBlock(indent + 1)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@ -330,6 +308,8 @@ 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":
|
||||
|
@ -66,12 +66,84 @@ func (identifier Identifier) ToString () (output string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (what Type) ToString () (output string) {
|
||||
func (values ObjectDefaultValues) ToString (
|
||||
indent int,
|
||||
breakLine bool,
|
||||
) (
|
||||
output string,
|
||||
) {
|
||||
if !breakLine { indent = 0 }
|
||||
output += doIndent(indent, "(")
|
||||
if breakLine { output += "\n" }
|
||||
|
||||
for index, name := range sortMapKeysAlphabetically(values) {
|
||||
if index > 0 && !breakLine { output += " " }
|
||||
|
||||
value := values[name]
|
||||
|
||||
output += doIndent(indent, "." + name + ":")
|
||||
|
||||
isComplexDefaultValue :=
|
||||
value.kind == ArgumentKindObjectDefaultValues ||
|
||||
value.kind == ArgumentKindArrayDefaultValues
|
||||
|
||||
if isComplexDefaultValue {
|
||||
if breakLine { output += "\n" }
|
||||
output += value.ToString(indent + 1, breakLine)
|
||||
} else {
|
||||
output += "<"
|
||||
output += value.ToString(indent + 1, false)
|
||||
output += ">"
|
||||
}
|
||||
if breakLine { output += "\n" }
|
||||
}
|
||||
output += doIndent(indent, ")")
|
||||
return
|
||||
}
|
||||
|
||||
func (values ArrayDefaultValues) ToString (
|
||||
indent int,
|
||||
breakLine bool,
|
||||
) (
|
||||
output string,
|
||||
) {
|
||||
if !breakLine { indent = 0 }
|
||||
output += doIndent(indent, "<")
|
||||
if breakLine { output += "\n" }
|
||||
|
||||
for index, value := range values {
|
||||
if index > 0 && !breakLine { output += " " }
|
||||
output += value.ToString(indent, breakLine)
|
||||
}
|
||||
|
||||
output += doIndent(indent, ">")
|
||||
return
|
||||
}
|
||||
|
||||
func (member TypeMember) ToString (indent int, breakLine bool) (output string) {
|
||||
output += doIndent(indent, ".")
|
||||
|
||||
output += member.permission.ToString() + " "
|
||||
output += member.name + ":"
|
||||
output += member.what.ToString(indent + 1, breakLine)
|
||||
|
||||
if member.bitWidth > 0 {
|
||||
output += fmt.Sprint(" & ", member.bitWidth)
|
||||
}
|
||||
|
||||
if breakLine {
|
||||
output += "\n"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (what Type) ToString (indent int, breakLine bool) (output string) {
|
||||
if what.kind == TypeKindBasic {
|
||||
output += what.name.ToString()
|
||||
} else {
|
||||
output += "{"
|
||||
output += what.points.ToString()
|
||||
output += what.points.ToString(indent, breakLine)
|
||||
|
||||
if what.kind == TypeKindVariableArray {
|
||||
output += " .."
|
||||
@ -87,45 +159,46 @@ func (what Type) ToString () (output string) {
|
||||
if what.mutable {
|
||||
output += ":mut"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (declaration Declaration) ToString () (output string) {
|
||||
output += declaration.name + ":"
|
||||
output += declaration.what.ToString()
|
||||
return
|
||||
}
|
||||
|
||||
func (attributes ObjectInitializationValues) ToString (
|
||||
indent int,
|
||||
) (
|
||||
output string,
|
||||
) {
|
||||
for _, name := range sortMapKeysAlphabetically(attributes.attributes) {
|
||||
value := attributes.attributes[name]
|
||||
|
||||
output += doIndent(indent, ".", name)
|
||||
if value.kind == ArgumentKindObjectInitializationValues {
|
||||
output += "\n"
|
||||
output += value.ToString(indent + 1, true)
|
||||
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 += " " + value.ToString(0, false) + "\n"
|
||||
output += ":("
|
||||
for index, member := range what.members {
|
||||
if index > 0 { output += " " }
|
||||
output += member.ToString(indent, breakLine)
|
||||
}
|
||||
output += ")"
|
||||
}
|
||||
}
|
||||
|
||||
defaultValueKind := what.defaultValue.kind
|
||||
if defaultValueKind != ArgumentKindNil {
|
||||
isComplexDefaultValue :=
|
||||
defaultValueKind == ArgumentKindObjectDefaultValues ||
|
||||
defaultValueKind == ArgumentKindArrayDefaultValues
|
||||
|
||||
if isComplexDefaultValue {
|
||||
output += ":"
|
||||
if breakLine { output += "\n" }
|
||||
output += what.defaultValue.ToString(indent, breakLine)
|
||||
} else {
|
||||
output += ":<"
|
||||
output += what.defaultValue.ToString(indent, false)
|
||||
output += ">"
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (values ArrayInitializationValues) ToString (
|
||||
indent int,
|
||||
) (
|
||||
output string,
|
||||
) {
|
||||
for _, value := range values.values {
|
||||
output += value.ToString(indent, true)
|
||||
}
|
||||
|
||||
func (declaration Declaration) ToString (indent int) (output string) {
|
||||
output += declaration.name + ":"
|
||||
output += declaration.what.ToString(indent, false)
|
||||
return
|
||||
}
|
||||
|
||||
@ -143,15 +216,13 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
|
||||
indent,
|
||||
breakLine)
|
||||
|
||||
case ArgumentKindObjectInitializationValues:
|
||||
// this should only appear in contexts where breakLine is true
|
||||
output += argument.value.(ObjectInitializationValues).
|
||||
ToString(indent)
|
||||
case ArgumentKindObjectDefaultValues:
|
||||
output += argument.value.(ObjectDefaultValues).
|
||||
ToString(indent, breakLine)
|
||||
|
||||
case ArgumentKindArrayInitializationValues:
|
||||
// this should only appear in contexts where breakLine is true
|
||||
output += argument.value.(ArrayInitializationValues).
|
||||
ToString(indent)
|
||||
case ArgumentKindArrayDefaultValues:
|
||||
output += argument.value.(ArrayDefaultValues).
|
||||
ToString(indent, breakLine)
|
||||
|
||||
case ArgumentKindIdentifier:
|
||||
output += doIndent (
|
||||
@ -162,7 +233,7 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
|
||||
case ArgumentKindDeclaration:
|
||||
output += doIndent (
|
||||
indent,
|
||||
argument.value.(Declaration).ToString())
|
||||
argument.value.(Declaration).ToString(indent))
|
||||
if breakLine { output += "\n" }
|
||||
|
||||
case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat:
|
||||
@ -260,24 +331,12 @@ func (section DataSection) ToString (indent int) (output string) {
|
||||
"data ",
|
||||
section.permission.ToString(), " ",
|
||||
section.name, ":",
|
||||
section.what.ToString())
|
||||
|
||||
isComplexInitialization :=
|
||||
section.value.kind == ArgumentKindObjectInitializationValues ||
|
||||
section.value.kind == ArgumentKindArrayInitializationValues
|
||||
|
||||
section.what.ToString(indent + 1, true), "\n")
|
||||
|
||||
if section.external {
|
||||
output += "\n"
|
||||
output += doIndent(indent + 1, "external\n")
|
||||
} else if section.value.value == nil {
|
||||
output += "\n"
|
||||
} else if isComplexInitialization {
|
||||
output += "\n"
|
||||
output += section.value.ToString(indent + 1, true)
|
||||
} else {
|
||||
output += " " + section.value.ToString(0, false)
|
||||
output += "\n"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -287,65 +346,10 @@ func (section TypeSection) ToString (indent int) (output string) {
|
||||
"type ",
|
||||
section.permission.ToString(), " ",
|
||||
section.name, ":",
|
||||
section.what.ToString())
|
||||
|
||||
isComplexInitialization :=
|
||||
section.value.kind == ArgumentKindObjectInitializationValues ||
|
||||
section.value.kind == ArgumentKindArrayInitializationValues
|
||||
|
||||
if section.value.value == nil {
|
||||
output += "\n"
|
||||
} else if isComplexInitialization {
|
||||
output += "\n"
|
||||
output += section.value.ToString(indent + 1, true)
|
||||
} else {
|
||||
output += " " + section.value.ToString(0, false)
|
||||
output += "\n"
|
||||
}
|
||||
section.what.ToString(indent + 1, true), "\n")
|
||||
return
|
||||
}
|
||||
|
||||
func (member ObjtMember) ToString (indent int) (output string) {
|
||||
output += doIndent(indent)
|
||||
|
||||
output += member.permission.ToString() + " "
|
||||
output += member.name + ":"
|
||||
output += member.what.ToString()
|
||||
|
||||
if member.bitWidth > 0 {
|
||||
output += fmt.Sprint(" & ", member.bitWidth)
|
||||
}
|
||||
|
||||
isComplexInitialization :=
|
||||
member.value.kind == ArgumentKindObjectInitializationValues ||
|
||||
member.value.kind == ArgumentKindArrayInitializationValues
|
||||
|
||||
if member.value.value == nil {
|
||||
output += "\n"
|
||||
} else if isComplexInitialization {
|
||||
output += "\n"
|
||||
output += member.value.ToString(indent + 1, true)
|
||||
} else {
|
||||
output += " " + member.value.ToString(0, false)
|
||||
output += "\n"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (section ObjtSection) ToString (indent int) (output string) {
|
||||
output += doIndent (
|
||||
indent,
|
||||
"objt ",
|
||||
section.permission.ToString(), " ",
|
||||
section.name, ":",
|
||||
section.inherits.ToString(), "\n")
|
||||
|
||||
for _, member := range section.members {
|
||||
output += member.ToString(indent + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (section EnumSection) ToString (indent int) (output string) {
|
||||
output += doIndent (
|
||||
@ -353,24 +357,22 @@ func (section EnumSection) ToString (indent int) (output string) {
|
||||
"enum ",
|
||||
section.permission.ToString(), " ",
|
||||
section.name, ":",
|
||||
section.what.ToString(), "\n")
|
||||
section.what.ToString(indent + 1, true), "\n")
|
||||
|
||||
for _, member := range section.members {
|
||||
output += doIndent(indent + 1, member.name)
|
||||
output += doIndent(indent + 1, "- ", member.name)
|
||||
|
||||
isComplexInitialization :=
|
||||
member.value.kind == ArgumentKindObjectInitializationValues ||
|
||||
member.value.kind == ArgumentKindArrayInitializationValues
|
||||
member.value.kind == ArgumentKindObjectDefaultValues ||
|
||||
member.value.kind == ArgumentKindArrayDefaultValues
|
||||
|
||||
if member.value.value == nil {
|
||||
output += "\n"
|
||||
} else if isComplexInitialization {
|
||||
output += "\n"
|
||||
if isComplexInitialization {
|
||||
output += ":\n"
|
||||
output += member.value.ToString(indent + 2, true)
|
||||
} else {
|
||||
output += " " + member.value.ToString(0, false)
|
||||
output += "\n"
|
||||
} else if member.value.kind != ArgumentKindNil {
|
||||
output += ":<" + member.value.ToString(0, false) + ">"
|
||||
}
|
||||
output += "\n"
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -394,11 +396,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(), "\n")
|
||||
output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n")
|
||||
}
|
||||
|
||||
for _, outputItem := range behavior.outputs {
|
||||
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
||||
output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
|
||||
}
|
||||
|
||||
return
|
||||
@ -409,18 +411,9 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
|
||||
output += doIndent(indent)
|
||||
}
|
||||
|
||||
var initializationValues Argument
|
||||
|
||||
output += "[" + phrase.command.ToString(0, false)
|
||||
for _, argument := range phrase.arguments {
|
||||
isInitializationValue :=
|
||||
argument.kind == ArgumentKindObjectInitializationValues ||
|
||||
argument.kind == ArgumentKindArrayInitializationValues
|
||||
if isInitializationValue {
|
||||
initializationValues = argument
|
||||
} else {
|
||||
output += " " + argument.ToString(0, false)
|
||||
}
|
||||
output += " " + argument.ToString(0, false)
|
||||
}
|
||||
output += "]"
|
||||
|
||||
@ -433,10 +426,9 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
|
||||
|
||||
if ownLine {
|
||||
output += "\n"
|
||||
if initializationValues.kind != ArgumentKindNil {
|
||||
output += initializationValues.ToString(indent + 1, true)
|
||||
}
|
||||
output += phrase.block.ToString(indent + 1)
|
||||
} else if len(phrase.block) > 0 {
|
||||
output += "NON-BLOCK-LEVEL-PHRASE-HAS-BLOCK"
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -449,14 +441,6 @@ func (block Block) ToString (indent int) (output string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (funcOutput FuncOutput) ToString () (output string) {
|
||||
output += funcOutput.Declaration.ToString()
|
||||
if funcOutput.value.kind != ArgumentKindNil {
|
||||
output += " " + funcOutput.value.ToString(0, false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (section FuncSection) ToString (indent int) (output string) {
|
||||
output += doIndent (
|
||||
indent,
|
||||
@ -467,15 +451,15 @@ func (section FuncSection) ToString (indent int) (output string) {
|
||||
if section.receiver != nil {
|
||||
output += doIndent (
|
||||
indent + 1,
|
||||
"@ ", section.receiver.ToString(), "\n")
|
||||
"@ ", section.receiver.ToString(indent), "\n")
|
||||
}
|
||||
|
||||
for _, inputItem := range section.inputs {
|
||||
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
|
||||
output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n")
|
||||
}
|
||||
|
||||
for _, outputItem := range section.outputs {
|
||||
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
|
||||
output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
|
||||
}
|
||||
|
||||
output += doIndent(indent + 1, "---\n")
|
||||
|
@ -20,7 +20,6 @@ type SectionKind int
|
||||
|
||||
const (
|
||||
SectionKindType = iota
|
||||
SectionKindObjt
|
||||
SectionKindEnum
|
||||
SectionKindFace
|
||||
SectionKindData
|
||||
@ -48,17 +47,27 @@ type Identifier struct {
|
||||
type TypeKind int
|
||||
|
||||
const (
|
||||
// TypeKindBasic either means it's a primitive, or it inherits from
|
||||
// something.
|
||||
// TypeKindBasic means its a normal type and inherits from something.
|
||||
// Basic types can define new members on their parent types.
|
||||
TypeKindBasic TypeKind = iota
|
||||
|
||||
// TypeKindPointer means it's a pointer
|
||||
// TypeKindPointer means it's a pointer.
|
||||
TypeKindPointer
|
||||
|
||||
// TypeKindVariableArray means it's an array of variable length.
|
||||
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
|
||||
@ -72,6 +81,12 @@ 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.
|
||||
@ -81,19 +96,12 @@ type Declaration struct {
|
||||
typeable
|
||||
}
|
||||
|
||||
// ObjectInitializationValues represents a list of object member initialization
|
||||
// ObjectDefaultValues represents a list of object member initialization
|
||||
// attributes.
|
||||
type ObjectInitializationValues struct {
|
||||
locatable
|
||||
attributes map[string] Argument
|
||||
}
|
||||
type ObjectDefaultValues map[string] Argument
|
||||
|
||||
// ArrayInitializationValues represents a list of attributes initializing an
|
||||
// array.
|
||||
type ArrayInitializationValues struct {
|
||||
locatable
|
||||
values []Argument
|
||||
}
|
||||
// ArrayDefaultValues represents a list of elements initializing an array.
|
||||
type ArrayDefaultValues []Argument
|
||||
|
||||
// ArgumentKind specifies the type of thing the value of an argument should be
|
||||
// cast to.
|
||||
@ -113,12 +121,12 @@ const (
|
||||
// {name 23}
|
||||
ArgumentKindSubscript
|
||||
|
||||
// .name value
|
||||
// but like, a lot of them
|
||||
ArgumentKindObjectInitializationValues
|
||||
// (.name <value>)
|
||||
// (.name <value> .name (.name <value))
|
||||
ArgumentKindObjectDefaultValues
|
||||
|
||||
// value value...
|
||||
ArgumentKindArrayInitializationValues
|
||||
// <4 32 98 5>
|
||||
ArgumentKindArrayDefaultValues
|
||||
|
||||
// name.name
|
||||
// name.name.name
|
||||
@ -168,39 +176,16 @@ type DataSection struct {
|
||||
nameable
|
||||
typeable
|
||||
permissionable
|
||||
valuable
|
||||
|
||||
external bool
|
||||
}
|
||||
|
||||
// TypeSection represents a blind type definition.
|
||||
// TypeSection represents a type definition.
|
||||
type TypeSection struct {
|
||||
locatable
|
||||
nameable
|
||||
typeable
|
||||
permissionable
|
||||
valuable
|
||||
}
|
||||
|
||||
// ObjtMember represents a part of an object type definition.
|
||||
type ObjtMember struct {
|
||||
locatable
|
||||
nameable
|
||||
typeable
|
||||
permissionable
|
||||
valuable
|
||||
|
||||
bitWidth uint64
|
||||
}
|
||||
|
||||
// ObjtSection represents an object type definition.
|
||||
type ObjtSection struct {
|
||||
locatable
|
||||
nameable
|
||||
permissionable
|
||||
inherits Identifier
|
||||
|
||||
members []ObjtMember
|
||||
}
|
||||
|
||||
// EnumMember represents a member of an enum section.
|
||||
@ -246,6 +231,7 @@ const (
|
||||
PhraseKindCall = iota
|
||||
PhraseKindCallExternal
|
||||
PhraseKindOperator
|
||||
PhraseKindLet
|
||||
PhraseKindAssign
|
||||
PhraseKindReference
|
||||
PhraseKindDefer
|
||||
@ -275,13 +261,6 @@ type Phrase struct {
|
||||
// Block represents a scoped/indented block of code.
|
||||
type Block []Phrase
|
||||
|
||||
// FuncOutput represents an input a function section. It is unlike an input in
|
||||
// that it can have a default value.
|
||||
type FuncOutput struct {
|
||||
Declaration
|
||||
valuable
|
||||
}
|
||||
|
||||
// FuncSection represents a function section.
|
||||
type FuncSection struct {
|
||||
locatable
|
||||
@ -290,7 +269,7 @@ type FuncSection struct {
|
||||
|
||||
receiver *Declaration
|
||||
inputs []Declaration
|
||||
outputs []FuncOutput
|
||||
outputs []Declaration
|
||||
root Block
|
||||
|
||||
external bool
|
||||
|
318
parser/type-notation.go
Normal file
318
parser/type-notation.go
Normal file
@ -0,0 +1,318 @@
|
||||
package parser
|
||||
|
||||
import "git.tebibyte.media/arf/arf/lexer"
|
||||
import "git.tebibyte.media/arf/arf/infoerr"
|
||||
import "git.tebibyte.media/arf/arf/types"
|
||||
|
||||
// parseType parses a type notation of the form Name, {Name}, etc.
|
||||
func (parser *ParsingOperation) parseType () (what Type, err error) {
|
||||
err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace)
|
||||
if err != nil { return }
|
||||
what.location = parser.token.Location()
|
||||
|
||||
if parser.token.Is(lexer.TokenKindLBrace) {
|
||||
what.kind = TypeKindPointer
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
var points Type
|
||||
points, err = parser.parseType()
|
||||
if err != nil { return }
|
||||
what.points = &points
|
||||
|
||||
err = parser.expect (
|
||||
lexer.TokenKindRBrace,
|
||||
lexer.TokenKindElipsis)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindElipsis) {
|
||||
what.kind = TypeKindVariableArray
|
||||
|
||||
err = parser.nextToken(lexer.TokenKindRBrace)
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
} else {
|
||||
what.name, err = parser.parseIdentifier()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
for {
|
||||
if !parser.token.Is(lexer.TokenKindColon) { break }
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
err = parser.skipWhitespace()
|
||||
if err != nil { return }
|
||||
|
||||
err = parser.expect(
|
||||
lexer.TokenKindName,
|
||||
lexer.TokenKindUInt,
|
||||
lexer.TokenKindLParen,
|
||||
lexer.TokenKindLessThan)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindName) {
|
||||
// parse type qualifier
|
||||
qualifier := parser.token.Value().(string)
|
||||
switch qualifier {
|
||||
case "mut":
|
||||
what.mutable = true
|
||||
default:
|
||||
err = parser.token.NewError (
|
||||
"unknown type qualifier \"" +
|
||||
qualifier + "\"",
|
||||
infoerr.ErrorKindError)
|
||||
return
|
||||
}
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindUInt) {
|
||||
// parse fixed array length
|
||||
what.length = parser.token.Value().(uint64)
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindLessThan) {
|
||||
// parse default value
|
||||
what.defaultValue, err = parser.parseBasicDefaultValue()
|
||||
if err != nil { return }
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindLParen) {
|
||||
// parse members and member default values
|
||||
what.defaultValue,
|
||||
what.members,
|
||||
err = parser.parseObjectDefaultValueAndMembers()
|
||||
if err != nil { return }
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseBasicDefaultValue parses a default value of a non-object type.
|
||||
func (parser *ParsingOperation) parseBasicDefaultValue () (
|
||||
value Argument,
|
||||
err error,
|
||||
) {
|
||||
value.location = parser.token.Location()
|
||||
|
||||
err = parser.expect(lexer.TokenKindLessThan)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
var attributes []Argument
|
||||
|
||||
defer func () {
|
||||
// if we have multiple values, we need to return the full array
|
||||
// instead.
|
||||
if len(attributes) > 1 {
|
||||
value.kind = ArgumentKindArrayDefaultValues
|
||||
value.value = ArrayDefaultValues(attributes)
|
||||
}
|
||||
} ()
|
||||
|
||||
for {
|
||||
err = parser.skipWhitespace()
|
||||
if err != nil { return }
|
||||
if parser.token.Is(lexer.TokenKindGreaterThan) { break }
|
||||
|
||||
value, err = parser.parseArgument()
|
||||
if err != nil { return }
|
||||
attributes = append(attributes, value)
|
||||
}
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseObjectDefaultValueAndMembers parses default values and new members of an
|
||||
// object type.
|
||||
func (parser *ParsingOperation) parseObjectDefaultValueAndMembers () (
|
||||
value Argument,
|
||||
members []TypeMember,
|
||||
err error,
|
||||
) {
|
||||
value.location = parser.token.Location()
|
||||
|
||||
err = parser.expect(lexer.TokenKindLParen)
|
||||
if err != nil { return }
|
||||
parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
var attributes ObjectDefaultValues
|
||||
|
||||
for {
|
||||
err = parser.skipWhitespace()
|
||||
if err != nil { return }
|
||||
if parser.token.Is(lexer.TokenKindRParen) { break }
|
||||
|
||||
err = parser.expect(lexer.TokenKindDot)
|
||||
if err != nil { return }
|
||||
parser.nextToken(lexer.TokenKindName, lexer.TokenKindPermission)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindName) {
|
||||
// parsing a defalut value for an inherited member
|
||||
var memberName string
|
||||
var memberValue Argument
|
||||
|
||||
memberName,
|
||||
memberValue, err = parser.parseObjectInheritedMember()
|
||||
if err != nil { return }
|
||||
|
||||
if value.kind == ArgumentKindNil {
|
||||
// create default value map if it doesn't
|
||||
// already exist
|
||||
value.kind = ArgumentKindObjectDefaultValues
|
||||
attributes = make(ObjectDefaultValues)
|
||||
value.value = attributes
|
||||
}
|
||||
|
||||
// TODO: error on duplicate
|
||||
if memberValue.kind != ArgumentKindNil {
|
||||
attributes[memberName] = memberValue
|
||||
}
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindPermission) {
|
||||
// parsing a member declaration
|
||||
var member TypeMember
|
||||
member, err = parser.parseObjectNewMember()
|
||||
|
||||
// TODO: error on duplicate
|
||||
members = append(members, member)
|
||||
if err != nil { return }
|
||||
}
|
||||
}
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseObjectDefaultValue parses member default values only, and will throw an
|
||||
// error when it encounteres a new member definition.
|
||||
func (parser *ParsingOperation) parseObjectDefaultValue () (
|
||||
value Argument,
|
||||
err error,
|
||||
) {
|
||||
value.location = parser.token.Location()
|
||||
|
||||
err = parser.expect(lexer.TokenKindLParen)
|
||||
if err != nil { return }
|
||||
parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
var attributes ObjectDefaultValues
|
||||
|
||||
for {
|
||||
err = parser.skipWhitespace()
|
||||
if err != nil { return }
|
||||
if parser.token.Is(lexer.TokenKindRParen) { break }
|
||||
|
||||
err = parser.expect(lexer.TokenKindDot)
|
||||
if err != nil { return }
|
||||
parser.nextToken(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
|
||||
if value.kind == ArgumentKindNil {
|
||||
value.kind = ArgumentKindObjectDefaultValues
|
||||
attributes = make(ObjectDefaultValues)
|
||||
value.value = attributes
|
||||
}
|
||||
|
||||
var memberName string
|
||||
var memberValue Argument
|
||||
memberName,
|
||||
memberValue, err = parser.parseObjectInheritedMember()
|
||||
|
||||
attributes[memberName] = memberValue
|
||||
}
|
||||
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// .name:<value>
|
||||
|
||||
// parseObjectInheritedMember parses a new default value for an inherited
|
||||
// member.
|
||||
func (parser *ParsingOperation) parseObjectInheritedMember () (
|
||||
name string,
|
||||
value Argument,
|
||||
err error,
|
||||
) {
|
||||
// get the name of the inherited member
|
||||
err = parser.expect(lexer.TokenKindName)
|
||||
value.location = parser.token.Location()
|
||||
if err != nil { return }
|
||||
name = parser.token.Value().(string)
|
||||
|
||||
// we require a default value to be present
|
||||
err = parser.nextToken(lexer.TokenKindColon)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken(lexer.TokenKindLParen, lexer.TokenKindLessThan)
|
||||
if err != nil { return }
|
||||
|
||||
if parser.token.Is(lexer.TokenKindLessThan) {
|
||||
// parse default value
|
||||
value, err = parser.parseBasicDefaultValue()
|
||||
if err != nil { return }
|
||||
|
||||
} else if parser.token.Is(lexer.TokenKindLParen) {
|
||||
// parse member default values
|
||||
value, err = parser.parseObjectDefaultValue()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// .ro name:Type:qualifier:<value>
|
||||
|
||||
// parseObjectNewMember parses an object member declaration, and its
|
||||
// default value if it exists.
|
||||
func (parser *ParsingOperation) parseObjectNewMember () (
|
||||
member TypeMember,
|
||||
err error,
|
||||
) {
|
||||
// get member permission
|
||||
err = parser.expect(lexer.TokenKindPermission)
|
||||
member.location = parser.token.Location()
|
||||
if err != nil { return }
|
||||
member.permission = parser.token.Value().(types.Permission)
|
||||
|
||||
// get member name
|
||||
err = parser.nextToken(lexer.TokenKindName)
|
||||
if err != nil { return }
|
||||
member.name = parser.token.Value().(string)
|
||||
|
||||
// get type
|
||||
err = parser.nextToken(lexer.TokenKindColon)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken(lexer.TokenKindName, lexer.TokenKindLBrace)
|
||||
if err != nil { return }
|
||||
member.what, err = parser.parseType()
|
||||
if err != nil { return }
|
||||
|
||||
// get bit width
|
||||
if parser.token.Is(lexer.TokenKindBinaryAnd) {
|
||||
err = parser.nextToken(lexer.TokenKindUInt)
|
||||
if err != nil { return }
|
||||
member.bitWidth = parser.token.Value().(uint64)
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -32,21 +32,10 @@ func (parser *ParsingOperation) parseTypeSection () (
|
||||
section.what, err = parser.parseType()
|
||||
if err != nil { return }
|
||||
|
||||
// parse default values
|
||||
if parser.token.Is(lexer.TokenKindNewline) {
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
section.value, err = parser.parseInitializationValues(0)
|
||||
if err != nil { return }
|
||||
} else {
|
||||
section.value, err = parser.parseArgument()
|
||||
if err != nil { return }
|
||||
|
||||
err = parser.expect(lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
}
|
||||
parser.expect(lexer.TokenKindNewline)
|
||||
if err != nil { return }
|
||||
err = parser.nextToken()
|
||||
if err != nil { return }
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -6,12 +6,55 @@ func TestType (test *testing.T) {
|
||||
checkTree ("../tests/parser/type", false,
|
||||
`:arf
|
||||
---
|
||||
type ro Basic:Int
|
||||
type ro BasicInit:Int 6
|
||||
type ro IntArray:{Int ..}
|
||||
type ro IntArrayInit:Int:3
|
||||
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 fBasic:Int
|
||||
type ro gBasicInit:Int:<6>
|
||||
type ro hIntArray:{Int ..}
|
||||
type ro iIntArrayInit:Int:3:
|
||||
<
|
||||
3298
|
||||
923
|
||||
92
|
||||
>
|
||||
`, test)
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
:arf
|
||||
--- rw -> -349820394 932748397 239485.37520 "hello world!\n" 'E' helloWorld:.,..[]{}
|
||||
--- rw -> -349820394 932748397 239485.37520 "hello world!\n" 'E' helloWorld:.,..()[]{}
|
||||
+ - ++ -- * / @ ! % %= ~ ~= = == != < <= << <<= > >= >> >>= | |= || & &= && ^ ^=
|
||||
|
@ -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,34 +13,33 @@ data ro eIntegerArray16:Int:16
|
||||
|
||||
data ro fIntegerArrayVariable:{Int ..}
|
||||
|
||||
data ro gIntegerArrayInitialized:Int:16
|
||||
data ro gIntegerArrayInitialized:Int:16:<
|
||||
3948 293 293049 948 912
|
||||
340 0 2304 0 4785 92
|
||||
>
|
||||
|
||||
# TODO: reinstate these two after phrase parsing is implemented
|
||||
# data wr hIntegerPointerInit:{Int} [& integer]
|
||||
data rw hIntegerPointerInit:{Int}:<[& integer]>
|
||||
|
||||
# data wr iMutIntegerPointerInit:{Int}:mut [& integer]
|
||||
data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
|
||||
|
||||
# TODO: maybe test identifiers somewhere else?
|
||||
data ro jObject:thing.Thing.
|
||||
thing.thing
|
||||
.this 324
|
||||
.that 2139
|
||||
data ro jObject:Obj:(
|
||||
.this:<324>
|
||||
.that:<324>)
|
||||
|
||||
data ro kNestedObject:Obj
|
||||
.this
|
||||
.bird0 324
|
||||
.bird1 "hello world"
|
||||
.that
|
||||
.bird2 123.8439
|
||||
.bird3 9328.21348239
|
||||
data ro kNestedObject:Obj:(
|
||||
.this:(
|
||||
.bird0:<324>
|
||||
.bird1:<"hello world">)
|
||||
.ro newMember:Int:<9023>
|
||||
.that:(
|
||||
.bird2:<123.8439>
|
||||
.bird3:<9328.21348239>))
|
||||
|
||||
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>
|
||||
|
@ -2,29 +2,35 @@
|
||||
---
|
||||
|
||||
enum ro Weekday:Int
|
||||
sunday
|
||||
monday
|
||||
tuesday
|
||||
wednesday
|
||||
thursday
|
||||
friday
|
||||
saturday
|
||||
- sunday
|
||||
- monday
|
||||
- tuesday
|
||||
- wednesday
|
||||
- thursday
|
||||
- friday
|
||||
- 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>)
|
||||
|
@ -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
|
||||
|
||||
@ -124,13 +124,12 @@ func ro gControlFlow
|
||||
|
||||
func ro hSetPhrase
|
||||
---
|
||||
= x:Int 3
|
||||
let x:Int:<3>
|
||||
# loc is a reference, similar to * in C
|
||||
= y:{Int} [loc x]
|
||||
= z:Int:8
|
||||
398 9 2309 983 -2387
|
||||
478 555 123
|
||||
= bird:Bird
|
||||
.that
|
||||
.whenYou 99999
|
||||
.this 324
|
||||
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>)
|
||||
|
@ -1,25 +0,0 @@
|
||||
:arf
|
||||
---
|
||||
objt ro Basic:Obj
|
||||
ro that:Basic
|
||||
ro this:Basic
|
||||
|
||||
objt ro BitFields:Obj
|
||||
ro that:Int & 1
|
||||
ro this:Int & 24 298
|
||||
|
||||
objt ro Init:Obj
|
||||
ro that:String "hello world"
|
||||
ro this:Int 23
|
||||
|
||||
objt ro ComplexInit:Obj
|
||||
ro whatever:Int:3
|
||||
230984
|
||||
849 394580
|
||||
ro complex0:Bird
|
||||
.that 98
|
||||
.this 2
|
||||
ro complex1:Bird
|
||||
.that 98902
|
||||
.this 235
|
||||
ro basic:Int 87
|
@ -7,12 +7,12 @@ 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
|
||||
-- this
|
||||
-- bird0 324
|
||||
-- bird1 "hello world"
|
||||
-- that
|
||||
-- bird2 123.8439
|
||||
-- bird3 9328.21348239
|
||||
|
||||
data ro dUninitialized:Int:16:mut
|
||||
|
||||
@ -28,9 +28,9 @@ func ro fComplexFunction
|
||||
398 9 2309 983 -2387
|
||||
478 555 123
|
||||
= bird:Bird
|
||||
.that
|
||||
.whenYou 99999
|
||||
.this 324
|
||||
-- that
|
||||
-- whenYou 99999
|
||||
-- this 324
|
||||
|
||||
func ro gExternalFunction
|
||||
> x:Int
|
||||
|
@ -1,10 +1,35 @@
|
||||
:arf
|
||||
---
|
||||
type ro Basic:Int
|
||||
type ro aBasic:Obj:(
|
||||
.ro that:Int
|
||||
.ro this:Int)
|
||||
|
||||
type ro BasicInit:Int 6
|
||||
type ro bBitFields:Obj:(
|
||||
.ro that:Int & 1
|
||||
.ro this:Int:<298> & 24)
|
||||
|
||||
type ro IntArray:{Int ..}
|
||||
type ro cInit:Obj:(
|
||||
.ro that:String:<"hello world">
|
||||
.ro this:Int:<23>)
|
||||
|
||||
type ro IntArrayInit:Int:3
|
||||
3298 923 92
|
||||
type ro dInitInherit:aBasic:(
|
||||
.that:<9384>
|
||||
.this:<389>)
|
||||
|
||||
type ro eInitAndDefine:aBasic:(
|
||||
.this:<389>
|
||||
.ro these:aBasic:(
|
||||
.ro born:Int:<4>
|
||||
.ro in:Int
|
||||
.ro the:Int:3:<9348 92384 92834>
|
||||
.this:<98>)
|
||||
.that:<9384>)
|
||||
|
||||
type ro fBasic:Int
|
||||
|
||||
type ro gBasicInit:Int:<6>
|
||||
|
||||
type ro hIntArray:{Int ..}
|
||||
|
||||
type ro iIntArrayInit:Int:3:
|
||||
<3298 923 92>
|
||||
|
Reference in New Issue
Block a user