Added some primitive phrase parsing
This commit is contained in:
parent
fccb67e5c0
commit
44021fe875
118
parser/func.go
118
parser/func.go
@ -4,6 +4,22 @@ import "git.tebibyte.media/arf/arf/types"
|
|||||||
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"
|
||||||
|
|
||||||
|
// validBlockLevelPhraseTokens lists all tokens that are expected when parsing
|
||||||
|
// a block level phrase.
|
||||||
|
var validBlockLevelPhraseTokens = append (
|
||||||
|
validArgumentStartTokens,
|
||||||
|
lexer.TokenKindNewline,
|
||||||
|
lexer.TokenKindReturnDirection)
|
||||||
|
|
||||||
|
// validDelimitedBlockLevelPhraseTokens is like validBlockLevelPhraseTokens, but
|
||||||
|
// it also includes a right brace token.
|
||||||
|
var validDelimitedBlockLevelPhraseTokens = append (
|
||||||
|
validArgumentStartTokens,
|
||||||
|
lexer.TokenKindNewline,
|
||||||
|
lexer.TokenKindIndent,
|
||||||
|
lexer.TokenKindRBracket,
|
||||||
|
lexer.TokenKindReturnDirection)
|
||||||
|
|
||||||
// parseFunc parses a function section.
|
// parseFunc parses a function section.
|
||||||
func (parser *ParsingOperation) parseFuncSection () (
|
func (parser *ParsingOperation) parseFuncSection () (
|
||||||
section *FuncSection,
|
section *FuncSection,
|
||||||
@ -201,7 +217,6 @@ func (parser *ParsingOperation) parseFuncArguments (
|
|||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,5 +227,106 @@ func (parser *ParsingOperation) parseBlock (
|
|||||||
block Block,
|
block Block,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
|
for {
|
||||||
|
// if we've left the block, stop parsing
|
||||||
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
|
if parser.token.Value().(int) != indent { return }
|
||||||
|
|
||||||
|
var phrase Phrase
|
||||||
|
phrase, err = parser.parseBlockLevelPhrase(indent)
|
||||||
|
block = append(block, phrase)
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseBlockLevelPhrase parses a phrase that is not being used as an argument
|
||||||
|
// to something else. This method is allowed to do things like parse return
|
||||||
|
// directions, and indented blocks beneath the phrase.
|
||||||
|
func (parser *ParsingOperation) parseBlockLevelPhrase (
|
||||||
|
indent int,
|
||||||
|
) (
|
||||||
|
phrase Phrase,
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
if !parser.token.Is(lexer.TokenKindIndent) { return }
|
||||||
|
if parser.token.Value().(int) != indent { return }
|
||||||
|
err = parser.nextToken(validArgumentStartTokens...)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
expectRightBracket := false
|
||||||
|
if parser.token.Is(lexer.TokenKindLBracket) {
|
||||||
|
expectRightBracket = true
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
// get command
|
||||||
|
err = parser.expect(validArgumentStartTokens...)
|
||||||
|
if err != nil { return }
|
||||||
|
phrase.command, err = parser.parseArgument()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
for {
|
||||||
|
if expectRightBracket {
|
||||||
|
// delimited
|
||||||
|
// [someFunc arg1 arg2 arg3] -> someVariable
|
||||||
|
err = parser.expect(validDelimitedBlockLevelPhraseTokens...)
|
||||||
|
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
|
||||||
|
// someFunc arg1 arg2 arg3 -> someVariable
|
||||||
|
err = parser.expect(validBlockLevelPhraseTokens...)
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
if parser.token.Is(lexer.TokenKindReturnDirection) {
|
||||||
|
// we've reached a return direction, so that
|
||||||
|
// means this is the end of the phrase
|
||||||
|
break
|
||||||
|
} else if parser.token.Is(lexer.TokenKindNewline) {
|
||||||
|
// we've reached the end of the line, so that
|
||||||
|
// means this is the end of the phrase.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// this is an argument
|
||||||
|
var argument Argument
|
||||||
|
argument, err = parser.parseArgument()
|
||||||
|
phrase.arguments = append(phrase.arguments, argument)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: expect return direction, or newline. then go onto the next
|
||||||
|
// line, parsing returnsTo if nescessary.
|
||||||
|
err = parser.expect(lexer.TokenKindNewline)
|
||||||
|
if err != nil { return }
|
||||||
|
err = parser.nextToken()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: create parseArgumentLevelPhrase, and call it from parseArgument
|
||||||
|
Reference in New Issue
Block a user