#lang racket/base
(require parser-tools/lex
(prefix-in : parser-tools/lex-sre)
2htdp/image
"../lexer.rkt"
)
(provide get-syntax-token)
(define (syn-val lex a b c d)
(values lex a b (position-offset c) (position-offset d)))
(define (colorize-string my-start-pos)
(define lxr
(lexer
[(:~ #\" #\\) (lxr input-port)]
[(:: #\\ #\\) (lxr input-port)]
[(:: #\\ #\newline) (lxr input-port)]
[(:: #\\ #\") (lxr input-port)]
[(eof) (syn-val "" 'error #f my-start-pos end-pos)]
[#\" (syn-val "" 'string #f my-start-pos end-pos)]))
lxr)
(define (suck-up-comment ip)
(define (helper str l)
(define current-position (file-position ip))
(let ((next (read-char-or-special ip)))
(if (eof-object? next)
(values str l)
(if (char? next)
(if (equal? #\newline next)
(values (string-append str "\n") (add1 l))
(helper (string-append str (string next)) (add1 l)))
(helper str (+ l (- (file-position ip) current-position)))))))
(helper "" 0))
(define (lex-string ip target-char start-pos)
(define (helper str current-pos skip?)
(let ((next (read-char-or-special ip)))
(if (eof-object? next)
(syn-val str 'string #f start-pos current-pos)
(if (not (char? next))
(syn-val str 'error #f start-pos current-pos)
(let-values (((next-line next-col next-off)
(port-next-location ip)))
(let ((next-pos (make-position next-off next-line next-col)))
(if (equal? next #\\)
(helper (string-append str (string #\\)) next-pos (not skip?))
(if (and (equal? next target-char)
(not skip?))
(syn-val (string-append str (string next)) 'string #f start-pos next-pos)
(helper (string-append str (string next)) next-pos #f)))))))))
(let-values (((next-line next-col next-off)
(port-next-location ip)))
(let ((next-pos (make-position next-off next-line next-col)))
(helper (string target-char) next-pos #f))))
(define get-syntax-token
(lexer
[(:+ whitespace)
(syn-val lexeme 'whitespace #f start-pos end-pos)]
[#\#
(let-values ([(rest-of-line len) (suck-up-comment input-port)])
(syn-val (string-append lexeme rest-of-line)
'comment
#f
start-pos
(make-position (+ (position-offset start-pos) (add1 len))
(position-line start-pos)
(+ (position-col start-pos) (add1 len)))))]
["empty"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["True"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["False"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["def"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["and"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["or"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["not"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["if"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["elif"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["else"
(syn-val lexeme 'keyword #f start-pos end-pos)]
[":done"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["struct"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["len"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["in"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["fun"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["test"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["is"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["within"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["test_error"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["test_range"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["from"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["to"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["big_bang"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["init"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["on_tick"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["tick_rate"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["tick_limit"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["to_draw"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["draw_width"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["draw_height"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["on_key"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["on_pad"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["on_release"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["on_mouse"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["stop_when"
(syn-val lexeme 'keyword #f start-pos end-pos)]
["last_scene"
(syn-val lexeme 'keyword #f start-pos end-pos)]
[".."
(syn-val lexeme 'keyword #f start-pos end-pos)]
["..."
(syn-val lexeme 'keyword #f start-pos end-pos)]
["...."
(syn-val lexeme 'keyword #f start-pos end-pos)]
["....."
(syn-val lexeme 'keyword #f start-pos end-pos)]
["......"
(syn-val lexeme 'keyword #f start-pos end-pos)]
[(:: "......" (:+ #\.))
(syn-val lexeme 'error #f start-pos end-pos)]
[#\:
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\;
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\,
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[(:or #\( #\) #\[ #\])
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\.
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[(:: (:/ #\0 #\9) (:* alpha-numeric-re))
(syn-val lexeme 'constant #f start-pos end-pos)]
[float-re
(syn-val lexeme 'constant #f start-pos end-pos)]
[imag-re
(syn-val lexeme 'constant #f start-pos end-pos)]
[#\'
(begin (displayln (peek-char input-port))
(lex-string input-port #\' start-pos))]
[#\"
(lex-string input-port #\" start-pos)]
[identifier-re
(syn-val lexeme 'symbol #f start-pos end-pos)]
[#\+
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\-
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\*
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\/
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\%
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[(:: #\* #\*)
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[#\<
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
["<="
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
["="
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
["!="
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[">="
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[">"
(syn-val lexeme 'parenthesis #f start-pos end-pos)]
[(eof) (syn-val lexeme 'eof #f start-pos end-pos)]
[#\" ((colorize-string start-pos) input-port)]
[any-char (syn-val lexeme 'symbol #f start-pos end-pos)]
[(special)
(syn-val lexeme 'no-color #f start-pos end-pos)]
)
)