<?xml version="1.0" encoding="UTF-8"?>
<!--
 Copyright (C) 2018 Jack R Linhart <iatenine@gmail.com>
 Copyright (C) 2014 Matthias F. Brandstetter <pub@mabra.me>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
 License as published by the Free Software Foundation; either
 version 2 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Library General Public License for more details.

 You should have received a copy of the GNU Library General Public
 License along with this library; if not, write to the
 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.
-->

<language id="gdscript" name="GDScript" version="2.0" _section="Script">
  <metadata>
    <property name="mimetypes">text/x-gdscript</property>
    <property name="globs">*.gd</property>
    <property name="line-comment-start">#</property>
  </metadata>

  <styles>
    <style id="module-handler"    name="Module Handler"        map-to="def:preprocessor"/>
    <style id="keyword"           name="Keyword"               map-to="def:keyword"/>
    <style id="multiline-string"  name="Multiline string"      map-to="def:string"/>
    <style id="string"            name="String"                map-to="def:string"/>
    <style id="escaped-char"      name="Escaped Character"     map-to="def:special-char"/>
    <style id="format"            name="Format"                map-to="def:character"/>
    <style id="string-conversion" name="string-conversion"/>
    <style id="special-variable"  name="Special Variable"      map-to="def:identifier"/>
    <style id="boolean"           name="Boolean"               map-to="def:boolean"/>
    <style id="floating-point"    name="Floating point number" map-to="def:floating-point"/>
    <style id="decimal"           name="Decimal number"        map-to="def:decimal"/>
    <style id="base-n-integer"    name="Base-N number"         map-to="def:base-n-integer"/>
    <style id="complex"           name="Complex number"        map-to="def:complex"/>
    <style id="builtin-constant"  name="Builtin Constant"      map-to="def:special-constant"/>
    <style id="builtin-object"    name="Builtin Object"        map-to="def:type"/>
    <style id="builtin-function"  name="Builtin Function"      map-to="def:builtin"/>
  </styles>

  <definitions>
    <define-regex id="identifier">[_a-zA-Z][_a-zA-Z0-9]*</define-regex>
    <define-regex id="number">[1-9][0-9]*</define-regex>

    <context id="format" style-ref="format" extend-parent="false">
      <match extended="true">
        %                       # leading % sign
        \(\%{identifier}\)?     # mapping key
        [#0\-\ \+]*             # conversion flags
        (\-?\%{number}|\*)?     # minimum field width
        (\.(\-?\%{number}|\*))? # precision
        (hlL)?                  # lentgh modifier
        [diouxXeEfFgGcrs%]      # conversion type
      </match>
    </context>

    <!-- http://docs.python.org/ref/strings.html -->
    <context id="escaped-char" style-ref="escaped-char" extend-parent="true">
      <match extended="true">
        \\(                   # leading backslash
        [\\\"\'nrbtfav\?] |   # escaped character
        [0-7]{1,3} |          # one, two, or three octal digits
        x[0-9A-Fa-f]+         # 'x' followed by hex digits
        )
      </match>
    </context>

    <context id="double-quoted-string" style-ref="string" end-at-line-end="true" class="string" class-disabled="no-spell-check">
      <start>"</start>
      <end>"</end>
      <include>
        <context ref="format"/>
        <context ref="escaped-char"/>
        <context ref="def:line-continue"/>
      </include>
    </context>

    <context id="single-quoted-string" style-ref="string" end-at-line-end="true" class="string" class-disabled="no-spell-check">
      <start>'</start>
      <end>'</end>
      <include>
        <context ref="format"/>
        <context ref="escaped-char"/>
        <context ref="def:line-continue"/>
      </include>
    </context>

    <context id="gdscript" class="no-spell-check">
      <include>
        <context ref="def:shebang"/>
        <context ref="def:shell-like-comment"/>
        
        <context ref="double-quoted-string"/>
        <context ref="single-quoted-string"/>

        <context id="special-variables" style-ref="special-variable">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>_init</keyword>
          <keyword>_ready</keyword>
        </context>

        <context id="boolean" style-ref="boolean">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>false</keyword>
          <keyword>true</keyword>
        </context>

        <define-regex id="float" extended="true">
          ( (\d+)?\.\d+ | \d+\. ) |
          ( (\d+|(\d+)?\.\d+|\d+\.)[eE][+-]?\d+ )
        </define-regex>

        <context id="complex" style-ref="complex">
          <match>(?&lt;![\w\.])(\%{float}|\d+)[jJ]\b</match>
        </context>

        <context id="float" style-ref="floating-point">
          <match>(?&lt;![\w\.])\%{float}(?![\w\.])</match>
        </context>

        <context id="decimal" style-ref="decimal">
          <match>(?&lt;![\w\.])([1-9][0-9]*|0)[lL]?(?![\w\.])</match>
        </context>

        <context id="octal" style-ref="base-n-integer">
          <match>(?&lt;![\w\.])0[0-7]+[lL]?(?![\w\.])</match>
        </context>

        <context id="hex" style-ref="base-n-integer">
          <match>(?&lt;![\w\.])0[xX][0-9A-Fa-f]+[lL]?(?![\w\.])</match>
        </context>

        <context id="module-handler" style-ref="module-handler">
          <keyword>extends</keyword>
          <keyword>preload</keyword>
        </context>

        <context id="builtin-constants" style-ref="builtin-constant">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>null</keyword>
        </context>

        <context id="keyword" style-ref="keyword">
          <keyword>and</keyword>
          <keyword>assert</keyword>          
          <keyword>break</keyword>
          <keyword>breakpoint</keyword>
          <keyword>class</keyword>
          <keyword>const</keyword>
          <keyword>continue</keyword>
          <keyword>elif</keyword>
          <keyword>else</keyword>
          <keyword>enum</keyword>
          <keyword>export</keyword>
          <keyword>extends</keyword>
          <keyword>false</keyword>
          <keyword>float</keyword>
          <keyword>for</keyword>
          <keyword>func</keyword>
          <keyword>if</keyword>
          <keyword>in</keyword>
          <keyword>int</keyword>
          <keyword>not</keyword>
          <keyword>null</keyword>
          <keyword>onready</keyword>
          <keyword>or</keyword>
          <keyword>pass</keyword>
          <keyword>return</keyword>
          <keyword>self</keyword>
          <keyword>setget</keyword>
          <keyword>signal</keyword>
          <keyword>static</keyword>
          <keyword>tool</keyword>
          <keyword>true</keyword>
          <keyword>var</keyword>
          <keyword>while</keyword>
          <keyword>yield</keyword>
        </context>

        <context id="builtin-objects" style-ref="builtin-object">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>Vector2</keyword>
          <keyword>Size2</keyword>
          <keyword>Rect2</keyword>
          <keyword>Vector3</keyword>
          <keyword>Matrix32</keyword>
          <keyword>Plane</keyword>
          <keyword>Quat</keyword>
          <keyword>AABB</keyword>
          <keyword>Box3</keyword>
          <keyword>Matrix3</keyword>
          <keyword>Transform</keyword>
          <keyword>Color</keyword>
          <keyword>Image</keyword>
          <keyword>NodePath</keyword>
          <keyword>RID</keyword>
          <keyword>Object</keyword>
          <keyword>InputEvent</keyword>
        </context>

        <context id="builtin-function" style-ref="builtin-function">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>print</keyword>
          <keyword>sin</keyword>
          <keyword>cos</keyword>
          <keyword>tan</keyword>
          <keyword>sinh</keyword>
          <keyword>cosh</keyword>
          <keyword>tanh</keyword>
          <keyword>asin</keyword>
          <keyword>acos</keyword>
          <keyword>atan</keyword>
          <keyword>atan2</keyword>
          <keyword>sqrt</keyword>
          <keyword>fmod</keyword>
          <keyword>fposmod</keyword>
          <keyword>floor</keyword>
          <keyword>ceil</keyword>
          <keyword>round</keyword>
          <keyword>abs</keyword>
          <keyword>sign</keyword>
          <keyword>pow</keyword>
          <keyword>log</keyword>
          <keyword>exp</keyword>
          <keyword>isnan</keyword>
          <keyword>isinf</keyword>
          <keyword>ease</keyword>
          <keyword>decimals</keyword>
          <keyword>stepify</keyword>
          <keyword>lerp</keyword>
          <keyword>dectime</keyword>
          <keyword>randomize</keyword>
          <keyword>rand</keyword>
          <keyword>randi</keyword>
          <keyword>randf</keyword>
          <keyword>rand_range</keyword>
          <keyword>rand_seed</keyword>
          <keyword>deg2rad</keyword>
          <keyword>rad2deg</keyword>
          <keyword>linear2db</keyword>
          <keyword>db2linear</keyword>
          <keyword>max</keyword>
          <keyword>min</keyword>
          <keyword>clamp</keyword>
          <keyword>nearest_po2</keyword>
          <keyword>weakref</keyword>
          <keyword>convert</keyword>
          <keyword>str</keyword>
          <keyword>print</keyword>
          <keyword>printt</keyword>
          <keyword>printerr</keyword>
          <keyword>printraw</keyword>
          <keyword>range</keyword>
          <keyword>load</keyword>
          <keyword>inst2dict</keyword>
          <keyword>dict2inst</keyword>
        </context>
      </include>
    </context>
  </definitions>
</language>
