First Parser

I’ve been trying to learn how to use the PLT Scheme parser-tools collection. As a learning exercise I’ve written a small parser and lexer.

The parser will read in a file with the format of the named.conf configuration files used by the Unix DNS daemon Bind. They look (in part) like this:

zone "web-wide.net" IN {
	type master;
	file "zone/web-wide.net";
	allow-update {
		127.0.0.1;
	};
};

And it will output it as an s-expression that looks like this:

((zone  |"web-wide.net"|  |IN|
 ((type master)
 (file |"zone/web-wide.net"|)
 (allow-update
  ((127.0.0.1))))))

Here is the code for the parser and lexer:

(require (lib "yacc.ss" "parser-tools")
         (lib "lex.ss" "parser-tools")
         (lib "readerr.ss" "syntax"))

(define-tokens value-tokens (STRING))
(define-empty-tokens stanza-tokens (OB CB SEMI EOF))

(define-lex-abbrevs
 (lower-letter (- "a" "z"))
 (upper-letter (- #A #Z))
 (digit (- "0" "9"))
 (string (+ (: lower-letter upper-letter digit "." "-" "_" )))
 (qstring (@ #\" (+ (^ #\")) #\"))
 )

(define confl
  (lexer
   ((eof) 'EOF)
   ((: #tab #space #newline) (confl input-port))
   ("{" 'OB)
   ("}" 'CB)
   (";" 'SEMI)
   (qstring (token-STRING (string->symbol lexeme)))
   (string (token-STRING (string->symbol lexeme)))))

(define confp
  (parser
   (start start)
   (end EOF)
   (tokens value-tokens stanza-tokens)
   (error (lambda (a b c) (void)))

   (grammar

    (start ((statement_list) $1))
    (block
     ((OB statement_list CB)  (list $2)))
    (element
     ((string) (list $1) )
     ((block) $1))
    (element_list
     ((element) $1)
     ((element_list element) (append $1 $2)))
    (statement
     ((element_list SEMI) (list $1)))
    (statement_list
     ((statement) $1)
     ((statement_list statement) (append $1 $2))))))

(define runp
  (lambda () (confp (lambda () (confl (current-input-port))))))
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s