这个程序展示了 PPCA Language 的语法及语义. 这个程序会求出所有输入数据的平方和.
; 注释以分号开头
; 程序入口点为 main 函数
(function (main)
; 多条语句需要用代码块包裹起来
(block
; 读入一个整数 n
; scan 是一个内置函数
(set n (scan))
; 读入 n 个整数, 存入一个数组
; array.scan 也是一个内置函数
(set xs (array.scan n))
; 输出答案
(print (sum^2 xs n))))
; sum^2 是一个合法的变量名/函数名
(function (sum^2 array length)
(block
; if 语句
; == 和 != 是内置函数 (下面的 < + * 都是内置函数)
(if (== length 0)
(return 0))
(if (!= length 0)
; 变量的作用域为整个函数;
; 即使退出了 if 语句, 在后面 for 中也能使用 sum 变量
(set sum 0))
; for 语句
(for
(set i 0) ; i = 0
(< i length) ; i < length
(set i (+ i 1)) ; ++i
(block
; value = array[i]
(set value (array.get array i))
; sum = sum + value * value
(set sum (+ sum (* value value)))))
; 返回平方和
(return sum)))相当于:
int main () {
int n;
std::cin >> n;
int *xs = new int[n];
for (int i = 0; i < n; ++i) std::cin >> xs[i];
std::cout << sum2(xs, n) << std::endl;
}
int sum2 (int *array, int length) {
int sum, i, value;
if (length == 0) return 0;
if (length != 0) sum = 0;
for (i = 0; i < length; ++i) {
value = array[i];
sum = sum + value * value;
}
return sum;
}PPCA Language 是一种极简但可用的命令式 (imperative) 编程语言. 这个语言的语法采用类似于 Lisp 的 S-expression 形式, 以方便解析与处理. 语法对空白符不敏感, 空格及换行符的数量不影响程序的语义.
PPCA Language 中具有两种值 (value): 数字 (范围及运算同 C++ 中的 int 类型) 和定长 int 数组 (0-based). 类型系统为动态类型, 源代码中不指定变量的类型.
一个程序 (program) 由若干个函数 (function) 构成, 程序的入口点为 main 函数. 函数具有返回值. 若函数执行完成时没有指定返回值, 则返回值为数字 0.
一个函数中包含一条语句 (statement), 语句中可能包含表达式 (expression). 表达式在执行时会具有一个值.
你可以用 ; 开始一个行注释, 类似于 C/C++ 中的 //.
下文中, 斜体部分表示一个占位符, 例如:
(set variable-name value)表示这些语句是合法的语句:
(set foo 1)
(set xyzzy foo)占位符后面的下标表示占位符的类型.
- id 表示一个变量名或函数名 (identifier, 标识符);
- stmt 表示一个语句 (statement);
- expr 表示一个表达式 (expression).
变量名或函数名可以包含除小括号 ()、分号 ; 外的所有可见 ASCII 字符, 但不能以数字开头; - 开头的变量名也不能是纯数字 (例如 -123 不是合法的变量名, 而 -123abc 是合法的).
占位符后面的 ... 表示这里可以填写零个、一个或者多个参数, 以空格分隔.
十进制整数是整数常量. 可以带有前导 0, 可以是负数.
直接写出一个变量名即可.
语法如下:
(function-nameid function-argumentsexpr...)即使函数没有参数, 也需要在函数名两侧加上括号.
例如:
(print 42) ; 打印 42
(print (* 6 7)) ; 打印 42
(print (* (+ 2 4) (+ 3 4))) ; 打印 42
(print foobar) ; 打印变量 foobar 的值
(print (+ foobar 42)) ; 打印变量 foobar 的值加上 42
(array.set a 0 42) ; 将 a 变量所表示的数组第 0 项设为 42
(array.set a 0 (scan)) ; 读入一个数到 a 变量所表示的数组第 0 项每行均为合法的函数调用.
内置函数如下: (传入错误类型参数时, 会直接异常终止程序运行)
int + (int x, int y): 返回 C++ 中x + y的值.int - (int x, int y): 返回 C++ 中x - y的值.int * (int x, int y): 返回 C++ 中x * y的值.int / (int x, int y): 若y不为 0, 则返回 C++ 中x / y的值, 否则异常终止运行.int % (int x, int y): 若y不为 0, 则返回 C++ 中x % y的值, 否则异常终止运行.int < (int x, int y): 返回 C++ 中x < y的值.int > (int x, int y): 返回 C++ 中x > y的值.int <= (int x, int y): 返回 C++ 中x <= y的值.int >= (int x, int y): 返回 C++ 中x >= y的值.int == (int x, int y): 返回 C++ 中x == y的值.int != (int x, int y): 返回 C++ 中x != y的值.int || (int x, int y): 返回 C++ 中x || y的值. 需注意没有短路求值.int && (int x, int y): 返回 C++ 中x && y的值. 需注意没有短路求值.int ! (int x): 返回 C++ 中!x的值.int scan (): 读入一个整数.int print (int x): 打印整数x和\n并返回 0.int[] array.create (int length): 创建一个长度为length的数组, 初始化为 0, 并返回.int[] array.scan (int length): 创建一个长度为length的数组, 读入length个数到数组中, 并返回这个数组. 类似于for (int i = 0; i < length; ++i) std::cin >> array[i];.int array.print (int[] array): 依次打印array数组中的所有数 (打印完每个数之后有\n), 并返回 0.int array.get (int[] array, int index): 返回array数组的第index项. 数组越界则终止程序.int array.set (int[] array, int index, int value): 将array数组的第index项设为value. 数组越界则终止程序.
表达式可以单独成为一个语句 (ExpressionStatement).
(set variable-nameid valueexpr)赋值语句的作用域为函数, 无需提前声明变量. 试图使用一个没有赋值过的变量会导致程序直接异常终止. 例如:
(function (main)
(block
(set x 1)
(if 1
(block
(set x 2)))
(print x)))会打印 2 而不是 1.
没有函数指针的概念; 不能把一个函数当成值赋给一个变量, 变量名与函数名也不能重名.
(if conditionexpr
then-bodystmt)如果 condition 所存储的整数不为 0, 则执行 body. 如果 condition 存储的不是一个整数, 则异常终止程序.
(for
initstmt
testexpr
updatestmt
bodystmt)语义同 C++ 中的
for (init; test; update) body;若 test 不为整数, 则异常终止程序.
(block
block-bodystmt...)依次执行 block-body 中的多条语句.
(return return-valueexpr)退出函数.
(function (function-nameid function-parametersid...)
function-bodystmt)函数的定义顺序对语义没有影响; 前面定义的函数也可以调用后面定义的函数.
例如:
(function (add x y)
(return (+ x y)))相当于:
int add (int x) {
return x + y;
}例如:
(function (abs x)
(block
(if (> x 0)
(return x))
(return (- 0 x))))相当于:
int abs (int x) {
if (x > 0) return x;
return 0 - x;
}