Blocks under control flow phrases now parse

... except for switch cases. This will be added momentarily.
This commit is contained in:
Sasha Koshka 2022-09-03 15:22:18 -04:00
parent 837b1c76a4
commit bcd44828dc
4 changed files with 62 additions and 44 deletions

View File

@ -4,15 +4,6 @@ import "git.tebibyte.media/arf/arf/types"
import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
// controlFlowNames contains a list of all command names that must have a block
// underneath them.
var controlFlowNames = []string {
"if", "else", "elseif",
"for", "while",
"switch",
"defer",
}
// parseFunc parses a function section.
func (parser *ParsingOperation) parseFuncSection () (
section *FuncSection,

View File

@ -72,6 +72,14 @@ var validDelimitedPhraseTokens = append (
lexer.TokenKindRBracket,
lexer.TokenKindReturnDirection)
// controlFlowNames contains a list of all command names that must have a block
// underneath them.
var controlFlowNames = []string {
"if", "else", "elseif",
"for", "while",
"defer",
}
// parseBlock parses an indented block of phrases
func (parser *ParsingOperation) parseBlock (
indent int,
@ -205,6 +213,23 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
err = parser.nextToken()
if err != nil { return }
// if this is a control flow statement, parse
if phrase.command.kind != ArgumentKindIdentifier { return }
command := phrase.command.value.(Identifier)
if len(command.trail) != 1 { return }
isControlFlow := false
for _, name := range controlFlowNames {
if command.trail[0] == name {
isControlFlow = true
break
}
}
if isControlFlow {
phrase.block, err = parser.parseBlock(indent + 1)
}
return
}

View File

@ -154,30 +154,6 @@ func (values ArrayInitializationValues) ToString (
return
}
func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
if ownLine {
output += doIndent(indent)
}
output += "[" + phrase.command.ToString(0, false)
for _, argument := range phrase.arguments {
output += " " + argument.ToString(0, false)
}
output += "]"
if len(phrase.returnsTo) > 0 {
output += " ->"
for _, returnItem := range phrase.returnsTo {
output += " " + returnItem.ToString(0, false)
}
}
if ownLine {
output += "\n"
}
return
}
func (argument *Argument) ToString (indent int, breakLine bool) (output string) {
if !breakLine { indent = 0 }
if argument.kind == ArgumentKindNil {
@ -446,6 +422,31 @@ func (behavior *FaceBehavior) ToString (indent int) (output string) {
return
}
func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
if ownLine {
output += doIndent(indent)
}
output += "[" + phrase.command.ToString(0, false)
for _, argument := range phrase.arguments {
output += " " + argument.ToString(0, false)
}
output += "]"
if len(phrase.returnsTo) > 0 {
output += " ->"
for _, returnItem := range phrase.returnsTo {
output += " " + returnItem.ToString(0, false)
}
}
if ownLine {
output += "\n"
output += phrase.block.ToString(indent + 1)
}
return
}
func (block Block) ToString (indent int) (output string) {
for _, phrase := range block {
output += phrase.ToString(indent, true)

View File

@ -79,15 +79,6 @@ type ArrayInitializationValues struct {
values []Argument
}
// Phrase represents a function call or operator. In ARF they are the same
// syntactical concept.
type Phrase struct {
location file.Location
command Argument
arguments []Argument
returnsTo []Argument
}
// ArgumentKind specifies the type of thing the value of an argument should be
// cast to.
type ArgumentKind int
@ -232,9 +223,19 @@ type FaceSection struct {
behaviors map[string] FaceBehavior
}
// Phrase represents a function call or operator. In ARF they are the same
// syntactical concept.
type Phrase struct {
location file.Location
command Argument
arguments []Argument
returnsTo []Argument
// only applicable for
block Block
}
// Block represents a scoped/indented block of code.
// TODO: blocks will not directly nest. nested blocks will be stored as a part
// of certain control flow statements.
type Block []Phrase
// FuncOutput represents an input a function section. It is unlike an input in