Implemented block instruction parsing
This commit is contained in:
parent
4fc1935183
commit
dd495fab4e
@ -8,5 +8,7 @@ hello() {
|
|||||||
address := 4194305
|
address := 4194305
|
||||||
length := 3
|
length := 3
|
||||||
|
|
||||||
|
loop {
|
||||||
syscall(write, stdout, address, length)
|
syscall(write, stdout, address, length)
|
||||||
}
|
}
|
||||||
|
}
|
@ -28,28 +28,40 @@ type Function struct {
|
|||||||
// Compile turns a function into machine code.
|
// Compile turns a function into machine code.
|
||||||
func (f *Function) Compile() {
|
func (f *Function) Compile() {
|
||||||
f.Assembler.Label(f.Name)
|
f.Assembler.Label(f.Name)
|
||||||
|
err := f.CompileTokens(f.Body)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
f.Error = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Assembler.Return()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompileTokens compiles a token list.
|
||||||
|
func (f *Function) CompileTokens(body token.List) error {
|
||||||
start := 0
|
start := 0
|
||||||
groupLevel := 0
|
groupLevel := 0
|
||||||
|
blockLevel := 0
|
||||||
|
|
||||||
for i, t := range f.Body {
|
for i, t := range body {
|
||||||
if start == i && (t.Kind == token.NewLine || t.Kind == token.BlockStart || t.Kind == token.BlockEnd) {
|
if start == i && t.Kind == token.NewLine {
|
||||||
start = i + 1
|
start = i + 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t.Kind {
|
switch t.Kind {
|
||||||
case token.NewLine:
|
case token.NewLine:
|
||||||
if groupLevel > 0 {
|
if groupLevel > 0 || blockLevel > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if start != -1 {
|
if start != -1 {
|
||||||
instruction := f.Body[start:i]
|
instruction := body[start:i]
|
||||||
err := f.CompileInstruction(instruction)
|
err := f.CompileInstruction(instruction)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Error = err
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start = -1
|
start = -1
|
||||||
@ -62,10 +74,16 @@ func (f *Function) Compile() {
|
|||||||
|
|
||||||
case token.GroupEnd:
|
case token.GroupEnd:
|
||||||
groupLevel--
|
groupLevel--
|
||||||
|
|
||||||
|
case token.BlockStart:
|
||||||
|
blockLevel++
|
||||||
|
|
||||||
|
case token.BlockEnd:
|
||||||
|
blockLevel--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.Assembler.Return()
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompileInstruction compiles a single instruction.
|
// CompileInstruction compiles a single instruction.
|
||||||
@ -109,6 +127,20 @@ func (f *Function) CompileKeyword(line token.List) error {
|
|||||||
|
|
||||||
f.Assembler.Return()
|
f.Assembler.Return()
|
||||||
|
|
||||||
|
case "loop":
|
||||||
|
blockStart := line.IndexKind(token.BlockStart) + 1
|
||||||
|
blockEnd := line.LastIndexKind(token.BlockEnd)
|
||||||
|
|
||||||
|
if blockStart == -1 {
|
||||||
|
return errors.New(errors.MissingBlockStart, f.File, line[0].End())
|
||||||
|
}
|
||||||
|
|
||||||
|
if blockEnd == -1 {
|
||||||
|
return errors.New(errors.MissingBlockEnd, f.File, line[len(line)-1].End())
|
||||||
|
}
|
||||||
|
|
||||||
|
return f.CompileTokens(line[blockStart:blockEnd])
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return errors.New(&errors.KeywordNotImplemented{Keyword: line[0].Text()}, f.File, line[0].Position)
|
return errors.New(&errors.KeywordNotImplemented{Keyword: line[0].Text()}, f.File, line[0].Position)
|
||||||
}
|
}
|
||||||
@ -119,7 +151,7 @@ func (f *Function) CompileKeyword(line token.List) error {
|
|||||||
// CompileVariableDefinition compiles a variable definition.
|
// CompileVariableDefinition compiles a variable definition.
|
||||||
func (f *Function) CompileVariableDefinition(expr *expression.Expression) error {
|
func (f *Function) CompileVariableDefinition(expr *expression.Expression) error {
|
||||||
if len(expr.Children) < 2 {
|
if len(expr.Children) < 2 {
|
||||||
return errors.New(errors.MissingAssignValue, f.File, expr.LastChild().Token.After())
|
return errors.New(errors.MissingAssignValue, f.File, expr.LastChild().Token.End())
|
||||||
}
|
}
|
||||||
|
|
||||||
name := expr.Children[0].Token.Text()
|
name := expr.Children[0].Token.Text()
|
||||||
|
@ -192,12 +192,11 @@ func scanFile(path string, functions chan<- *Function) error {
|
|||||||
return errors.New(errors.MissingBlockStart, file, tokens[i].Position)
|
return errors.New(errors.MissingBlockStart, file, tokens[i].Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
i++
|
|
||||||
|
|
||||||
if blockLevel == 0 {
|
if blockLevel == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,5 +236,6 @@ func scanFile(path string, functions chan<- *Function) error {
|
|||||||
nameStart = -1
|
nameStart = -1
|
||||||
paramsStart = -1
|
paramsStart = -1
|
||||||
bodyStart = -1
|
bodyStart = -1
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,5 @@ package token
|
|||||||
// Keywords defines the keywords used in the language.
|
// Keywords defines the keywords used in the language.
|
||||||
var Keywords = map[string]bool{
|
var Keywords = map[string]bool{
|
||||||
"return": true,
|
"return": true,
|
||||||
|
"loop": true,
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,28 @@ import (
|
|||||||
// List is a slice of tokens.
|
// List is a slice of tokens.
|
||||||
type List []Token
|
type List []Token
|
||||||
|
|
||||||
|
// IndexKind returns the position of a token kind within a token list.
|
||||||
|
func (list List) IndexKind(kind Kind) int {
|
||||||
|
for i, token := range list {
|
||||||
|
if token.Kind == kind {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastIndexKind returns the position of the last token kind within a token list.
|
||||||
|
func (list List) LastIndexKind(kind Kind) int {
|
||||||
|
for i := len(list) - 1; i >= 0; i-- {
|
||||||
|
if list[i].Kind == kind {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
// String implements string serialization.
|
// String implements string serialization.
|
||||||
func (list List) String() string {
|
func (list List) String() string {
|
||||||
builder := bytes.Buffer{}
|
builder := bytes.Buffer{}
|
||||||
|
@ -11,8 +11,8 @@ type Token struct {
|
|||||||
Bytes []byte
|
Bytes []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// After returns the position after the token.
|
// End returns the position after the token.
|
||||||
func (t *Token) After() int {
|
func (t *Token) End() int {
|
||||||
return t.Position + len(t.Bytes)
|
return t.Position + len(t.Bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user