diff --git a/analyzer/block.go b/analyzer/block.go index 4ad34e1..1ecd154 100644 --- a/analyzer/block.go +++ b/analyzer/block.go @@ -4,7 +4,6 @@ import "git.tebibyte.media/arf/arf/parser" // Block represents a scoped block of phrases. type Block struct { - locatable phrases []Phrase // TODO: create a scope struct and embed it @@ -31,7 +30,10 @@ func (analyzer *analysisOperation) analyzeBlock ( err error, ) { for _, inputPhrase := range inputBlock { - + var outputPhrase Phrase + outputPhrase, err = analyzer.analyzePhrase(inputPhrase) + block.phrases = append(block.phrases, outputPhrase) } + return } diff --git a/analyzer/phrase.go b/analyzer/phrase.go index 1f72db9..864bd34 100644 --- a/analyzer/phrase.go +++ b/analyzer/phrase.go @@ -1,9 +1,12 @@ package analyzer +import "regexp" import "git.tebibyte.media/arf/arf/file" import "git.tebibyte.media/arf/arf/parser" import "git.tebibyte.media/arf/arf/infoerr" +var validNameRegex = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") + type Phrase interface { // Provided by phraseBase Location () (location file.Location) @@ -19,6 +22,17 @@ type ArbitraryPhrase struct { arguments []Argument } +func (phrase ArbitraryPhrase) ToString (indent int) (output string) { + output += doIndent(indent, "phrase\n") + output += doIndent(indent + 1, phrase.command, "\n") + + for _, argument := range phrase.arguments { + output += argument.ToString(indent + 1) + } + + return +} + type CastPhrase struct { phraseBase command Argument @@ -33,5 +47,41 @@ func (analyzer *analysisOperation) analyzePhrase ( phrase Phrase, err error, ) { + base := phraseBase { + + } + + arguments := []Argument { } + for index := 0; index < inputPhrase.Length(); index ++ { + inputArgument := inputPhrase.Argument(index) + + var argument Argument + argument, err = analyzer.analyzeArgument(inputArgument) + if err != nil { return } + arguments = append(arguments, argument) + } + + switch inputPhrase.Kind() { + case parser.PhraseKindArbitrary: + command := inputPhrase.Command().Value().(string) + if !validNameRegex.Match([]byte(command)) { + err = inputPhrase.NewError ( + "command cannot contain characters other " + + "than a-z, A-Z, 0-9, underscores, or begin " + + "with a number", + infoerr.ErrorKindError) + return + } + + outputPhrase := ArbitraryPhrase { + phraseBase: base, + command: command, + arguments: arguments, + } + phrase = outputPhrase + + default: + panic("phrase kind not implemented") + } return } diff --git a/parser/tree.go b/parser/tree.go index a41bc53..bb3a5a2 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -277,7 +277,7 @@ const ( // Phrase represents a function call or operator. In ARF they are the same // syntactical concept. type Phrase struct { - location file.Location + locatable returnees []Argument multiValuable