r2108 + introduce $any_op autotag
[racktables] / inc / code.php
index 2bc5b8e46d41741c5f259f26e1cd9613fa8142f0..867bc66eb23f4dcb8f5a30bfd0631dfa839682bb 100644 (file)
  */
 
 // Complain about martian char.
  */
 
 // Complain about martian char.
-function abortLex1 ($state, $text, $pos)
+function lexError1 ($state, $text, $pos)
 {
 {
-       $message = "invalid char with code " . ord (mb_substr ($text, $pos, 1));
-       $message .= " at position ${pos} (FSM state is '${state}')";
+       $message = "invalid char with code " . ord (mb_substr ($text, $pos, 1)) . ' (';
+       $message .= mb_substr ($text, $pos, 1) . ") at position ${pos} (FSM state is '${state}')";
        return array ('result' => 'NAK', 'load' => $message);
 }
 
 // Complain about martian keyword.
        return array ('result' => 'NAK', 'load' => $message);
 }
 
 // Complain about martian keyword.
-function abortLex2 ($word)
+function lexError2 ($word)
 {
        return array
        (
 {
        return array
        (
@@ -36,7 +36,7 @@ function abortLex2 ($word)
 }
 
 // Complain about wrong FSM state.
 }
 
 // Complain about wrong FSM state.
-function abortLex3 ($state)
+function lexError3 ($state)
 {
        return array
        (
 {
        return array
        (
@@ -45,6 +45,15 @@ function abortLex3 ($state)
        );
 }
 
        );
 }
 
+function lexError4 ($s)
+{
+       return array
+       (
+               'result' => 'NAK',
+               'load' => "Invalid tag or predicate name '${s}'"
+       );
+}
+
 // Produce a list of lexems from the given text. Possible lexems are:
 function getLexemsFromRackCode ($text)
 {
 // Produce a list of lexems from the given text. Possible lexems are:
 function getLexemsFromRackCode ($text)
 {
@@ -81,7 +90,7 @@ function getLexemsFromRackCode ($text)
                                                $newstate = 'reading predicate 1';
                                                break;
                                        default:
                                                $newstate = 'reading predicate 1';
                                                break;
                                        default:
-                                               return abortLex1 ($state, $text, $i);
+                                               return lexError1 ($state, $text, $i);
                                }
                                break;
                        case 'reading keyword':
                                }
                                break;
                        case 'reading keyword':
@@ -113,12 +122,12 @@ function getLexemsFromRackCode ($text)
                                                                $ret[] = array ('type' => 'LEX_BOOLCONST', 'load' => $buffer);
                                                                break;
                                                        default:
                                                                $ret[] = array ('type' => 'LEX_BOOLCONST', 'load' => $buffer);
                                                                break;
                                                        default:
-                                                               return abortLex2 ($buffer);
+                                                               return lexError2 ($buffer);
                                                }
                                                $newstate = 'ESOTSM';
                                                break;
                                        default:
                                                }
                                                $newstate = 'ESOTSM';
                                                break;
                                        default:
-                                               return abortLex1 ($state, $text, $i);
+                                               return lexError1 ($state, $text, $i);
                                }
                                break;
                        case 'reading tag 1':
                                }
                                break;
                        case 'reading tag 1':
@@ -127,12 +136,12 @@ function getLexemsFromRackCode ($text)
                                        case (preg_match ('/^[ \t\n\r]$/', $char)):
                                                // nom-nom...
                                                break;
                                        case (preg_match ('/^[ \t\n\r]$/', $char)):
                                                // nom-nom...
                                                break;
-                                       case (mb_ereg ('[[:alpha:]\$]', $char) > 0):
+                                       case (mb_ereg ('[[:alnum:]\$]', $char) > 0):
                                                $buffer = $char;
                                                $newstate = 'reading tag 2';
                                                break;
                                        default:
                                                $buffer = $char;
                                                $newstate = 'reading tag 2';
                                                break;
                                        default:
-                                               return abortLex1 ($state, $text, $i);
+                                               return lexError1 ($state, $text, $i);
                                }
                                break;
                        case 'reading tag 2':
                                }
                                break;
                        case 'reading tag 2':
@@ -140,16 +149,16 @@ function getLexemsFromRackCode ($text)
                                {
                                        case ($char == '}'):
                                                $buffer = rtrim ($buffer);
                                {
                                        case ($char == '}'):
                                                $buffer = rtrim ($buffer);
-                                               if (mb_ereg ('[[:alnum:]]', mb_substr ($buffer, -1)) == 0)
-                                                       return abortLex1 ($state, $text, $i);
+                                               if (!validTagName ($buffer, TRUE))
+                                                       return lexError4 ($buffer);
                                                $ret[] = array ('type' => 'LEX_TAG', 'load' => $buffer);
                                                $newstate = 'ESOTSM';
                                                break;
                                                $ret[] = array ('type' => 'LEX_TAG', 'load' => $buffer);
                                                $newstate = 'ESOTSM';
                                                break;
-                                       case (mb_ereg ('[[:alnum:] _-]', $char) > 0):
+                                       case (mb_ereg ('[[:alnum:]\. _~-]', $char) > 0):
                                                $buffer .= $char;
                                                break;
                                        default:
                                                $buffer .= $char;
                                                break;
                                        default:
-                                               return abortLex1 ($state, $text, $i);
+                                               return lexError1 ($state, $text, $i);
                                }
                                break;
                        case 'reading predicate 1':
                                }
                                break;
                        case 'reading predicate 1':
@@ -158,12 +167,12 @@ function getLexemsFromRackCode ($text)
                                        case (preg_match ('/^[ \t\n\r]$/', $char)):
                                                // nom-nom...
                                                break;
                                        case (preg_match ('/^[ \t\n\r]$/', $char)):
                                                // nom-nom...
                                                break;
-                                       case (mb_ereg ('[[:alpha:]]', $char) > 0):
+                                       case (mb_ereg ('[[:alnum:]]', $char) > 0):
                                                $buffer = $char;
                                                $newstate = 'reading predicate 2';
                                                break;
                                        default:
                                                $buffer = $char;
                                                $newstate = 'reading predicate 2';
                                                break;
                                        default:
-                                               return abortLex1 ($state, $text, $i);
+                                               return lexError1 ($state, $text, $i);
                                }
                                break;
                        case 'reading predicate 2':
                                }
                                break;
                        case 'reading predicate 2':
@@ -171,16 +180,16 @@ function getLexemsFromRackCode ($text)
                                {
                                        case ($char == ']'):
                                                $buffer = rtrim ($buffer);
                                {
                                        case ($char == ']'):
                                                $buffer = rtrim ($buffer);
-                                               if (mb_ereg ('[[:alnum:]]', mb_substr ($buffer, -1)) == 0)
-                                                       return abortLex1 ($state, $text, $i);
+                                               if (!validTagName ($buffer))
+                                                       return lexError4 ($buffer);
                                                $ret[] = array ('type' => 'LEX_PREDICATE', 'load' => $buffer);
                                                $newstate = 'ESOTSM';
                                                break;
                                                $ret[] = array ('type' => 'LEX_PREDICATE', 'load' => $buffer);
                                                $newstate = 'ESOTSM';
                                                break;
-                                       case (mb_ereg ('[[:alnum:] _-]', $char) > 0):
+                                       case (mb_ereg ('[[:alnum:]\. _~-]', $char) > 0):
                                                $buffer .= $char;
                                                break;
                                        default:
                                                $buffer .= $char;
                                                break;
                                        default:
-                                               return abortLex1 ($state, $text, $i);
+                                               return lexError1 ($state, $text, $i);
                                }
                                break;
                        case 'skipping comment':
                                }
                                break;
                        case 'skipping comment':
@@ -198,7 +207,7 @@ function getLexemsFromRackCode ($text)
                $state = $newstate;
        endfor;
        if ($state != 'ESOTSM' and $state != 'skipping comment')
                $state = $newstate;
        endfor;
        if ($state != 'ESOTSM' and $state != 'skipping comment')
-               return abortLex3 ($state);
+               return lexError3 ($state);
        return array ('result' => 'ACK', 'load' => $ret);
 }
 
        return array ('result' => 'ACK', 'load' => $ret);
 }
 
@@ -572,23 +581,27 @@ function getRackCode ($text)
        return semanticFilter ($synt['load']);
 }
 
        return semanticFilter ($synt['load']);
 }
 
-// Return true, if the given expression can be evaluated against the given
-// predicate list.
-function valid_predrefs ($plist, $expr)
+// Return NULL, if the given expression can be evaluated against the given
+// predicate list. Return the name of the first show stopper otherwise.
+function firstUnrefPredicate ($plist, $expr)
 {
        switch ($expr['type'])
        {
                case 'LEX_BOOLCONST':
                case 'LEX_TAG':
 {
        switch ($expr['type'])
        {
                case 'LEX_BOOLCONST':
                case 'LEX_TAG':
-                       return TRUE;
+                       return NULL;
                case 'LEX_PREDICATE':
                case 'LEX_PREDICATE':
-                       return in_array ($expr['load'], $plist);
+                       return in_array ($expr['load'], $plist) ? NULL : $expr['load'];
                case 'SYNT_NOTEXPR':
                case 'SYNT_NOTEXPR':
-                       return valid_predrefs ($plist, $expr['load']);
+                       return firstUnrefPredicate ($plist, $expr['load']);
                case 'SYNT_BOOLOP':
                case 'SYNT_BOOLOP':
-                       return valid_predrefs ($plist, $expr['left']) and valid_predrefs ($plist, $expr['right']);
+                       if (($tmp = firstUnrefPredicate ($plist, $expr['left'])) !== NULL)
+                               return $tmp;
+                       if (($tmp = firstUnrefPredicate ($plist, $expr['right'])) !== NULL)
+                               return $tmp;
+                       return NULL;
                default:
                default:
-                       return FALSE;
+                       return NULL;
        }
 }
 
        }
 }
 
@@ -599,13 +612,23 @@ function semanticFilter ($code)
                switch ($sentence['type'])
                {
                        case 'SYNT_DEFINITION':
                switch ($sentence['type'])
                {
                        case 'SYNT_DEFINITION':
-                               if (!valid_predrefs ($predicatelist, $sentence['definition']))
-                                       return array ('result' => 'NAK', 'load' => 'cannot dereference definition sentence');
+                               $up = firstUnrefPredicate ($predicatelist, $sentence['definition']);
+                               if ($up !== NULL)
+                                       return array
+                                       (
+                                               'result' => 'NAK',
+                                               'load' => "definition [${sentence['term']}] uses unknown predicate [${up}]"
+                                       );
                                $predicatelist[] = $sentence['term'];
                                break;
                        case 'SYNT_GRANT':
                                $predicatelist[] = $sentence['term'];
                                break;
                        case 'SYNT_GRANT':
-                               if (!valid_predrefs ($predicatelist, $sentence['condition']))
-                                       return array ('result' => 'NAK', 'load' => 'cannot dereference grant sentence');
+                               $up = firstUnrefPredicate ($predicatelist, $sentence['condition']);
+                               if ($up !== NULL)
+                                       return array
+                                       (
+                                               'result' => 'NAK',
+                                               'load' => "grant sentence uses unknown predicate [${up}]"
+                                       );
                                break;
                        default:
                                return array ('result' => 'NAK', 'load' => 'unknown sentence type');
                                break;
                        default:
                                return array ('result' => 'NAK', 'load' => 'unknown sentence type');