Folks,
Has anyone gotten cl-yacc to report error location (line and column
range)?
I browsed the source code but couldn't find such functionality.
How would I go about implementing this myself? I'm spoiled by
ocamlyacc and Parsec (Haskell) that have this built-in.
Thanks, Joel
Joel Reymont <······@gmail.com> writes:
> Folks,
>
> Has anyone gotten cl-yacc to report error location (line and column
> range)?
>
> I browsed the source code but couldn't find such functionality.
I've done something like this in the past with cl-yacc, using a Gray
Streams class to keep track of the tokenizer's position in the stream.
A rudimentary Gray Streams class for this purpose is available in the
SBCL manual [1], and the relevant cl-yacc code went something like
this:
(define-condition yacc-parse-error-with-position (yacc-parse-error)
((stream-line-number :initarg :stream-line-number
:reader yacc-parse-error-with-position-line-number)
(stream-column-number :initarg :stream-column-number
:reader
yacc-parse-error-with-position-column-number))
(:report (lambda (e stream)
(format stream "~<Unexpected terminal ~S (value ~S)~
Expected one of: ~S~
Line number ~D~
Column number ···@:>"
(yacc-parse-error-terminal e)
(yacc-parse-error-value e)
(yacc-parse-error-expected-terminals e)
(yacc-parse-error-with-position-line-number e)
(yacc-parse-error-with-position-column-number e)))))
;; *STREAM* is your real input stream, *LEXER* is your lexer function,
;; *PARSER* is your parser.
(let ((counting-stream
(make-instance 'counting-character-input-stream
:stream *stream*)))
(handler-bind
((yacc-parse-error
#'(lambda (error)
(error 'yacc-parse-error-with-position
:terminal (yacc-parse-error-terminal error)
:value (yacc-parse-error-value error)
:expected-terminals (yacc-parse-error-expected-terminals
error)
:stream-line-number (line-count-of counting-stream)
:stream-column-number (col-count-of counting-stream)))))
(parse-with-lexer *lexer* *parser*)))
Hope that helps,
RmK
[1] http://www.sbcl.org/manual/Character-counting-input-stream.html#Character-counting-input-stream