辛蒂JS公司

CindyScript语言规范

本文档对CindyScript语言进行了低层次的描述。

词汇结构

词法结构描述输入字符串是如何转换的变成一系列单独的单位,称为标记,类似于单词。

评论

单行注释由引入//跨越到线的末端,即下一个换行符或输入文本的结尾。

6*7//这是一个注释,因此将被忽略
42

块注释由/**/.

CindyScript>=3.0
1 + /* 7 - */ 2

CindyJS中的块注释可以嵌套。

CindyScript>=3.0
1 + /* 2 + /* 3 + */ 4 + */ 5
6

未闭合的块注释是错误的。

CindyScript>=3.0
1+/*未关闭
CindyScriptParse错误:1:4处的注释未终止:“/*”
1+/*这个/*仍然*/没有
CindyScriptParseError:1:4处未终止的注释:“/*”

空白

CindyScript将以下字符视为空白:

这些字符可能出现在词汇标记之间不影响代码的含义。一个例外是字符串,这些标记是按字面意思解释的。另一个例外是行评论(// …)其中newline具有终止注释的效果。

也可能出现空格和水平制表符在内部某些词汇标记,即在数字文字标识符.如果在其中一个标记中遇到此类空白字符,在进一步处理发生之前将它们剥离,因此,它们不是标记语义内容的一部分。

弧sin(1)
90°
abc=1 2 3。45; a b c类
123.45
回复se([1,2,3])
[3, 2, 1]

换行仍然分隔标记,因此以下内容被解读为三个不同的标识符之间没有运算符:

CindyScript>=3.0
b条c(c)
CindyScriptParse错误:2:1处缺少运算符:“b”
CindyScript<3.0
b条c(c)
123.45

字符串常量

字符串文字以双引号开头,并在下一个引号处结束。没有转义序列;引号之间的所有文本都包含在字面上。使用unicode码功能包括文字双引号和其他特殊字符。

“”文本换行符、//注释和某些制表符“
带有下划线、//注释和特定字符的文本
她说“+unicode(“22”)+“你好,世界!”+unicode(”22“)
她说“你好,世界!”\""

请注意,在本文档中,字符串结果以JSON格式打印,但这种表示实际上并不适合作为输入。

数值型的字面值

数字文字通常由整数部分组成,可选的小数部分和可选的十进制指数。整数部分是由零个或多个ASCII十进制数字组成的序列。如果分数部分没有数字,则整数部分mus至少包含一个数字。小数部分是一个点(U+002E),后跟零位或多位数字。指数是字母e(电子)E类,后面可能有一个标志(+-),后跟一个或多个数字。

CindyScript>=3.0
[1、2.、3.4、.5、6e7、2.e-3、3.2E+1、.5e-3]
[1, 2, 3.4, 0.5, 60000000, 0.002, 32, 0.0005]
[1、2、2、3、3、4、5、6、5、1、2、e-3、3.2、e+1、.5、e-3]
[11, 22, 33.44, 0.56, 600000, 0.012, 32, 0.0005]

与过去的CindyScript版本相反,唯一的点不再是数字0的有效表示。特别是,这包括一个唯一的点作为有效的表示对于数字0。

CindyScript>=3.0
0 + (.)
CindyScriptParse错误:1:5处没有操作数的运算符:“.”
CindyScript<3.0
0 + (.)
0

没有负文字,但一元符号运算符可以与用于构建负数的数字文字。一元否定与二元否定具有相同的优先级,因此它的绑定不如例如电力运营商那么紧密^.

-1^4//实际解析为-(1^4)
-1

复数也没有文字,但是变量预设为复杂单元。

4.5+6.7*i
4.5+i*6.7

没有表示无限值或NaN(非数字)值的文字。

数字文字可以包含任意数量的数字,虽然增加更多的数字不会在内部浮点精度已耗尽。

3.1415926535897932334567890123456789012345==pi//最后一位数字错误!
真的

如果数字文字后面不紧跟,则它只能以点结尾第二个点,因为后者代表一个范围。

1..3
[1, 2, 3]
CindyScript>=3.0
1 . . 
CindyScriptParseError:字段名必须是1:2处的标识符:“.”

标识符名称

标识符用于变量和用于用户定义函数,以及用于此类函数的参数和命名修改器.

标识符可能包含以下一个或多个符号:

除此之外,##1个通过#9也是有效的变量名。但不允许使用多个数字。

#9 = 12; #9
12
#12 = 17; #12
CindyScriptParse错误:1:2处缺少运算符:“2”
foo#1=19;足球#1
CindyScriptParse错误:1:3处缺少运算符:“#1”

字母集包括以下字符飞机基本多语言平面(BMP)除外。这些是使用JavaScript的UTF-16编码中的代理对进行编码的。

CindyScript>=3.0
𝐶𝑖𝑛𝑑𝑦 𝑱𝑺 = 2;𝐶𝑖𝑛𝑑𝑦𝑱𝑺
2

请注意,某些字母的默认文字方向可能是从右向左。根据环境的不同,这可能会导致意外的显示顺序用于输入或输出。

ערשטער = 1;רגע = 2;דריט = 3;[ערשטער, רגע, דריט]
[1, 2, 3]

与许多其他编程语言相反,这个强调_是操作员并且不能用作标识符名称的一部分。如前所述,可以使用空格分隔单词在上面.

函数名不区分大小写。

对于所有(1..3,println(#))
12

操作员和支架

以下部分将介绍一些运算符和括号符号它也构成了词汇标记。

在给定位置解析的标记与在该位置输入的较长部分注意的例外..在数字后面文本,它本身被解析为运算符,而不是以小数点结尾的数字,后跟运算符..

x=[];x: 12.3=4.56;x: “12.3”
4.56

运算符符号中可能没有空格。

CindyScript>=3.0
f(x):=123
CindyScriptParse错误:在1:5:“:”处不能使用运算符后缀

上标和下标

可以使用上标和下标unicode符号来表示指数和指数。它们的操作方式与^_操作员。上标文字是可选的上标符号,后跟一个或多个上标数字。所有字符都可以用in token分隔空白.相应地定义了下标文字。

CindyScript>=3.0
125
4¹
0.25
2¹ 
1024
lst=10*(1..20);第一次
30
第一次₊ ₁ ₅
150

下标与_.对于上标,情况略有不同。

禁止任何操作员跟随上标它会比电力运营商绑得更紧或更紧^.这避免了混淆以下事实:^是正确的社交而上标在视觉上看起来更紧密地结合在一起。

CindyScript>=3.0
2³^4
CindyScriptParse错误:1:2处的上标后不允许有运算符:“^”
2³_1
CindyScriptParse错误:1:2处的上标后不允许有运算符:“_”
(2³)^4
4096
[2³]_1
8

非正式语法

语法描述了如何组合词汇标记以形成表达式。

表达

表达式可以是以下之一

  1. 文字数字或字符串
  2. 用作变量名称的标识符
  3. 零个或多个表达式的序列,用逗号分隔并用括号括起来
  4. 后跟二进制运算符的表达式,后跟表达式
  5. 后跟后缀运算符的表达式
  6. 后跟表达式的前缀运算符
  7. 函数调用

操作员

运算符优先级

CindyJS了解以下运算符,按优先级排序:

  1. :,.,_,°
  2. ^,
  3. *,×,/
  4. +,-,!
  5. ..
  6. ==,!=,<,>,<=,>=,~=,~!=,~<,~>,~<=,~>=,,,=:= (未记录)
  7. &,%
  8. <:
  9. ++,--,~~,:>
  10. =,:=,::=,:=_ ->

同等优先级的运算符通常是左联的。

其中一个例外是^运算符和其他具有同等优先级的运算符,这是正确的社交。

CindyScript>=3.0
3^2^4
43046721
(3^2)^4
6561
CindyScript<3.0
3^2^4
6561

另一类右关联运算符是赋值运算符。

CindyScript>=3.0
x=y=1
1
(x=y)=2
不能将中缀表达式用作左值
2
x个
1

预处理运算符<:也是正确的社交方式。

CindyScript>=3.0
1 <: 2 <: [3, 4, 5] :> 6 :> 7
[1, 2, 3, 4, 5, 6, 7]
1<:2<:[3]-[2]
[1, 3]

有时查看逗号是有意义的,作为另一个操作员,优先级甚至低于.但从那以后,只能在括号内使用,不能在顶层使用,它不包括在上面的列表中。

1, 2, 3
CindyScriptParseError:逗号只能用于以1:1分隔列表元素

其中几个运算符具有替代的Unicode形式通常可读性更强,但更难输入。

这些替代项仅在运算符标记中有效。在数字文字的指数中使用Unicode减号是非法的:

2.34e−5
CindyScriptParse错误:1:4处缺少运算符:“e”

前缀和后缀运算符

这个+-运算符既可以用于中缀,也可以用于前缀表示法。

x=17;-x个
-17个
+x个
17
-[1, 2, 3]
[-1, -2, -3]
+[1, 2, 3]
[1, 2, 3]

这个!运算符只能用于前缀表示法。

!(7 == 7)
CindyScript>=3.0
√4
2

这个°运算符只能用于后缀表示法。

90° + 0
1.5708

所有其他运算符仅在中缀表示法中有效。

括号

括号表达式由一个左括号组成,后跟零个或多个表达式,用逗号分隔,后面是一个匹配的右括号。

在最后一个元素后附加逗号是不正确的,因为thar表示后面是一个空表达式作为最后一个元素。

[1,2,]
[1, 2, ___]

CindyScript知道四种类型的括号:

圆括号(…)

作为(Şexpr›)它可以用于控制表达式的求值顺序。作为(expr1›、бexpr2›……)它用给定的元素定义一个向量。表格()可以用来表示空列表。

7 * (1 + 2)
21
7 * (1, 2)
[7, 14]
7 * ()
[]

方括号[…]

它们总是表示一个列表,即使它们只包含一个表达式。

7 * [1 + 2]
[21]
7 * [1, 2]
[7, 14]
7 * []
[]

花括号{…}

花括号表示JSON对象。JavaScript Object Notation(JSON)是结构化数据序列化的文本格式。有关详细文档,请参阅RFC 4627。CindyScript(目前)只允许字符串作为键,但将来可能会发生变化。

CindyScript>=3.0
7 * {1 + 2}
错误:JSON键必须是字符串。
7 * {1, 2}
错误:JSON键必须是字符串。错误:JSON键必须是字符串。
___
7*{“键”:1}
___
7 * {}
___
正弦{30°}
CindyScriptParseError:尚未为运算符定义{…}。比例为1:3

函数调用

函数调用是函数名(是标识符),后面是用方括号或圆括号括起的零个或多个参数。

罪[0]
0
重置时钟()
___

允许函数参数为空。这与控制流功能特别相关,其中,空参数可以表示空的命令序列。

如果(2<3,println(“返回学校!”)
___

在索引结构的索引位置中使用函数时使用_,.:,必须用括号括起来。(这为类似方法的调用保留了此类构造可能是面向对象编程风格中的匿名函数。)

lst=10*(1..7);f(x):=x+1;lst(f(3))
40
CindyScript>=2016年
lst_f(3)
CindyScriptParseError:索引结构中的函数调用必须以1:5的比例括在括号中

垂直钢筋|…|

只要一个参数,|出口›|表示复数的绝对值,或向量的范数。

|3+4*i|
5
v=[2,2,3,2,2]|v(v)|
5

有两个参数,|vec1›、vec2›|计算这些点或向量之间的距离。

x=[3,7];y=[7,10];|x、 年|
5

使用竖线嵌套表达式是非法的直接在另一个内部:

CindyScript>=3.0
|3+|4*i|-2|
CindyScriptParse错误:在1:3处不能使用运算符后缀:“+”

但是,如果至少有一级其他括号,则可以嵌套它们((…),[…]{…})他们之间。

CindyScript>=3.0
|[3,|4*i|]|
5

形式语法

这是使用上下文无关语法对CindyScript语言的描述如GNU Bison所理解的BNF符号。

大多数非终端有两种类型:一个没有,一个后缀为无条形图.那是因为人不能筑巢|…|不带的构造中间有其他形式的括号。所以无条形图版本是内部使用的版本|…|构造,和其他高层或内部人员(…)[…].

不要期望太多意义来自此语法中使用的非终结符的名称。选择它们主要是为了区分不同的优先级,虽然名称往往会捕获主应用程序在该级别描述的操作员中,这并不总是合适的。

程序:expressionOpt表达式Opt:表达式|%空表达式OptNoBars:表达式NoBars|%空表达:语句|表达式OP_SEMI语句|表达式OP_SEMI|OP_SEMI语句|OP_电磁干扰无栏表达式:语句NoBars|表达式NoBars OP_SEMI语句NoBars|表达NoBars OP_SEMI|OP_SEMI语句无条|OP_电磁干扰陈述:赋值语句无栏:assignmentNoBars分配:列表操作|listOp OP_ASSIGN分配|listOp OP_DEFINE赋值|listOp OP_BDEFINE赋值|列表OP_DEFINE OP_TAKE分配编号栏:listOpNoBars|列表OpNoBars OP_ASSIGN分配NoBars|列表OpNoBars OP_DEFINE赋值NoBars|列表OpNoBars OP_BDEFINE赋值NoBars|列表OpNoBars OP_DEFINE OP_TAKE列表Op:预先发送|列表OP OP_CONCAT预发送|列表OP OP_REMOVE预发送|列表OP OP_COMMON预发送|listOp OP_APPEND前缀列表OpNoBars:prependNoBars|列表OpNoBars OP_CONCAT prependNoBars|列表OpNoBars OP_REMOVE prependNoBars|列表OpNoBars OP_COMMON prependNoBars|列表OpNoBars OP_APPEND prependNoBars预弯:秒|第二个OP_PREPEND预处理prependNo条形图:第条无条|condNoBars OP_PREPEND准备NoBars康德:相对|第二OP_AND相对|第二OP_OR relcondNoBars公司:relNoBars|condNoBars OP_AND相对NoBars|condNoBars OP_OR关系NoBars相对:seq|相关OP_EQ序列|相关OP_NE序列|相关OP_LT序列|相关OP_GT序列|相关OP_LE序列|相关OP_GE序列|相关OP_AEQ序列|相关OP_ANE序列|相关OP_ALT序列|相关OP_AGT序列|相关OP_ALE序列|相关OP_AGE序列|相关OP_IN序列|相关OP_NIN序列relNoBars(无条形图):序列号栏|relNoBars OP_EQ序列NoBars|relNoBars OP_NE序列NoBars|relNoBars OP_LT序列NoBars|relNoBars OP_GT序列NoBars|relNoBars OP_LE序列NoBars|relNoBars OP_GE序列NoBars|relNoBars OP_AEQ序列NoBars|relNoBars OP_ANE序列NoBars|relNoBars OP_ALT序列NoBars|relNoBars OP_AGT序列NoBars|relNoBars OP_ALE序列NoBars|relNoBars OP_AGE序列NoBars|relNoBars OP_IN序列NoBars|relNoBars OP_NIN序列号Bars序列:总和|序列OP_seq总和序列号条:sumNoBars|序列号条OP_SEQ汇总号条总和:产品|OP_ADD产品总和|总和OP_SUB产品|OP_ADD产品|OP_SUB产品|OP_NEG产品汇总无条:productNoBars|sumNoBars OP_ADD产品NoBars|sumNoBars OP_SUB产品NoBars|OP_ADD产品无栏|OP_SUB产品无栏|OP_NEG产品无栏产品:功率|产品OP_MUL电源|产品OP_CROSS电源|产品OP_DIV电源产品编号栏:powerNoBars(无电源线)|productNoBars OP_MUL电源NoBars|产品NoBars OP_CROSS电源NoBars|产品NoBars OP_DIV电源NoBars权力:已索引|索引OP_POW功率|索引SUPSCRIPT|OP_SQRT索引电源NoBars:索引无条|索引NoBars OP_POW功率NoBars|索引NoBars SUPSCRIPT|OP_SQRT索引无栏编入索引的:atom(原子)|函数调用|索引OP_KEY原子|索引OP_FIELD标识符|索引OP_TAKE原子|索引订阅|索引OP_DEG索引无条:原子编号栏|函数调用|索引NoBars OP_KEY原子NoBars|索引NoBars OP_字段标识符|索引无条OP_TAKE原子无条|索引无栏订阅|索引无条OP_DEG原子:ROUND_OPEN表达式ROUND_CLOSE|列表|abs标准偏差|数字|字符串|变量原子无条:ROUND_OPEN表达式ROUND_CLOSE|列表|数字|字符串|变量变量:标识符列表:ROUND_OPEN ROUND_CLOSE(圆形_打开圆形_关闭)|ROUND_OPEN表达式2 ROUND_CLOSE|SQUARE_OPEN表达式0 SQUARE_CLOSE表达式0:%空|表达式|表达式2表达式2:表达式Opt OP_LIST表达式Opt|表达式2 OP_LIST表达式Optabs标准偏差:BAR表达式NoBars BAR|BAR表达式OptNoBars OP_LIST表达式OptNobar BAR函数调用:functionName ROUND_OPEN参数ROUND_CLOSE|functionName SQUARE_OPEN参数SQUARE_CLOSE参数:arg(参数)|参数OP_LIST参数参数:expressionOpt|IDENTIFIER OP_MODIF表达式函数名称:标识符:浮动一串:字符串

相关端子定义如下:

OP_KEY:':';OP_FIELD:“.”;OP_DEG:“°”;OP_TAKE:'_';//也用于内部:=_OP_POW:“^”;OP_SQRT:“√”;操作(_MUL): '*'|“\u2062”//不可见时间|'\u22c5'//●点运算符|'\u00b7'//·中间点OP_CROSS:“×”;OP_DIV(操作_输入): '/'|'\u00f7'//÷除法符号|'\u2215'//¨除法斜线|'\u2236'//∶比率OP_ADD:“+”;OP_SUB:'-'|'−';OP_NEG:'!'|'¬';OP_SEQ:“…”;OP_EQ:'=='|'≟;OP_NE:'!='|'<>'|'≠';OP_LT:“<”;OP_GT:“>”;OP_LE:'≤'|'≤'|'≤';OP_GE:'>='|'≥'|'≥';OP_AEQ:'~='|'≈';OP_ANE:'~!='|'≉';OP_ALT:'~<'|'⪉';OP_AGT:“~>”|“⪊”;OP_ALE:'~<='|'⪅';OP_AGE:'~>='|'⪆';OP_IN:'∈';OP_NIN:“∉”;OP_AND:'&'|'∧';OP_OR:“%”|“∨”;OP_PREPEND:“<:”;OP_APPEND:':>';OP_CONCAT:'++'|'О';OP_REMOVE:“--”|“∖”;OP_COMMON:'~~'|'英寸';OP_ASSIGN:'=';OP_DEFINE:':=';//也用于内部:=_OP_BDEFINE:'::=';OP_SEMI:';';OP_MODIF:'->'|'→';OP_LIST:',';条形图:“|”;ROUND_OPEN:'(';ROUND_CLOSE:')';SQUARE_OPEN:“[”;SQUARE_CLOSE:']';字符串:“”.*?“”浮动:[0-9](WS[0-9])*(WS[.](?![.]))?(WS[Ee](WS[+\-])?(WS[0-9])+)?|([0-9]WS)*[.](WS[0-9])+(WS[Ee](WS[+\-])?(WS[0-9])+)?认购:([₊₋] WS)?[₀õõõ₆₇₈₉](WS)[₀₁₂₃₄₅₆₇₈₉])*超级脚本:([₊₋] WS)?[¹²³⁴⁵⁶⁷⁸⁹] (WS)[¹²³⁴⁵⁶⁷⁸⁹])*标识符:(字母|['])(WS([0-9']|LETTER))*|[#](WS[0-9])?

此列表末尾的非运算符标记可能包含可选的标记内空白操作系统,可以是由以下内容组成的任何序列空格字符和/或水平制表符。它没有语义相关性。

WS:[\t]*;

在标记之间,允许使用以下词汇结构和将被后续处理步骤忽略。

空格:[\t\n]+;SINGLE_LINE_COMMENT:'//'[^\n]*;MULTI_LINE_COMMENT:'/*'(MLC_BODY MULTI_LINE_COMMENT)*MLC_BODY'*'+'/';MLC_BODY:([^/*]|[/]+[^/*]|[*]+[*/*])*;

当然,许多lexer生成器不允许递归标记定义,因此,实现可能需要处理/**/作为单独的代币,并在普通解析模式和注释解析模式之间切换。

如前所述在上面,的信件建造表示具有一般类别的任何代码点L(左)在Unicode 8.0.0标准中。

浮动代币,(?![.])用于表示负数前瞻性断言:此时的下一个字符不能成为第二个点。如果是,第一个点和它前面的任何空白不属于浮动标记。