Skip to content

Instantly share code, notes, and snippets.

@jysperm
Created August 1, 2013 14:07
Show Gist options
  • Save jysperm/6131683 to your computer and use it in GitHub Desktop.
Save jysperm/6131683 to your computer and use it in GitHub Desktop.

#语法概述 GPML使用严格的XML语法(关于什么是XML,请自行谷歌),每个GPML源文件必须是形式良好的XML文档.
你需要按照XML的规则转义需要转义的字符.
GPML从不使用XML标记的属性.

每个标签名都有对应的中文和英文,可在后面速查表查到.
我们约定每个源文件的根元素均为<GPML />,强制使用UTF-8编码.

本文档是一份参考而非教程,阅读本文档需要您有其他语言的编程基础.

#变量 ##基本数据类型

  • <int /> 整数
  • <long /> 无限精度整数
  • <string /> 字符串
  • <byte /> 字节
  • <float /> 浮点数
  • <double /> 无限精度小数
  • <bool /> 比特,布尔值

###特殊值

  • <true /> 真,用于<bool /> .

  • <false /> 假,用于<bool /> .

  • <zero /> 数字零,用于<int /><long /><byte /><float /><double />

  • <max /> 最大值,用于<int /><byte /><float />

  • <empty /> 空字符串,用于<string />

  • <null /> 空,独立于类型

###默认初值

  • <int /> - <zero />
  • <long /> - <zero />
  • <string /> - <empty />
  • <byte /> - <zero />
  • <float /> - <zero />
  • <double /> - <zero />
  • <bool /> - <false />

###有效范围

  • <int /> - 长度为寄存器位数
  • <float /> - 遵循IEEE 754的规定,长度为寄存器位数

##字面常量

<类型>值</类型>
  • 上面的类型是占位符,不是指<type />标记
  • 任何时候,使用字面常量都需要写明类型

例如一个值为123的整数:

<int>123</int>

再例如一个值为Hello World的字符串:

<string>Hello World</string>

##声明和定义一个变量

<variable>
    <type>类型</type>
    <name>变量名</name>
    <value>初值</value>
</variable>
  • 变量名区分大小写,可以使用任何字符,只需要按照XML的规则进行转义(以后不再强调).
  • 初值为可选项,是一个右值表达式,不声明初值即使用相应类型的默认初值.

例如声明一个名为a,类型为int,初值为456的变量:

<variable>
    <type><int /></type>
    <name>a</name>
    <value><int>456</int></value>
</variable>

###常量 通过在声明变量时加入<const />标记,即可表示这个变量为常量,不可更改

例如:

<variable>
    <type><int /></type>
    <name>a</name>
    <value><int>456</int></value>
    <const />
</variable>

##引用变量 你可以在任何一个需要右值的地方通过下面的方式引用一个变量:

<variable>变量名</variable>

例如引用一个变量名为a的变量:

<variable>a</variable>

##赋值

<move>
    <form>右值表达式</form>
    <to>左值</to>
</move>
  • <form /><to />的类型必须相同,或满足自动类型转换的条件.

例如将a赋值给b:

<move>
    <form><variable>a</variable></form>
    <to><variable>b</variable></to>
</move>

再例如将字面常量Hello World赋值给a:

<move>
    <form><string>Hello World</string></form>
    <to><variable>a</variable></to>
</move>

###运算符 有下面五种运算符:

  • <plus /> - 加,适用于<int /><long /><byte /><float /><double /><string />
  • <minus /> - 减,适用于<int /><long /><byte /><float /><double />
  • <multiply /> 乘,适用于<int /><long /><byte /><float /><double /><string />
  • <except /> 除,适用于<int /><long /><byte /><float /><double />
  • <mod /> 取余数,适用于<int /><long /><byte />

你可以使用<calc />标签进行计算,例如计算1和2的和:

<calc>
    <value><int>1</int></value>
    <plus />
    <value><int>2</int></value>
</calc>

你也可以一次计算两个以上的数,但是他们会按顺序进行计算,而不是按照运算符的优先级计算:

<calc>
    <value><int>1</int></value>
    <plus />
    <value><int>2</int></value>
    <multiply />
    <value><int>3</int></value>
</calc>

上面的代码计算的是(1+2)*3的值.

你还可以在<move />标签中对多个<form />进行计算.
例如计算2*3,将结果赋值到变量a:

<move>
    <form><int>2</int></form>
    <multiply />
    <form><int>3</int></form>
    <to><variable>a</variable></to>
</move>

#作用域 下列标记中,将视为一个单独的作用域:<select /><while /><case /><function />

引用变量时,从内层向外层开始查找,直到找到这个标识符.

#流程控制 ##选择语句 ###单选

<select>
    <if>布尔表达式</if>
    <then>
        语句序列A
    </then>
    <else>
        语句序列B
    </else>
</select>
  • 当布尔表达式为<true />时,执行<then />中的语句序列,执行<else />中的语句序列.
  • <else />可省略.

###多选

<select>
    <if>右值表达式</if>
    <case>
        <value>匹配值1</value>
        <then>
            语句序列1
        </then>
    </case>
    <case>
        <value>匹配值2</value>
        <then>
            语句序列2
        </then>
    </case>
    <else>
            语句序列3
    </else>
</select>
  • 依次执行所有<value /><if />相等的<case />中的<then />中的语句.

  • 如果没有一个<case />被匹配,则执行<else />中的语句.

  • <value />的类型和<if />必须相同,或满足自动类型转换的条件.

  • <value />可省略,这时的<case />必被执行.

  • 单选和多选并不兼容,<case /><then />不能直接存在于<select />下.

##循环语句 ###当型循环

<while>
    <if>布尔表达式</if>
    <then>
        语句序列
    </then>
</while>
  • 执行<then />中的语句序列直到<if /><false />.
  • <if />可省略,这时为死循环.

###计数循环和遍历

<while>
    <for>整数表达式或列表对象</for>
    <index>计数器/指针名</index>
    <then>
        语句序列
    </then>
</while>
  • 如果<for />为整数,则执行<then />中的语句序列<for />次,<index />中定义的变量名作为计数器,由0起始.
  • 如果<for />为列表对象类型,则对于其中的每个元素执行<then />中的语句序列,<index />中定义的变量名作为循环指针.
  • <index />可省略.

###跳出循环

<break />
  • 该标记可跳出<while />循环.

###进入下一次循环

<continue />
  • 该标记可跳过<while />的剩余部分,进入下一次循环.

#数组 ##声明数组 和声明变量很类似,我们只需要在类型上下文章就行了:

<variable>
    <type>
        <listof>元素类型</listof>
        <size>数组尺寸</size>
    </type>
    <name>数组名</name>
    <value>初值</value>
</variable>

例如声明一个具有10个整数元素的数组a,每个元素的初值均为100:

<variable>
    <type>
        <listof><int /></listof>
        <size><int>10</int></size>
    </type>
    <name>a</name>
    <value><int>100</int></value>
</variable>

这种情况下,每个元素都会被设置为初值,你可以通过下面的方式,为数组的每个元素设定不同的初值:

<variable>
    <type>
        <listof>元素类型</listof>
        <size>数组尺寸</size>
    </type>
    <name>数组名</name>
    <value>
        <value>初值1</value>
        <value>初值2</value>
        <value>初值3</value>
    </value>
</variable>
  • <size />是整形表达式.

##引用数组元素 你可以这样引用数组的元素

<indexof>
    <variable>数组名名</variable>
    <index>索引值</index>
</indexof>
  • 一个数组的元素范围是0到<size />减一.

#函数 ##定义函数

<function>
    <name>函数名<name>
    <type>返回值类型<type>
    <params>
        <variable>
            <type>参数类型1</type>
            <name>参数名1</name>
            <value>参数默认值1</value>
        </variable>
        <variable>
            <type>参数类型2</type>
            <name>参数名2</name>
            <value>参数默认值2</value>
        </variable>
    </params>
    <body>
        函数语句序列
        <return>返回值</return>
    </body>
</function>
  • <params />中的<variable />中的<value />可省略,这时调用时要求必须提供参数.
  • <type />可省略,这时不返回值.
  • <body />中恰当的位置应该用<return />来返回值.
  • 支持函数重载

##调用函数

<call>
    <function>函数名</function>
    <params>
        <variable>参数1</variable>
        <variable>参数2</variable>
    </params>
</call>

##模板函数

<function>
    <name>函数名<name>
    <type>返回值类型<type>
    <template>模板参数1<template>
    <template>模板参数1<template>
    <params>
        <variable>
            <type>参数类型1</type>
            <name>参数名1</name>
        </variable>
    </params>
    <body>
        函数语句序列
    </body>
</function>
  • 在整个函数范围内,<template>模板参数名<template>即可作为类型名使用.

在参数声明中,还可以直接把<type />替换成<template />,这样即可自动接收任意类型的参数,在调用时也不必写明模板参数,例如:

<function>
    <name>函数名<name>
    <type>返回值类型<type>
    <params>
        <variable>
            <template>模板参数名</template>
            <name>参数名</name>
        </variable>
    </params>
    <body>
        函数语句序列
    </body>
</function>

##调用模板函数

<call>
    <function>函数名</function>
    <template>模板参数1<template>
    <template>模板参数2<template>
    <params>
        <variable>参数1</variable>
        <variable>参数2</variable>
    </params>
</call>
  • 模板参数是一个类型名,例如<int />.

##参数传递方式 默认使用传值方式传递参数,可通过添加<byref />标记来通过引用方式传递参数,例如:

<function>
    <name>函数名<name>
    <type>返回值类型<type>
    <params>
        <variable>
            <type>参数类型</type>
            <name>参数名</name>
            <byref />
        </variable>
    </params>
    <body>
        函数语句序列
    </body>
</function>

#类 ##定义类

<class>
    <name>类名<name>
    <public>
        公有成员
    </public>
    <protected>
        保护成员
    </protected>
    <private>
        私有成员
    </private>
</class>
  • 你可以在<public /><protected /><private />中声明成员变量、成员函数.
  • 构造函数与类名同名.
  • 析构函数与类名同名,且仅接受一个<null />类型的参数.
  • 构造函数和析构函数不返回值.

声明成员变量和成员函数时,可以加入<static />标记使其成为静态成员.

在类的实例中,可使用<this />引用到当前实例.

##引用类成员 引用成员函数:

<call>
    <function>
        <class>类名</class>
        <name>函数名</name>
    </function>
    <params>
        <variable>参数1</variable>
        <variable>参数2</variable>
    </params>
</call>

引用成员变量:

<variable>
    <class>类名</class>
    <name>变量名</name>
</variable>
  • 其中<class> /可以嵌套.

##声明对象 声明对象和声明一个变量一样:

<variable>
    <type><class>类名</class></type>
    <name>变量名</name>
</variable>

可以通过<params />向类的构造函数传递参数:

<variable>
    <type><class>类名</class></type>
    <name>变量名</name>
    <params>
        <variable>参数1</variable>
        <variable>参数2</variable>
    </params>
</variable>

##继承 可以加入<inherit />标记来生成派生类:

<class>
    <name>类名<name>
    <inherit>
        <public />
        <class>基类名</class>
    </inherit>
</class>
  • 可以加入多个<inherit />标记来进行多重继承.
  • 可以在成员函数中加入<abstract />标记来表示这是一个抽象函数,派生类必须实现该函数,这种情况函数的<body />可以省略.
  • 可以在成员函数中加入<virtual />标记来表示这是一个虚函数.

#编译和执行 编译和解释时,全部代码都被读入编译器/解释器来建立模型,所以标识符在使用前无需声明.
程序执行从一个无参数的main函数开始.

##编译时包含

<include>文件名</include>
  • 编译器会确保每个文件只被包含一次.

#标记速查

  • int - 整数
  • long - 无限精度整数
  • string - 字符串
  • byte - 字节
  • float - 浮点数
  • double - 无限精度小数
  • bool - 布尔
  • true - 真
  • false - 假
  • zero - 零
  • max - 最大
  • empty - 空
  • null - 无
  • variable - 变量
  • type - 类型
  • name - 名字
  • value - 值
  • const - 常量
  • form - 从
  • to - 至
  • plus - 加
  • minus - 减
  • multiply - 乘
  • except - 除
  • mod - 取余数
  • select - 选择
  • if - 如果
  • then - 则
  • else - 否则
  • case - 匹配
  • while - 循环
  • for - 对于
  • index - 索引
  • break - 跳出
  • continue - 继续
  • listof - 一个列表
  • size - 尺寸
  • indexof - 元素
  • body - 主体
  • return - 返回
  • template - 模板
  • call - 调用
  • byref - 传地址
  • class - 类
  • inherit - 继承
  • public - 公有
  • protected - 保护
  • private - 私有
  • static - 静态
  • this - 当前
  • inherit - 继承
  • abstract - 抽象
  • virtual - 虚
  • include - 包含
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment