Function: wisent-parse

wisent-parse is a byte-compiled function defined in wisent.el.gz.

Signature

(wisent-parse AUTOMATON LEXER &optional ERROR START)

Documentation

Parse input using the automaton specified in AUTOMATON.

- AUTOMATON is an LALR(1) automaton generated by
  wisent-compile-grammar.

- LEXER is a function with no argument called by the parser to obtain
  the next terminal (token) in input.

- ERROR is an optional reporting function called when a parse error
  occurs. It receives a message string to report. It defaults to the
  function wisent-message.

- START specify the start symbol (nonterminal) used by the parser as
  its goal. It defaults to the start symbol defined in the grammar
  (see also wisent-compile-grammar).

Source Code

;; Defined in /usr/src/emacs/lisp/cedet/semantic/wisent/wisent.el.gz
(defun wisent-parse (automaton lexer &optional error start)
  "Parse input using the automaton specified in AUTOMATON.

- AUTOMATON is an LALR(1) automaton generated by
  `wisent-compile-grammar'.

- LEXER is a function with no argument called by the parser to obtain
  the next terminal (token) in input.

- ERROR is an optional reporting function called when a parse error
  occurs.  It receives a message string to report.  It defaults to the
  function `wisent-message'.

- START specify the start symbol (nonterminal) used by the parser as
  its goal.  It defaults to the start symbol defined in the grammar
  (see also `wisent-compile-grammar')."
  (run-hooks 'wisent-pre-parse-hook)
  (let* ((actions (aref automaton 0))
         (gotos   (aref automaton 1))
         (starts  (aref automaton 2))
         (stack (make-vector wisent-parse-max-stack-size nil))
         (sp 0)
         (wisent-loop t)
         (wisent-parse-error-function (or error 'wisent-message))
         (wisent-parse-lexer-function lexer)
         (wisent-recovering nil)
         (wisent-input (wisent-parse-start start starts))
         state tokid choices choice)
    (setq wisent-nerrs     0 ;; Reset parse error counter
          wisent-lookahead nil) ;; and lookahead token
    (aset stack 0 0) ;; Initial state
    (while wisent-loop
      (setq state (aref stack sp)
            tokid (car wisent-input)
            wisent-loop (wisent-parse-action tokid (aref actions state)))
      (cond

       ;; Input successfully parsed
       ;; -------------------------
       ((eq wisent-loop wisent-accept-tag)
        (setq wisent-loop nil))

       ;; Syntax error in input
       ;; ---------------------
       ((eq wisent-loop wisent-error-tag)
        ;; Report this error if not already recovering from an error.
        (setq choices (aref actions state))
        (or wisent-recovering
            (wisent-error
             (format "Syntax error, unexpected %s, expecting %s"
                     (wisent-token-to-string wisent-input)
                     (mapconcat #'wisent-item-to-string
                                (delq wisent-error-term
                                      (mapcar #'car (cdr choices)))
                                ", "))))
        ;; Increment the error counter
        (setq wisent-nerrs (1+ wisent-nerrs))
        ;; If just tried and failed to reuse lookahead token after an
        ;; error, discard it.
        (if (eq wisent-recovering wisent-parse-max-recover)
            (if (eq tokid wisent-eoi-term)
                (wisent-abort) ;; Terminate if at end of input.
              (wisent-message "Error recovery: skip %s"
                              (wisent-token-to-string wisent-input))
              (run-hook-with-args
               'wisent-discarding-token-functions wisent-input)
              (setq wisent-input (wisent-lexer)))

          ;; Else will try to reuse lookahead token after shifting the
          ;; error token.

          ;; Each real token shifted decrements this.
          (setq wisent-recovering wisent-parse-max-recover)
          ;; Pop the value/state stack to see if an action associated
          ;; to special terminal symbol 'error exists.
          (while (and (>= sp 0)
                      (not (and (setq state   (aref stack sp)
                                      choices (aref actions state)
                                      choice  (assq wisent-error-term choices))
                                (natnump (cdr choice)))))
            (setq sp (- sp 2)))

          (if (not choice)
              ;; No 'error terminal was found.  Just terminate.
              (wisent-abort)
            ;; Try to recover and continue parsing.
            ;; Shift the error terminal.
            (setq state (cdr choice)    ; new state
                  sp    (+ sp 2))
            (aset stack (1- sp) nil)    ; push value
            (aset stack sp state)       ; push new state
            ;; Adjust input to error recovery state.  Unless 'error
            ;; triggers a reduction, eat the input stream until an
            ;; expected terminal symbol is found, or EOI is reached.
            (if (cdr (setq choices (aref actions state)))
                (while (not (or (eq (car wisent-input) wisent-eoi-term)
                                (assq (car wisent-input) choices)))
                  (wisent-message "Error recovery: skip %s"
                                  (wisent-token-to-string wisent-input))
                  (run-hook-with-args
                   'wisent-discarding-token-functions wisent-input)
                  (setq wisent-input (wisent-lexer)))))))

       ;; Shift current token on top of the stack
       ;; ---------------------------------------
       ((natnump wisent-loop)
        ;; Count tokens shifted since error; after
        ;; `wisent-parse-max-recover', turn off error status.
        (setq wisent-recovering (and (natnump wisent-recovering)
                                     (> wisent-recovering 1)
                                     (1- wisent-recovering)))
        (setq sp (+ sp 2))
        (aset stack (1- sp) (cdr wisent-input))
        (aset stack sp wisent-loop)
        (setq wisent-input (wisent-lexer)))

       ;; Reduce by rule (call semantic action)
       ;; -------------------------------------
       (t
        (setq sp (funcall wisent-loop stack sp gotos))
        (or wisent-input (setq wisent-input (wisent-lexer))))))
    (run-hooks 'wisent-post-parse-hook)
    (car (aref stack 1))))