Function: define-lex-block-type-analyzer
define-lex-block-type-analyzer is a macro defined in lex.el.gz.
Signature
(define-lex-block-type-analyzer NAME DOC SYNTAX MATCHES)
Documentation
Define a block type analyzer NAME with DOC string.
SYNTAX is the regexp that matches block delimiters, typically the
open (\\s() and close (\\s)) parenthesis syntax classes.
MATCHES is a pair (OPEN-SPECS . CLOSE-SPECS) that defines blocks.
OPEN-SPECS is a list of (OPEN-DELIM OPEN-TOKEN BLOCK-TOKEN) elements
where:
OPEN-DELIM is a string: the block open delimiter character.
OPEN-TOKEN is the lexical token class associated to the OPEN-DELIM
delimiter.
BLOCK-TOKEN is the lexical token class associated to the block
that starts at the OPEN-DELIM delimiter.
CLOSE-SPECS is a list of (CLOSE-DELIM CLOSE-TOKEN) elements where:
CLOSE-DELIM is a string: the block end delimiter character.
CLOSE-TOKEN is the lexical token class associated to the
CLOSE-DELIM delimiter.
Each element in OPEN-SPECS must have a corresponding element in CLOSE-SPECS.
The lexer will return a BLOCK-TOKEN token when the value of
semantic-lex-current-depth is greater than or equal to the maximum
depth of parenthesis tracking (see also the function semantic-lex).
Otherwise it will return OPEN-TOKEN and CLOSE-TOKEN tokens.
TO DO: Put the following in the developer's guide and just put a reference here.
In the grammar:
The value of a block token must be a string that contains a readable sexp of the form:
"(OPEN-TOKEN CLOSE-TOKEN)"
OPEN-TOKEN and CLOSE-TOKEN represent the block delimiters, and must be
lexical tokens of respectively open-paren and close-paren types.
Their value is the corresponding delimiter character as a string.
Here is a small example to analyze a parenthesis block:
%token <block> PAREN_BLOCK "(LPAREN RPAREN)"
%token <open-paren> LPAREN "("
%token <close-paren> RPAREN ")"
When the lexer encounters the open-paren delimiter "(":
- If the maximum depth of parenthesis tracking is not reached (that
is, current depth < max depth), it returns a (LPAREN start . end)
token, then continue analysis inside the block. Later, when the
corresponding close-paren delimiter ")" will be encountered, it
will return a (RPAREN start . end) token.
- If the maximum depth of parenthesis tracking is reached (current
depth >= max depth), it returns the whole parenthesis block as
a (PAREN_BLOCK start . end) token.
Source Code
;; Defined in /usr/src/emacs/lisp/cedet/semantic/lex.el.gz
(defmacro define-lex-block-type-analyzer (name doc syntax matches)
"Define a block type analyzer NAME with DOC string.
SYNTAX is the regexp that matches block delimiters, typically the
open (`\\\\s(') and close (`\\\\s)') parenthesis syntax classes.
MATCHES is a pair (OPEN-SPECS . CLOSE-SPECS) that defines blocks.
OPEN-SPECS is a list of (OPEN-DELIM OPEN-TOKEN BLOCK-TOKEN) elements
where:
OPEN-DELIM is a string: the block open delimiter character.
OPEN-TOKEN is the lexical token class associated to the OPEN-DELIM
delimiter.
BLOCK-TOKEN is the lexical token class associated to the block
that starts at the OPEN-DELIM delimiter.
CLOSE-SPECS is a list of (CLOSE-DELIM CLOSE-TOKEN) elements where:
CLOSE-DELIM is a string: the block end delimiter character.
CLOSE-TOKEN is the lexical token class associated to the
CLOSE-DELIM delimiter.
Each element in OPEN-SPECS must have a corresponding element in
CLOSE-SPECS.
The lexer will return a BLOCK-TOKEN token when the value of
`semantic-lex-current-depth' is greater than or equal to the maximum
depth of parenthesis tracking (see also the function `semantic-lex').
Otherwise it will return OPEN-TOKEN and CLOSE-TOKEN tokens.
TO DO: Put the following in the developer's guide and just put a
reference here.
In the grammar:
The value of a block token must be a string that contains a readable
sexp of the form:
\"(OPEN-TOKEN CLOSE-TOKEN)\"
OPEN-TOKEN and CLOSE-TOKEN represent the block delimiters, and must be
lexical tokens of respectively `open-paren' and `close-paren' types.
Their value is the corresponding delimiter character as a string.
Here is a small example to analyze a parenthesis block:
%token <block> PAREN_BLOCK \"(LPAREN RPAREN)\"
%token <open-paren> LPAREN \"(\"
%token <close-paren> RPAREN \")\"
When the lexer encounters the open-paren delimiter \"(\":
- If the maximum depth of parenthesis tracking is not reached (that
is, current depth < max depth), it returns a (LPAREN start . end)
token, then continue analysis inside the block. Later, when the
corresponding close-paren delimiter \")\" will be encountered, it
will return a (RPAREN start . end) token.
- If the maximum depth of parenthesis tracking is reached (current
depth >= max depth), it returns the whole parenthesis block as
a (PAREN_BLOCK start . end) token."
(declare (indent 1))
(let* ((val (make-symbol "val"))
(lst (make-symbol "lst"))
(elt (make-symbol "elt")))
`(define-lex-analyzer ,name
,doc
(and
(looking-at ,syntax) ;; "\\(\\s(\\|\\s)\\)"
(let ((,val (match-string 0))
(,lst ,matches)
,elt)
(cond
((setq ,elt (assoc ,val (car ,lst)))
(if (or (not semantic-lex-maximum-depth)
(< semantic-lex-current-depth semantic-lex-maximum-depth))
(progn
(setq semantic-lex-current-depth (1+ semantic-lex-current-depth))
(semantic-lex-push-token
(semantic-lex-token
(nth 1 ,elt)
(match-beginning 0) (match-end 0))))
(semantic-lex-push-token
(semantic-lex-token
(nth 2 ,elt)
(match-beginning 0)
(save-excursion
(semantic-lex-unterminated-syntax-protection (nth 2 ,elt)
(forward-list 1)
(point)))))))
((setq ,elt (assoc ,val (cdr ,lst)))
(setq semantic-lex-current-depth (1- semantic-lex-current-depth))
(semantic-lex-push-token
(semantic-lex-token
(nth 1 ,elt)
(match-beginning 0) (match-end 0))))
))))
))