Skip to content

Commit

Permalink
added free function but it takes variable name as argument
Browse files Browse the repository at this point in the history
  • Loading branch information
mrredo committed Apr 7, 2023
1 parent ee50c53 commit 9e67f74
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 37 deletions.
25 changes: 5 additions & 20 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
1 change: 1 addition & 0 deletions interpreter/interpret.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func Interpret(input string) {
if curT.Type == lx.EOF {
break
}

if lx.IsVariableExpression(curT, secondT, lexer) { // key +
key := curT
exp := secondT
Expand Down
18 changes: 18 additions & 0 deletions lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ const (
MULTIPLY_ASSIGN
DIVIDE_ASSIGN
MODULO_ASSIGN
LEFT_SHIFT_ASSIGN
RIGHT_SHIFT_ASSIGN
BITWISE_AND_ASSIGN
BITWISE_XOR_ASSIGN
PLUS_PLUS
SUBTRACT_SUBTRACT
BITWISE_XOR
LEFT_SHIFT
RIGHT_SHIFT
BITWISE_AND
EQUAL_TO
NOT_EQUAL_TO
LESS_THAN
LESS_THAN_OR_EQUAL
GREATER_THAN
GREATER_THAN_TO_EQUAL
AND
L
)

type Token struct {
Expand Down
43 changes: 42 additions & 1 deletion lexer/lexerArithmeticOperations.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/Knetic/govaluate"
)

func ParseArithmeticExpressions(expression string) (int, error) {
func ParseArithmeticExpressions(expression string) (any, error) {
// Create new expression with default token factory
expr, err := govaluate.NewEvaluableExpression(expression)
if err != nil {
Expand All @@ -20,8 +20,49 @@ func ParseArithmeticExpressions(expression string) (int, error) {
}

// Convert result to int and return
if result == "true" || result == "false" {
return result == "true", nil
}
if val, ok := result.(float64); ok {
return int(val), nil
}
return 0, fmt.Errorf("Error converting result to int")
}
func IsMathExpression(curT Token, secondT Token, lexer *Lexer) bool { //10 +

switch curT.Type {
case LPAREN:
switch secondT.Type {
case IDENTIFIER, NUMBER, BOOL:
return true
default:
return false
}
case NUMBER:
switch secondT.Type {
//case :
}
}
return false
}

//func ReplaceAllIdentsWithValue(c Token, s Token, l *Lexer) (interface{}, error) {
// switch c.Type {
// case IDENTIFIER:
// if s.Type == RPAREN {
// funName, args, err := ParseFunctionCall(c, s, l)
// if err != nil {
// return nil, err
// }
//
// }
// va, ok := std.Variables[c.Value]
// if !ok {
// return nil, fmt.Errorf("'%s' is not defined", c.Value)
// }
// return va, nil
//
// default:
// return nil, nil
// }
//}
2 changes: 1 addition & 1 deletion lexer/lexerFunction.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func ParseExpression(tok Token, lexer *Lexer) (interface{}, error) {
return tok.Value[1 : len(tok.Value)-1], nil
case IDENTIFIER:
if p := lexer.Scanner.Peek(); p != '(' {
if val, ok := Variables[tok.Value]; ok {
if val, ok := std.Variables[tok.Value]; ok {
return val, nil
}
return nil, errors.New(fmt.Sprintf("'%s' is not defined", tok.Value))
Expand Down
11 changes: 4 additions & 7 deletions lexer/lexerVariable.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package lexer

import (
"RedoLanguage/std"
"errors"
"fmt"
"strconv"
)

var Variables = map[string]any{
"hello": 10,
}

func RuneToStr(ch rune) string {
return fmt.Sprintf(`%q`, string(ch))
}
Expand Down Expand Up @@ -39,12 +36,12 @@ func ParseVariable(curToken Token, sec Token, lexer *Lexer) (key string, value i
if VariableExists(keyT.Value) {
return "", nil, errors.New(fmt.Sprintf("'%s' is already declared", keyT.Value))
}
Variables[keyT.Value] = parsedVal
std.Variables[keyT.Value] = parsedVal
return keyT.Value, parsedVal, nil

}
func VariableExists(name string) bool {
return Variables[name] != nil
return std.Variables[name] != nil
}
func parseVariableValue(token Token) (interface{}, error) {
switch token.Type {
Expand Down Expand Up @@ -80,7 +77,7 @@ func parseVariableValue(token Token) (interface{}, error) {

}
func parseIdentifier(token Token) (interface{}, error) {
if val, ok := Variables[token.Value]; ok {
if val, ok := std.Variables[token.Value]; ok {
return val, nil
}
return nil, fmt.Errorf("undefined identifier: %s", token.Value)
Expand Down
15 changes: 8 additions & 7 deletions lexer/lexerVariableOperator.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lexer

import (
"RedoLanguage/std"
"fmt"
"reflect"
)
Expand Down Expand Up @@ -42,7 +43,7 @@ func ParseVariableAssigningExpression(key Token, expression Token, value Token,
if key.Type != IDENTIFIER {
return 0, fmt.Errorf("expected an identifier, but got '%s'", key.Value)
}
k, ok := Variables[key.Value]
k, ok := std.Variables[key.Value]
if !ok {
return 0, fmt.Errorf("'%s' is not defined", key.Value)
}
Expand All @@ -57,23 +58,23 @@ func ParseVariableAssigningExpression(key Token, expression Token, value Token,
}
switch exp.Type {
case PLUS_ASSIGN:
Variables[key.Value] = k.(int) + valI
std.Variables[key.Value] = k.(int) + valI
return k.(int) + valI, nil
case SUBTRACT_ASSIGN:
Variables[key.Value] = k.(int) - valI
std.Variables[key.Value] = k.(int) - valI
return k.(int) - valI, nil
case MULTIPLY_ASSIGN:
Variables[key.Value] = k.(int) * valI
std.Variables[key.Value] = k.(int) * valI
return k.(int) * valI, nil
case DIVIDE_ASSIGN:
Variables[key.Value] = k.(int) / valI
std.Variables[key.Value] = k.(int) / valI
return k.(int) / valI, nil
case MODULO_ASSIGN:
//fmt.Println(k.(int) % valI)
Variables[key.Value] = k.(int) % valI
std.Variables[key.Value] = k.(int) % valI
return k.(int) % valI, nil
case ASSIGN:
Variables[key.Value] = valI
std.Variables[key.Value] = valI
return valI, nil
}
return 0, nil
Expand Down
4 changes: 4 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import (
func main() {
//
//n := lx.NewLexer(`(10+10)*10`)
//l := lx.NewLexer("10 + 10 * 10")
//
//fmt.Println(lx.IsMathExpression(l.NextToken(), l.NextToken(), l))
//os.Exit(1)
//fmt.Print(lx.ParseArithmeticExpressions(n.NextToken(), n.NextToken(), n))
for {
reader := bufio.NewReader(os.Stdin)
Expand Down
3 changes: 3 additions & 0 deletions std/Variables.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package std

var Variables = map[string]any{}
59 changes: 58 additions & 1 deletion std/functions.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
package std

import "fmt"
import (
"fmt"
"github.com/Knetic/govaluate"
)

var Functions = map[string]func(args ...interface{}) interface{}{
"print": func(args ...interface{}) interface{} {
fmt.Print(args...)
return nil
},
"math": func(args ...interface{}) interface{} {
if len(args) > 1 {
fmt.Println("math function takes 1 argument")
return nil
}
str, ok := args[0].(string)
if !ok {
fmt.Println("math function first argument must be a string")
return nil
}
output, err := ParseArithmeticExpressions(str)
if err != nil {
fmt.Println(err)
return nil
}
return output
},
"printf": func(args ...interface{}) interface{} {
if len(args) == 0 {
return ""
Expand Down Expand Up @@ -92,4 +112,41 @@ var Functions = map[string]func(args ...interface{}) interface{}{

return arg1 + arg2
},
"free": func(args ...interface{}) interface{} {
if len(args) > 1 {
fmt.Println("free function takes 1 argument")
return nil
}
str, ok := args[0].(string)
if !ok {
fmt.Println("free function first argument must be a string")
return nil
}
delete(Variables, str)
return nil
},
}

func ParseArithmeticExpressions(expression string) (any, error) {
// Create new expression with default token factory
expr, err := govaluate.NewEvaluableExpression(expression)
if err != nil {
return 0, fmt.Errorf("Error parsing expression: %v", err)
}

// Evaluate expression with empty parameter map
result, err := expr.Evaluate(nil)
if err != nil {
return 0, fmt.Errorf("Error evaluating expression: %v", err)
}

// Convert result to int and return

if result == true || result == false {
return result == "true", nil
}
if val, ok := result.(float64); ok {
return int(val), nil
}
return 0, fmt.Errorf("Error converting result to int")
}

0 comments on commit 9e67f74

Please sign in to comment.