@@ -11,8 +11,8 @@ use crate::error::{GraphError, Result};
1111use nom:: {
1212 branch:: alt,
1313 bytes:: complete:: { tag, tag_no_case, take_while1} ,
14- character:: complete:: { char, multispace0, multispace1} ,
15- combinator:: { map, opt, peek, recognize} ,
14+ character:: complete:: { char, digit0 , digit1 , multispace0, multispace1, one_of } ,
15+ combinator:: { map, map_res , opt, peek, recognize} ,
1616 multi:: { many0, separated_list0, separated_list1} ,
1717 sequence:: { delimited, pair, preceded, tuple} ,
1818 IResult ,
@@ -438,8 +438,9 @@ fn comparison_operator(input: &str) -> IResult<&str, ComparisonOperator> {
438438// Parse a basic value expression (without vector functions to avoid circular dependency)
439439fn basic_value_expression ( input : & str ) -> IResult < & str , ValueExpression > {
440440 alt ( (
441- parse_parameter, // Try $parameter
442- function_call, // Regular function calls
441+ parse_vector_literal, // Try vector literal first [0.1, 0.2]
442+ parse_parameter, // Try $parameter
443+ function_call, // Regular function calls
443444 map ( property_value, ValueExpression :: Literal ) , // Try literals BEFORE property references
444445 map ( property_reference, ValueExpression :: Property ) ,
445446 map ( identifier, |id| ValueExpression :: Variable ( id. to_string ( ) ) ) ,
@@ -603,6 +604,44 @@ fn value_expression_list(input: &str) -> IResult<&str, Vec<ValueExpression>> {
603604 ) ( input)
604605}
605606
607+ // Parse a float32 literal for vectors
608+ fn float32_literal ( input : & str ) -> IResult < & str , f32 > {
609+ map_res (
610+ recognize ( tuple ( (
611+ opt ( char ( '-' ) ) ,
612+ alt ( (
613+ // Scientific notation: 1e-3, 2.5e2
614+ recognize ( tuple ( (
615+ digit1,
616+ opt ( tuple ( ( char ( '.' ) , digit0) ) ) ,
617+ one_of ( "eE" ) ,
618+ opt ( one_of ( "+-" ) ) ,
619+ digit1,
620+ ) ) ) ,
621+ // Regular float: 1.23 or integer: 123
622+ recognize ( tuple ( ( digit1, opt ( tuple ( ( char ( '.' ) , digit0) ) ) ) ) ) ,
623+ ) ) ,
624+ ) ) ) ,
625+ |s : & str | s. parse :: < f32 > ( ) ,
626+ ) ( input)
627+ }
628+
629+ // Parse vector literal: [0.1, 0.2, 0.3]
630+ fn parse_vector_literal ( input : & str ) -> IResult < & str , ValueExpression > {
631+ let ( input, _) = char ( '[' ) ( input) ?;
632+ let ( input, _) = multispace0 ( input) ?;
633+
634+ let ( input, values) = separated_list1 (
635+ tuple ( ( multispace0, char ( ',' ) , multispace0) ) ,
636+ float32_literal,
637+ ) ( input) ?;
638+
639+ let ( input, _) = multispace0 ( input) ?;
640+ let ( input, _) = char ( ']' ) ( input) ?;
641+
642+ Ok ( ( input, ValueExpression :: VectorLiteral ( values) ) )
643+ }
644+
606645// Parse a property reference: variable.property
607646fn property_reference ( input : & str ) -> IResult < & str , PropertyRef > {
608647 let ( input, variable) = identifier ( input) ?;
@@ -1597,4 +1636,90 @@ mod tests {
15971636 _ => panic ! ( "Expected AND expression" ) ,
15981637 }
15991638 }
1639+
1640+ #[ test]
1641+ fn test_parse_vector_literal ( ) {
1642+ let result = parse_vector_literal ( "[0.1, 0.2, 0.3]" ) ;
1643+ assert ! ( result. is_ok( ) ) ;
1644+ let ( _, expr) = result. unwrap ( ) ;
1645+ match expr {
1646+ ValueExpression :: VectorLiteral ( vec) => {
1647+ assert_eq ! ( vec. len( ) , 3 ) ;
1648+ assert_eq ! ( vec[ 0 ] , 0.1 ) ;
1649+ assert_eq ! ( vec[ 1 ] , 0.2 ) ;
1650+ assert_eq ! ( vec[ 2 ] , 0.3 ) ;
1651+ }
1652+ _ => panic ! ( "Expected VectorLiteral" ) ,
1653+ }
1654+ }
1655+
1656+ #[ test]
1657+ fn test_parse_vector_literal_with_negative_values ( ) {
1658+ let result = parse_vector_literal ( "[-0.1, 0.2, -0.3]" ) ;
1659+ assert ! ( result. is_ok( ) ) ;
1660+ let ( _, expr) = result. unwrap ( ) ;
1661+ match expr {
1662+ ValueExpression :: VectorLiteral ( vec) => {
1663+ assert_eq ! ( vec. len( ) , 3 ) ;
1664+ assert_eq ! ( vec[ 0 ] , -0.1 ) ;
1665+ assert_eq ! ( vec[ 2 ] , -0.3 ) ;
1666+ }
1667+ _ => panic ! ( "Expected VectorLiteral" ) ,
1668+ }
1669+ }
1670+
1671+ #[ test]
1672+ fn test_parse_vector_literal_scientific_notation ( ) {
1673+ let result = parse_vector_literal ( "[1e-3, 2.5e2, -3e-1]" ) ;
1674+ assert ! ( result. is_ok( ) ) ;
1675+ let ( _, expr) = result. unwrap ( ) ;
1676+ match expr {
1677+ ValueExpression :: VectorLiteral ( vec) => {
1678+ assert_eq ! ( vec. len( ) , 3 ) ;
1679+ assert ! ( ( vec[ 0 ] - 0.001 ) . abs( ) < 1e-6 ) ;
1680+ assert ! ( ( vec[ 1 ] - 250.0 ) . abs( ) < 1e-6 ) ;
1681+ assert ! ( ( vec[ 2 ] - ( -0.3 ) ) . abs( ) < 1e-6 ) ;
1682+ }
1683+ _ => panic ! ( "Expected VectorLiteral" ) ,
1684+ }
1685+ }
1686+
1687+ #[ test]
1688+ fn test_vector_distance_with_literal ( ) {
1689+ let query =
1690+ "MATCH (p:Person) WHERE vector_distance(p.embedding, [0.1, 0.2], l2) < 0.5 RETURN p" ;
1691+ let result = parse_cypher_query ( query) ;
1692+ assert ! ( result. is_ok( ) ) ;
1693+
1694+ let ast = result. unwrap ( ) ;
1695+ let where_clause = ast. where_clause . expect ( "Expected WHERE clause" ) ;
1696+
1697+ match where_clause. expression {
1698+ BooleanExpression :: Comparison { left, operator, .. } => {
1699+ match left {
1700+ ValueExpression :: VectorDistance {
1701+ left,
1702+ right,
1703+ metric,
1704+ } => {
1705+ // Left should be property reference
1706+ assert ! ( matches!( * left, ValueExpression :: Property ( _) ) ) ;
1707+ // Right should be vector literal
1708+ match * right {
1709+ ValueExpression :: VectorLiteral ( vec) => {
1710+ assert_eq ! ( vec. len( ) , 2 ) ;
1711+ assert_eq ! ( vec[ 0 ] , 0.1 ) ;
1712+ assert_eq ! ( vec[ 1 ] , 0.2 ) ;
1713+ }
1714+ _ => panic ! ( "Expected VectorLiteral" ) ,
1715+ }
1716+ assert_eq ! ( metric, DistanceMetric :: L2 ) ;
1717+ }
1718+ _ => panic ! ( "Expected VectorDistance" ) ,
1719+ }
1720+ assert_eq ! ( operator, ComparisonOperator :: LessThan ) ;
1721+ }
1722+ _ => panic ! ( "Expected comparison" ) ,
1723+ }
1724+ }
16001725}
0 commit comments