diff --git a/src/more_math/helperFunc.py b/src/more_math/helperFunc.py index d9cfe4d..3d8530f 100644 --- a/src/more_math/helperFunc.py +++ b/src/more_math/helperFunc.py @@ -30,9 +30,9 @@ def evaluate_tensor_expression(ast, variables): op, operand_expr = ast[1] operand_val = evaluate_tensor_expression(operand_expr, variables) if op == '+': - return operand_val + return to_tensor(operand_val,variables['a']) elif op == '-': - return torch.neg(operand_val) + return torch.neg(to_tensor(operand_val,variables['a'])) else: raise ValueError(f"Unsupported unary operator: {op}") @@ -45,15 +45,15 @@ def evaluate_tensor_expression(ast, variables): if func_name == 'ABS': return torch.abs(arg_vals[0]) elif func_name == 'NORM': - return torch.nn.functional.normalize(arg_vals[0], p=2, dim=-1) + return torch.nn.functional.normalize(to_tensor(arg_vals[0],variables['a']), p=2, dim=-1) elif func_name == 'SQRT': - return torch.sqrt(arg_vals[0]) + return torch.sqrt(to_tensor(arg_vals[0],variables['a'])) elif func_name == 'SIN': - return torch.sin(arg_vals[0]) + return torch.sin(to_tensor(arg_vals[0],variables['a'])) elif func_name == 'COS': - return torch.cos(arg_vals[0]) + return torch.cos(to_tensor(arg_vals[0],variables['a'])) elif func_name == 'TAN': - return torch.tan(arg_vals[0]) + return torch.tan(to_tensor(arg_vals[0],variables['a'])) elif func_name == 'MAX': return torch.max(*arg_vals) elif func_name == 'MIN': diff --git a/src/more_math/parser.py b/src/more_math/parser.py index 93de2f0..039db21 100644 --- a/src/more_math/parser.py +++ b/src/more_math/parser.py @@ -11,14 +11,25 @@ class Parser: self.pos += 1 return token + def expect(self, expected_type=None, expected_value=None): + tok_type, value = self.peek() + if expected_type and tok_type != expected_type: + raise SyntaxError( + f"Expected token type {expected_type}, got {tok_type} ('{value}') at position {self.pos}." + ) + if expected_value and value != expected_value: + raise SyntaxError( + f"Expected token value '{expected_value}', got '{value}' at position {self.pos}." + ) + return self.consume() + def parse_expression(self): - """Expression: term (PLUS|MINUS term)*""" left = self.parse_term() while True: tok_type, value = self.peek() if value in ['+', '-']: op = value - self.consume() # Consume '+' or '-' + self.consume() right = self.parse_term() left = ('BINOP', (op, left, right)) else: @@ -26,13 +37,12 @@ class Parser: return left def parse_term(self): - """Term: factor (MULT|DIVIDE|POW|MOD factor)*""" left = self.parse_factor() while True: tok_type, value = self.peek() if value in ['*', '/', '^', '%']: op = value - self.consume() # Consume '*', '/', '^' nebo '%' + self.consume() right = self.parse_factor() left = ('BINOP', (op, left, right)) else: @@ -40,7 +50,6 @@ class Parser: return left def parse_arguments(self): - """Parse comma-separated argument list for function calls.""" args = [] if self.peek()[0] == 'OP' and self.peek()[1] == ')': return args # žádné argumenty @@ -49,13 +58,12 @@ class Parser: args.append(arg) tok_type, value = self.peek() if tok_type == 'OP' and value == ',': - self.consume() # přeskoč čárku + self.consume() else: break return args def parse_factor(self): - """Factor: unary_op factor | variable | function_call | number | parenthesis""" tok_type, value = self.peek() # Podpora unárních operátorů + a - @@ -68,23 +76,54 @@ class Parser: if tok_type == 'OP' and value == '(': self.consume() # Skip '(' expr = self.parse_expression() - assert self.peek()[0] == 'OP' and self.peek()[1] == ')', "Missing closing parenthesis" + if self.peek()[0] != 'OP' or self.peek()[1] != ')': + raise SyntaxError( + f"Missing closing parenthesis at position {self.pos}." + ) self.consume() # Skip ')' return ('PARENTHESIS', expr) elif tok_type == 'NAME': - func_name = value + name = value self.consume() + # Podpora matematických konstant + if name.lower() == 'pi': + return ('LITERAL', 3.141592653589793) + if name.lower() == 'e': + return ('LITERAL', 2.718281828459045) if self.peek()[0] == 'OP' and self.peek()[1] == '(': self.consume() # Skip '(' args = self.parse_arguments() - assert self.peek()[0] == 'OP' and self.peek()[1] == ')', "Missing closing parenthesis" + if self.peek()[0] != 'OP' or self.peek()[1] != ')': + raise SyntaxError( + f"Missing closing parenthesis for function '{name}' at position {self.pos}." + ) self.consume() - return ('FUNCTION', (func_name.upper(), args)) + return ('FUNCTION', (name.upper(), args)) else: - return ('VARIABLE', func_name) + return ('VARIABLE', name) elif tok_type == 'NUMBER': - num = float(value) + try: + num = float(value) + except Exception: + raise SyntaxError( + f"Invalid number '{value}' at position {self.pos}." + ) self.consume() return ('LITERAL', num) + + elif tok_type == 'OP' and value == ')': + raise SyntaxError( + f"Unexpected right parenthesis ')' at position {self.pos}." + ) + + elif tok_type == 'ENDMARKER': + raise SyntaxError( + "Unexpected end of input. Check for missing arguments or closing parentheses." + ) + + else: + raise SyntaxError( + f"Unexpected token '{value}' of type {tok_type} at position {self.pos}." + )