branch: externals/parser-generator commit c0310bf426180199844413b67ec9c6624b59b1f1 Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Added error-handling to lexical analyser --- parser-generator-lex-analyzer.el | 89 +++++++++++++++++++----------- test/parser-generator-lex-analyzer-test.el | 27 ++++++++- 2 files changed, 82 insertions(+), 34 deletions(-) diff --git a/parser-generator-lex-analyzer.el b/parser-generator-lex-analyzer.el index b9f30c3..6f0609f 100644 --- a/parser-generator-lex-analyzer.el +++ b/parser-generator-lex-analyzer.el @@ -15,11 +15,11 @@ (defvar parser-generator-lex-analyzer--get-function nil - "Get token information function.") + "Get token information function. This function will be called when building token meta-information before calling optional syntax-directed translation / semantic-actions. Anything other than nil is expected.") (defvar parser-generator-lex-analyzer--function nil - "Function used as lex-analyzer.") + "Function used as lex-analyzer. This function will be called and as result a list with structure '(a b . c) is expected where a is a string or symbol, if no more tokens can be found nil is expected, if it's not possible to proceed lex analysis an error-signal is expected.") (defvar parser-generator-lex-analyzer--index nil @@ -33,14 +33,24 @@ ;; Functions -;; TODO Catch errors (defun parser-generator-lex-analyzer--get-function (token) "Get information about TOKEN." (unless parser-generator-lex-analyzer--get-function (error "Missing lex-analyzer get function!")) - (funcall parser-generator-lex-analyzer--get-function token)) + (let ((meta-information)) + (condition-case error + (progn + (setq meta-information (funcall + parser-generator-lex-analyzer--get-function + token))) + (error (error + "Lex-analyze failed to get token meta-data of %s, error: %s" + token + (car (cdr error))))) + (unless meta-information + (error "Could not find any token meta-information for: %s" token)) + meta-information)) -;; TODO Catch errors (defun parser-generator-lex-analyzer--peek-next-look-ahead () "Peek next look-ahead number of tokens via lex-analyzer." (unless parser-generator-lex-analyzer--index @@ -52,41 +62,56 @@ (let ((look-ahead) (look-ahead-length 0) (index parser-generator-lex-analyzer--index)) - (while (< look-ahead-length parser-generator--look-ahead-number) - (let ((next-look-ahead - (funcall - parser-generator-lex-analyzer--function - index))) - (if next-look-ahead - (progn - (unless (listp (car next-look-ahead)) - (setq next-look-ahead (list next-look-ahead))) - (dolist (next-look-ahead-item next-look-ahead) - (when (< look-ahead-length parser-generator--look-ahead-number) - (push next-look-ahead-item look-ahead) - (setq look-ahead-length (1+ look-ahead-length)) - (setq index (cdr (cdr next-look-ahead-item)))))) - (push (list parser-generator--e-identifier) look-ahead) - (setq look-ahead-length (1+ look-ahead-length)) - (setq index (1+ index))))) + (while (< + look-ahead-length + parser-generator--look-ahead-number) + (condition-case error + (progn + (let ((next-look-ahead + (funcall + parser-generator-lex-analyzer--function + index))) + (if next-look-ahead + (progn + (unless (listp (car next-look-ahead)) + (setq next-look-ahead (list next-look-ahead))) + (dolist (next-look-ahead-item next-look-ahead) + (when (< + look-ahead-length + parser-generator--look-ahead-number) + (push next-look-ahead-item look-ahead) + (setq look-ahead-length (1+ look-ahead-length)) + (setq index (cdr (cdr next-look-ahead-item)))))) + (push (list parser-generator--e-identifier) look-ahead) + (setq look-ahead-length (1+ look-ahead-length)) + (setq index (1+ index))))) + (error (error + "Lex-analyze failed to peek next look-ahead at %s, error: %s" + index + (car (cdr error)))))) (nreverse look-ahead))) -;; TODO Catch errors (defun parser-generator-lex-analyzer--pop-token () "Pop next token via lex-analyzer." (unless parser-generator-lex-analyzer--index (error "Missing lex-analyzer index!")) (unless parser-generator-lex-analyzer--function (error "Missing lex-analyzer function!")) - (let ((token (funcall - parser-generator-lex-analyzer--function - parser-generator-lex-analyzer--index))) - (unless (listp (car token)) - (setq token (list token))) - (let ((first-token (car token))) - (setq parser-generator-lex-analyzer--index - (cdr (cdr first-token))) - first-token))) + (condition-case error + (progn + (let ((token (funcall + parser-generator-lex-analyzer--function + parser-generator-lex-analyzer--index))) + (unless (listp (car token)) + (setq token (list token))) + (let ((first-token (car token))) + (setq parser-generator-lex-analyzer--index + (cdr (cdr first-token))) + first-token))) + (error (error + "Lex-analyze failed to pop token at %s, error: %s" + parser-generator-lex-analyzer--index + (car (cdr error)))))) (defun parser-generator-lex-analyzer--reset () "Reset lex-analyzer." diff --git a/test/parser-generator-lex-analyzer-test.el b/test/parser-generator-lex-analyzer-test.el index 7666a57..e3fcc9c 100644 --- a/test/parser-generator-lex-analyzer-test.el +++ b/test/parser-generator-lex-analyzer-test.el @@ -26,11 +26,13 @@ (let* ((string '(("a" 1 . 2) ("b" 2 . 3) ("c" 3 . 4) ("d" 4 . 5))) (string-length (length string)) (max-index index) - (tokens)) + (tokens) + (next-token)) (while (and (< (1- index) string-length) (< (1- index) max-index)) - (push (nth (1- index) string) tokens) + (setq next-token (nth (1- index) string)) + (push next-token tokens) (setq index (1+ index))) (nreverse tokens)))) (should-error @@ -59,6 +61,27 @@ '(("a" 1 . 2) ("b" 2 . 3) ("c" 3 . 4) ("d" 4 . 5) (e) (e) (e) (e) (e) (e)) (parser-generator-lex-analyzer--peek-next-look-ahead))) + (setq + parser-generator-lex-analyzer--function + (lambda (index) + (let* ((string '(("a" 1 . 2) ("b" 2 . 3) ("c" 3 . 4) ("d" 4 . 5))) + (string-length (length string)) + (max-index index) + (tokens) + (next-token)) + (while (and + (< (1- index) string-length) + (< (1- index) max-index)) + (setq next-token (nth (1- index) string)) + (when (string= (car next-token) "d") + (error "Invalid token: %s" next-token)) + (push next-token tokens) + (setq index (1+ index))) + (nreverse tokens)))) + + (should-error + (parser-generator-lex-analyzer--peek-next-look-ahead)) + (message "Ended tests for (parser-generator-lex-analyzer--peek-next-look-ahead)")) (defun parser-generator-lex-analyzer-test--pop-token ()