Skip to content

Commit

Permalink
fixing some stuff and added advanced err messages to arihtmetic expre…
Browse files Browse the repository at this point in the history
…ssions
  • Loading branch information
mrredo committed Apr 10, 2023
1 parent 2bf6eb0 commit 8e6a070
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 152 deletions.
6 changes: 6 additions & 0 deletions err/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ func NewUndefinedError(variableName string, pos scanner.Position) error {
func NewTypeError(pos scanner.Position) error {
return Error(MismatchedTypesInExpression, TypeError, pos)
}
func NewExpressionError(format string, msg string, pos scanner.Position) error {
return Error(fmt.Sprintf(format, msg), ExpressionError, pos)
}
func NewFunctionVoidError(variableName string, pos scanner.Position) error {
return Error(fmt.Sprintf(FunctionReturnsVoid, variableName), InvalidFunctionCall, pos)
}
8 changes: 7 additions & 1 deletion err/errorMessages.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package err
const (
VariableNotDefined = "'%s' is not defined"
MismatchedTypesInExpression = "mismatched types in expression"
FunctionReturnsVoid = ""
FunctionReturnsVoid = "'%s' method returns void"
VariableAlreadyDeclared = "'%s' is already declared"
//math
ErrorParsingExpression = "failed parsing math expression - %v"
ErrorEvaluatingExpression = "failed evaluating math expression - %v"
ErrorConvertingResultToInt = ""
//

)
2 changes: 2 additions & 0 deletions err/errorTypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ const (
SyntaxError = "syntax error"
RefrenceError = "refrence error"
TypeError = "type error"
ExpressionError = "expression error"
InvalidFunctionCall = "invalid function call"
)
5 changes: 2 additions & 3 deletions interpreter/interpret.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package interpreter
import (
lx "RedoLanguage/lexer"
"RedoLanguage/std"
"fmt"
"log"
"strings"
)
Expand All @@ -19,7 +18,7 @@ func Interpret(input string) {

curT := secondTS
secondT := lexer.NextToken()
if curT.Type == lx.EOF {
if curT.Type == lx.EOF || secondT.Type == lx.EOF {
break
}

Expand All @@ -41,7 +40,7 @@ func Interpret(input string) {
}

if lx.IsVariable(curT) {
fmt.Println(curT, secondT)

_, _, err := lx.ParseVariable(curT, secondT, lexer)
if err != nil {
log.Println(err)
Expand Down
1 change: 0 additions & 1 deletion lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
)

type TokenType int

const (
EOF TokenType = iota // end of file
LPAREN // (
Expand Down
103 changes: 13 additions & 90 deletions lexer/lexerArithmeticOperations.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import (
"reflect"
)

func ParseArithmeticExpressions(expression string) (any, error) {
func ParseArithmeticExpressions(expression string, l *Lexer) (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)
expr, errs := govaluate.NewEvaluableExpression(expression)
if errs != nil {
return 0, err.NewExpressionError(err.ErrorParsingExpression, errs.Error(), l.Scanner.Pos()) //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)
result, errss := expr.Evaluate(nil)
if errss != nil {
return 0, err.NewExpressionError(err.ErrorEvaluatingExpression, errss.Error(), l.Scanner.Pos()) //fmt.Errorf("error evaluating expression: %v", err)
}

// Convert result to int and return
Expand All @@ -32,81 +32,10 @@ func ParseArithmeticExpressions(expression string) (any, error) {
if val, ok := result.(float64); ok {
return int(val), nil
}
return 0, fmt.Errorf("error converting result to int")
}
func MathExpressionTokensToEndFunctionArgument(c Token, l *Lexer) (string, Token, error) {
var tokenArr []Token

var RPcount = 0
var LPcount = 0
var finalStr string
for {
if c.Type == SEMICOLON || c.Type == NEW_LINE || c.Type == EOF || c.Type == COMMA {
break
}
if p := l.Scanner.Pos(); p.Offset == len(l.Input)-2 {
break
}
if p := l.Scanner.Peek(); p == ';' || p == '\n' {
break
}

switch c.Type {
case IDENTIFIER:
if p := l.Scanner.Peek(); p == '(' {
s := l.NextToken()
f, args, err := ParseFunctionCall(c, s, l)
if err != nil {
return "", c, err
}
out, ok := std.Functions[f]

if !ok {
return "", c, fmt.Errorf("'%s' function is not defined", c.Value)
}
o := out(args...)
if o == nil {
return "", c, fmt.Errorf("invalid function call: '%s' function does not return a value", c.Value)
}
finalStr += fmt.Sprint(o)
c = l.NextToken()
continue
} else {
va, ok := std.Variables[c.Value]
if !ok {
return "", c, fmt.Errorf("'%s' is not defined", c.Value)
}
finalStr += fmt.Sprint(va)
tokenArr = append(tokenArr, c)
}

case LPAREN:
LPcount++
finalStr += "("
tokenArr = append(tokenArr, c)
case RPAREN:

RPcount++
finalStr += ")"
tokenArr = append(tokenArr, c)
default:
finalStr += c.Value
tokenArr = append(tokenArr, c)
}

c = l.NextToken()
//if c.Type != RPAREN || c.Type != LPAREN {
// OperatorTurn = !OperatorTurn
//}
}
//if LPcount != RPcount {
// return "", fmt.Errorf("invalid left/right parentheses count")
//}
return finalStr, c, nil
return 0, err.NewExpressionError(err.ErrorConvertingResultToInt, "", l.Scanner.Pos()) //fmt.Errorf("error converting result to int")
}

func MathExpressionTokensToEnd(c Token, l *Lexer, function ...bool) (string, Token, error) {
var tokenArr []Token

var RPcount = 0
var LPcount = 0
Expand All @@ -117,10 +46,10 @@ func MathExpressionTokensToEnd(c Token, l *Lexer, function ...bool) (string, Tok
if c.Type == SEMICOLON || c.Type == NEW_LINE || c.Type == EOF || c.Type == COMMA {
break
}
fmt.Println(c)
if p := l.Scanner.Pos(); p.Offset == len(l.Input)-2 && len(function) >= 1 {
break
}

if p := l.Scanner.Peek(); p == ';' || p == '\n' {
break
}
Expand All @@ -133,7 +62,6 @@ func MathExpressionTokensToEnd(c Token, l *Lexer, function ...bool) (string, Tok
return "", c, err.NewTypeError(l.Scanner.Pos())
}
finalStr += c.Value
tokenArr = append(tokenArr, c)
case BOOL, NUMBER:

if curType == -1 {
Expand All @@ -143,7 +71,6 @@ func MathExpressionTokensToEnd(c Token, l *Lexer, function ...bool) (string, Tok
return "", c, err.NewTypeError(l.Scanner.Pos())
}
finalStr += c.Value
tokenArr = append(tokenArr, c)

case IDENTIFIER:
if p := l.Scanner.Peek(); p == '(' {
Expand All @@ -155,11 +82,12 @@ func MathExpressionTokensToEnd(c Token, l *Lexer, function ...bool) (string, Tok
out, ok := std.Functions[f]

if !ok {
return "", c, fmt.Errorf("'%s' function is not defined", c.Value)
return "", c, err.NewUndefinedError(c.Value, l.Scanner.Pos()) //fmt.Errorf("'%s' function is not defined", c.Value)
}
o := out(args...)

if o == nil {
return "", c, fmt.Errorf("invalid function call: '%s' function does not return a value", c.Value)
return "", c, err.NewFunctionVoidError(c.Value, l.Scanner.Pos()) //fmt.Errorf("invalid function call: '%s' function does not return a value", c.Value)
}
if vas, ok1 := o.(string); ok1 {
finalStr += fmt.Sprintf(`"%s"`, vas)
Expand All @@ -182,15 +110,14 @@ func MathExpressionTokensToEnd(c Token, l *Lexer, function ...bool) (string, Tok
} else {
va, ok := std.Variables[c.Value]
if !ok {
return "", c, fmt.Errorf("'%s' is not defined", c.Value)
return "", c, err.NewUndefinedError(c.Value, l.Scanner.Pos()) //fmt.Errorf("'%s' is not defined", c.Value)
}
if vas, ok1 := va.(string); ok1 {
finalStr += fmt.Sprintf(`"%s"`, vas)
} else {
finalStr += fmt.Sprint(va)
}

tokenArr = append(tokenArr, c)
if curType == -1 {
curType = ConvertToTokenType(reflect.TypeOf(fmt.Sprint(va)).String())
}
Expand All @@ -204,20 +131,16 @@ func MathExpressionTokensToEnd(c Token, l *Lexer, function ...bool) (string, Tok
case OR, AND:
curType = -1
finalStr += c.Value
tokenArr = append(tokenArr, c)
case LPAREN:
LPcount++
finalStr += "("
tokenArr = append(tokenArr, c)
case RPAREN:

RPcount++
finalStr += ")"
tokenArr = append(tokenArr, c)
default:

finalStr += c.Value
tokenArr = append(tokenArr, c)
}

c = l.NextToken()
Expand Down
8 changes: 5 additions & 3 deletions lexer/lexerFunction.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ func ParseFunctionCall(curT Token, sec Token, lexer *Lexer) (string, []interface
if errs != nil {
return "", nil, errs
}
o, errss := ParseArithmeticExpressions(out)
fmt.Println(out)
tok = l
o, errss := ParseArithmeticExpressions(out[:len(out)-1], lexer)
if errss != nil {
return "", nil, errss
}
tok = l

//arg, err := ParseExpression(tok, lexer)
//if err != nil {
// return "", nil, err
Expand Down Expand Up @@ -93,7 +95,7 @@ func ParseExpression(tok Token, lexer *Lexer) (interface{}, error) {
if val, ok := std.Variables[tok.Value]; ok {
return val, nil
}
return nil, errors.New(fmt.Sprintf("'%s' is not defined", tok.Value))
return nil, fmt.Errorf("'%s' is not defined", tok.Value)
}

//if tok.Value == "true" {
Expand Down
42 changes: 2 additions & 40 deletions lexer/lexerVariable.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"RedoLanguage/std"
"errors"
"fmt"
"strconv"

)

func RuneToStr(ch rune) string {
Expand Down Expand Up @@ -52,7 +52,7 @@ func ParseVariable(curToken Token, sec Token, lexer *Lexer) (key string, value i
if errs != nil {
return "", nil, errs
}
o, errss := ParseArithmeticExpressions(out)
o, errss := ParseArithmeticExpressions(out, lexer)
if errss != nil {
return "", 0, errss
}
Expand All @@ -72,42 +72,4 @@ func ParseVariable(curToken Token, sec Token, lexer *Lexer) (key string, value i
func VariableExists(name string) bool {
return std.Variables[name] != nil
}
func parseVariableValue(token Token) (interface{}, error) {
switch token.Type {
case 0:
return nil, nil
case NUMBER:
return strconv.Atoi(token.Value)
case STRING:
return token.Value[1 : len(token.Value)-1], nil
case BOOL:
if token.Value == "true" {
return true, nil
}
return false, nil

case IDENTIFIER:
return parseIdentifier(token)
default:
/*
TODO: {
1. check if identifier exists and if does return identifier value
2. check if function then take function output if function returns nothing throw err
}

*/
return nil, nil

}

}
func parseIdentifier(token Token) (interface{}, error) {
if val, ok := std.Variables[token.Value]; ok {
return val, nil
}
return nil, fmt.Errorf("undefined identifier: %s", token.Value)
}
Loading

0 comments on commit 8e6a070

Please sign in to comment.