diff options
author | Himbeer <himbeer@disroot.org> | 2024-08-30 22:27:48 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-08-30 22:27:48 +0200 |
commit | bb80a9c772b077bdc7173055e88c3e9f8bb1c35b (patch) | |
tree | daf2a813e4d33983a0eeab7f78f190da6c6f3eac | |
parent | 4019e81876fdceccf2db58182160d996546adaa5 (diff) |
Allow the use of local variables in expressions
-rw-r--r-- | GRAMMAR.txt | 3 | ||||
-rw-r--r-- | expression.go | 13 | ||||
-rw-r--r-- | generate.go | 15 | ||||
-rw-r--r-- | parse.go | 28 |
4 files changed, 57 insertions, 2 deletions
diff --git a/GRAMMAR.txt b/GRAMMAR.txt index bd7b4d4..68177fc 100644 --- a/GRAMMAR.txt +++ b/GRAMMAR.txt @@ -26,10 +26,11 @@ term -> numeral ( ( "<<" | ">>" ) numeral )* numeral -> factor ( ( "+" | "-" ) factor )* factor -> unary ( ( "*" | "/" ) unary )* unary -> ( "-" | "!" | "~" )? primary -primary -> grouping | literal | call +primary -> grouping | literal | call | variable grouping -> "(" expression ")" literal -> string | number string -> STRING* number -> NUMBER IDENTIFIER call -> IDENTIFIER "(" arg? ")" arg -> expression ( "," arg )? +variable -> IDENTIFIER diff --git a/expression.go b/expression.go index 285cac3..9752730 100644 --- a/expression.go +++ b/expression.go @@ -323,3 +323,16 @@ type argument struct { value exprExpr next *argument } + +type varExpr struct { + name string + ln int +} + +func (v *varExpr) markExpr() {} + +func (v *varExpr) markExprExpr() {} + +func (v *varExpr) markPrimaryExpr() {} + +func (v *varExpr) line() int { return v.ln } diff --git a/generate.go b/generate.go index 187ec8f..5701cb1 100644 --- a/generate.go +++ b/generate.go @@ -476,3 +476,18 @@ func (c *callExpr) generate(w io.Writer) (string, error) { return ret, nil } + +func (v *varExpr) generate(w io.Writer) (string, error) { + ok, mutable := isDeclared(v.name, false) + if !ok { + return "", errUndeclared{name: v.name, line: v.line()} + } + + if mutable { + reg := allocReg() + fmt.Fprintf(w, "%s =w loadl %%%s\n", reg, v.name) + return reg, nil + } + + return localConsts[currentFunc][v.name], nil +} @@ -801,6 +801,14 @@ func parsePrimary(toks *tokens) (primaryExpr, error) { return call, nil } + variable, err := parseVariable(toks) + if err != nil { + return nil, err + } + if variable != nil { + return variable, nil + } + return nil, expectedPrimary{got: toks.current()} } @@ -923,9 +931,14 @@ func parseCall(toks *tokens) (*callExpr, error) { return nil, nil } - if err := toks.mustMatch(lparen); err != nil { + ok, err := toks.match(lparen) + if err != nil { return nil, err } + if !ok { + toks.unreadTokens(2) + return nil, nil + } args, err := parseArg(toks) if err != nil { @@ -970,3 +983,16 @@ func parseArg(toks *tokens) (*argument, error) { return &argument{value: arg, next: next}, nil } + +func parseVariable(toks *tokens) (*varExpr, error) { + nameTok, ok := toks.consumeToken() + if !ok { + return nil, unexpectedEOF + } + if nameTok.kind != identifier { + toks.unreadToken() + return nil, nil + } + + return &varExpr{name: nameTok.value, ln: nameTok.line}, nil +} |