Browse Source

xpath.pp: Fixed lexical analysis in ParseStep(), now conformant with paragraph 3.7 of the specs:
* Identifier is treated as AxisName only if it is followed by '::'
* Identifier is treated as NodeType only if it is followed by '('.

git-svn-id: trunk@13123 -

sergei 16 years ago
parent
commit
4cabfad02a
1 changed files with 42 additions and 51 deletions
  1. 42 51
      packages/fcl-xml/src/xpath.pp

+ 42 - 51
packages/fcl-xml/src/xpath.pp

@@ -41,8 +41,8 @@ resourcestring
   { Parser errors }
   { Parser errors }
   SParserExpectedLeftBracket = 'Expected "("';
   SParserExpectedLeftBracket = 'Expected "("';
   SParserExpectedRightBracket = 'Expected ")"';
   SParserExpectedRightBracket = 'Expected ")"';
-  SParserExpectedColonColon = 'Expected "::" after axis specifier';
-  SParserExpectedBrackets = 'Expected "()" after NodeType test';
+  SParserBadAxisName = 'Invalid axis name';
+  SParserBadNodeType = 'Invalid node type';
   SParserExpectedRightSquareBracket = 'Expected "]" after predicate';
   SParserExpectedRightSquareBracket = 'Expected "]" after predicate';
   SParserInvalidPrimExpr = 'Invalid primary expression';
   SParserInvalidPrimExpr = 'Invalid primary expression';
   SParserGarbageAfterExpression = 'Unrecognized input after expression';
   SParserGarbageAfterExpression = 'Unrecognized input after expression';
@@ -351,7 +351,7 @@ type
     FTokenStart: DOMPChar;
     FTokenStart: DOMPChar;
     FTokenLength: Integer;
     FTokenLength: Integer;
     procedure Error(const Msg: String);
     procedure Error(const Msg: String);
-    procedure ParseStep(var Dest: TStep);                // [4]
+    procedure ParseStep(Dest: TStep);          // [4]
     function ParsePrimaryExpr: TXPathExprNode; // [15]
     function ParsePrimaryExpr: TXPathExprNode; // [15]
     function ParseUnionExpr: TXPathExprNode;   // [18]
     function ParseUnionExpr: TXPathExprNode;   // [18]
     function ParsePathExpr: TXPathExprNode;    // [19]
     function ParsePathExpr: TXPathExprNode;    // [19]
@@ -1707,15 +1707,13 @@ begin
   raise Exception.Create(Msg) at get_caller_addr(get_frame);
   raise Exception.Create(Msg) at get_caller_addr(get_frame);
 end;
 end;
 
 
-procedure TXPathScanner.ParseStep(var Dest: TStep);  // [4]
-var
-  NeedColonColon: Boolean;
+procedure TXPathScanner.ParseStep(Dest: TStep);  // [4]
 
 
   procedure NeedBrackets;
   procedure NeedBrackets;
   begin
   begin
-    if (NextToken <> tkLeftBracket) or
-       (NextToken <> tkRightBracket) then
-       Error(SParserExpectedBrackets);
+    NextToken;
+    if NextToken <> tkRightBracket then
+       Error(SParserExpectedRightBracket);
     NextToken;
     NextToken;
   end;
   end;
 
 
@@ -1739,12 +1737,9 @@ begin
       Dest.Axis := axisAttribute;
       Dest.Axis := axisAttribute;
       NextToken;
       NextToken;
     end
     end
-    else if CurToken = tkIdentifier then       // [5] AxisName '::'
+    else if (CurToken = tkIdentifier) and (PeekToken = tkColonColon) then  // [5] AxisName '::'
     begin
     begin
-      { TODO: should first check whether identifier is followed by '::',
-        if not, it should be treated as NodeTest, not AxisName }
       // Check for [6] AxisName
       // Check for [6] AxisName
-      NeedColonColon := True;
       if CurTokenString = 'ancestor' then
       if CurTokenString = 'ancestor' then
         Dest.Axis := axisAncestor
         Dest.Axis := axisAncestor
       else if CurTokenString = 'ancestor-or-self' then
       else if CurTokenString = 'ancestor-or-self' then
@@ -1772,16 +1767,10 @@ begin
       else if CurTokenString = 'self' then
       else if CurTokenString = 'self' then
         Dest.Axis := axisSelf
         Dest.Axis := axisSelf
       else
       else
-      begin
-        NeedColonColon := False;
-        Dest.Axis := axisChild;
-      end;
-      if NeedColonColon then
-      begin
-        if NextToken <> tkColonColon then
-          Error(SParserExpectedColonColon);
-        NextToken;
-      end;
+        Error(SParserBadAxisName);
+
+      NextToken;  // skip identifier and the '::'
+      NextToken;
     end
     end
     else if CurToken <> tkEndOfStream then
     else if CurToken <> tkEndOfStream then
       Dest.Axis := axisChild;
       Dest.Axis := axisChild;
@@ -1794,38 +1783,40 @@ begin
     end
     end
     else if CurToken = tkIdentifier then
     else if CurToken = tkIdentifier then
     begin
     begin
-      { TODO: should first check whether identifier is followed by '(',
-       if not, it is a NodeTest, not NodeType }
       // Check for case [38] NodeType
       // Check for case [38] NodeType
-      if CurTokenString = 'comment' then
-      begin
-        NeedBrackets;
-        Dest.NodeTestType := ntCommentNode;
-      end
-      else if CurTokenString = 'text' then
+      if PeekToken = tkLeftBracket then
       begin
       begin
-        NeedBrackets;
-        Dest.NodeTestType := ntTextNode;
-      end
-      else if CurTokenString = 'processing-instruction' then
-      begin
-        if NextToken <> tkLeftBracket then
-          Error(SParserExpectedLeftBracket);
-        if NextToken = tkString then
+        if CurTokenString = 'comment' then
+        begin
+          NeedBrackets;
+          Dest.NodeTestType := ntCommentNode;
+        end
+        else if CurTokenString = 'text' then
         begin
         begin
-          // TODO: Handle processing-instruction('name') constructs
-          Dest.NodeTestString := CurTokenString;
+          NeedBrackets;
+          Dest.NodeTestType := ntTextNode;
+        end
+        else if CurTokenString = 'processing-instruction' then
+        begin
+          NextToken;   { skip '('; we know it's there }
+          if NextToken = tkString then
+          begin
+            // TODO: Handle processing-instruction('name') constructs
+            Dest.NodeTestString := CurTokenString;
+            NextToken;
+          end;
+          if CurToken <> tkRightBracket then
+            Error(SParserExpectedRightBracket);
           NextToken;
           NextToken;
-        end;
-        if CurToken <> tkRightBracket then
-          Error(SParserExpectedRightBracket);
-        NextToken;
-        Dest.NodeTestType := ntPINode;
-      end
-      else if CurTokenString = 'node' then
-      begin
-        NeedBrackets;
-        Dest.NodeTestType := ntAnyNode;
+          Dest.NodeTestType := ntPINode;
+        end
+        else if CurTokenString = 'node' then
+        begin
+          NeedBrackets;
+          Dest.NodeTestType := ntAnyNode;
+        end
+        else
+          Error(SParserBadNodeType);
       end
       end
       else  // [37] NameTest, second or third case
       else  // [37] NameTest, second or third case
       begin
       begin