" Vim syntax file
" Language:	   Resp
" Last Change: 2009 Dec 5
" Maintainer:  David Robillard <d@drobilla.net>

if version < 600
  syntax clear
elseif exists("b:current_syntax")
  finish
endif

" Fascist highlighting: everything that doesn't fit the rules is an error...

"syn match	respError	oneline    ![^ \t()\[\]";]*!
syn match	respError	oneline    ")"

" Quoted and backquoted stuff

syn region respQuoted matchgroup=Delimiter start="['`]" end=![ \t()\[\]";]!me=e-1 contains=ALLBUT,respStruc,respSyntax,respFunc

syn region respQuoted matchgroup=Delimiter start="['`](" matchgroup=Delimiter end=")" contains=ALLBUT,respStruc,respSyntax,respFunc
syn region respQuoted matchgroup=Delimiter start="['`]#(" matchgroup=Delimiter end=")" contains=ALLBUT,respStruc,respSyntax,respFunc

syn region respStrucRestricted matchgroup=Delimiter start="(" matchgroup=Delimiter end=")" contains=ALLBUT,respStruc,respSyntax,respFunc
syn region respStrucRestricted matchgroup=Delimiter start="#(" matchgroup=Delimiter end=")" contains=ALLBUT,respStruc,respSyntax,respFunc

" Popular Scheme extension:
" using [] as well as ()
syn region respStrucRestricted matchgroup=Delimiter start="\[" matchgroup=Delimiter end="\]" contains=ALLBUT,respStruc,respSyntax,respFunc
syn region respStrucRestricted matchgroup=Delimiter start="#\[" matchgroup=Delimiter end="\]" contains=ALLBUT,respStruc,respSyntax,respFunc

syn region respUnquote matchgroup=Delimiter start="," end=![ \t\[\]()";]!me=e-1 contains=ALLBUT,respStruc,respSyntax,respFunc
syn region respUnquote matchgroup=Delimiter start=",@" end=![ \t\[\]()";]!me=e-1 contains=ALLBUT,respStruc,respSyntax,respFunc

syn region respUnquote matchgroup=Delimiter start=",(" end=")" contains=ALL
syn region respUnquote matchgroup=Delimiter start=",@(" end=")" contains=ALL

syn region respUnquote matchgroup=Delimiter start=",#(" end=")" contains=ALLBUT,respStruc,respSyntax,respFunc
syn region respUnquote matchgroup=Delimiter start=",@#(" end=")" contains=ALLBUT,respStruc,respSyntax,respFunc

syn region respUnquote matchgroup=Delimiter start=",\[" end="\]" contains=ALL
syn region respUnquote matchgroup=Delimiter start=",@\[" end="\]" contains=ALL

syn region respUnquote matchgroup=Delimiter start=",#\[" end="\]" contains=ALLBUT,respStruc,respSyntax,respFunc
syn region respUnquote matchgroup=Delimiter start=",@#\[" end="\]" contains=ALLBUT,respStruc,respSyntax,respFunc

" R5RS Scheme Functions and Syntax:

if version < 600
  set iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_
else
  setlocal iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_
endif

syn keyword respSyntax fn def if match def-type
syn keyword respFunc cons car cdr

syn match respTypeAnnotation    ":[A-Z][a-zA-Z\.]*"
syn match respTypeAnnotationExp ":([A-Z][a-zA-Z ]*)"
syn match respType              "[A-Z][a-zA-Z\.]*"
syn match respPrefix            "[a-z][a-z]*\."

" ... so that a single + or -, inside a quoted context, would not be
" interpreted as a number (outside such contexts, it's a respFunc)

syn match	respDelimiter	oneline    !\.[ \t\[\]()";]!me=e-1
syn match	respDelimiter	oneline    !\.$!
" ... and a single dot is not a number but a delimiter

" This keeps all other stuff unhighlighted, except *stuff* and <stuff>:

syn match	respOther	oneline    ,[a-z!$%&*/<=>?^_~+@#%-][-a-z!$%&*/:<=>?^_~0-9+.@#%]*,
"syn match	respError	oneline    ,[a-z!$%&*/:<=>?^_~+@#%-][-a-z!$%&*/:<=>?^_~0-9+.@#%]*[^-a-z!$%&*/:<=>?^_~0-9+.@ \t\[\]()";]\+[^ \t\[\]()";]*,
"
"syn match	respOther	oneline    "\.\.\."
"syn match	respError	oneline    !\.\.\.[^ \t\[\]()";]\+!
"" ... a special identifier
"
"syn match	respConstant	oneline    ,\*[-a-z!$%&*/:<=>?^_~0-9+.@]*\*[ \t\[\]()";],me=e-1
"syn match	respConstant	oneline    ,\*[-a-z!$%&*/:<=>?^_~0-9+.@]*\*$,
"syn match	respError	oneline    ,\*[-a-z!$%&*/:<=>?^_~0-9+.@]*\*[^-a-z!$%&*/:<=>?^_~0-9+.@ \t\[\]()";]\+[^ \t\[\]()";]*,
"
"syn match	respConstant	oneline    ,<[-a-z!$%&*/:<=>?^_~0-9+.@]*>[ \t\[\]()";],me=e-1
"syn match	respConstant	oneline    ,<[-a-z!$%&*/:<=>?^_~0-9+.@]*>$,
"syn match	respError	oneline    ,<[-a-z!$%&*/:<=>?^_~0-9+.@]*>[^-a-z!$%&*/:<=>?^_~0-9+.@ \t\[\]()";]\+[^ \t\[\]()";]*,

" Non-quoted lists, and strings:

syn region respStruc matchgroup=Delimiter start="(" matchgroup=Delimiter end=")" contains=ALL
syn region respStruc matchgroup=Delimiter start="#(" matchgroup=Delimiter end=")" contains=ALL

syn region respStruc matchgroup=Delimiter start="\[" matchgroup=Delimiter end="\]" contains=ALL
syn region respStruc matchgroup=Delimiter start="#\[" matchgroup=Delimiter end="\]" contains=ALL

" Simple literals:
syn region respString start=+\%(\\\)\@<!"+ skip=+\\[\\"]+ end=+"+

" Comments:

syn match	respComment	";.*$"


" Writing out the complete description of Scheme numerals without
" using variables is a day's work for a trained secretary...

syn match	respOther	oneline    ![+-][ \t\[\]()";]!me=e-1
syn match	respOther	oneline    ![+-]$!
"
" This is a useful lax approximation:
syn match	respNumber	oneline    "[-#+0-9.][-#+/0-9a-f@i.boxesfdl]*"
syn match	respError	oneline    ![-#+0-9.][-#+/0-9a-f@i.boxesfdl]*[^-#+/0-9a-f@i.boxesfdl \t\[\]()";][^ \t\[\]()";]*!

syn match	respBoolean	oneline    "#[tf]"
syn match	respError	oneline    !#[tf][^ \t\[\]()";]\+!

syn match	respChar	oneline    "#\\"
syn match	respChar	oneline    "#\\."
syn match	respError	oneline    !#\\.[^ \t\[\]()";]\+!
syn match	respChar	oneline    "#\\space"
syn match	respError	oneline    !#\\space[^ \t\[\]()";]\+!
syn match	respChar	oneline    "#\\newline"
syn match	respError	oneline    !#\\newline[^ \t\[\]()";]\+!

syn region	respComment start="#|" end="|#"

" Synchronization and the wrapping up...

syn sync match matchPlace grouphere NONE "^[^ \t]"
" ... i.e. synchronize on a line that starts at the left margin

" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
" For version 5.8 and later: only when an item doesn't have highlighting yet
if version >= 508 || !exists("did_resp_syntax_inits")
  if version < 508
    let did_resp_syntax_inits = 1
    command -nargs=+ HiLink hi link <args>
  else
    command -nargs=+ HiLink hi def link <args>
  endif
  
  "HiLink respPrefix            Identifier
  HiLink respSyntax            Statement
  HiLink respFunc              Function
  HiLink respTypeAnnotation    Type
  HiLink respTypeAnnotationExp Type
  HiLink respType              Type

  HiLink respString            String
  HiLink respChar              Character
  HiLink respNumber            Number
  HiLink respBoolean           Boolean
                                
  HiLink respDelimiter         Delimiter
  HiLink respConstant          Constant
                                
  HiLink respComment           Comment
  HiLink respMultilineComment  Comment
  HiLink respError             Error
                                
  HiLink respExtSyntax         Type
  HiLink respExtFunc           PreProc
  delcommand HiLink
endif

let b:current_syntax = "resp"