Skip to content

Latest commit

 

History

History
63 lines (46 loc) · 3.5 KB

0X07定义Lua(3).md

File metadata and controls

63 lines (46 loc) · 3.5 KB

0X07 定义 Lua (3)

这一节会对之前用到的的一些零件进行定义.其中数字,字符串字面值等,其实很多编程语言的写法都是类似的.

注意,这一部分语法 Lua 标准只给了描述性定义.这一部分的语法规则都是我根据 Lua 官网上

字符串字面值

LiteralString = LString1 | LString2 | LString3 ;
LString1 = "'", {Char1}, "'";
LString2 = '"', {Char2}, '"';
Char1 = CharSet - "'";
Char2 = CharSet - '"';

第三种字符串字面值(可以直接用换行符的那种)比较麻烦.因为它事实上包含无数个定界符(等号的数量可以无限增加).EBNF可以轻松包括任意长度的字符串,但是麻烦在于首尾的等号个数要相等.这也是难以仅仅从语法层面不依赖任何语义分析解决的.(另外注意,第三种字符串的字符集中包括换行符.)

如果要包含这无数个定界符,就需要定义无穷个名词.可以考虑用转义串描述性定义.

严格来说 Lua 的第三种字符串字面值是上下文相关文法.因为 ]===] 是不是一个字符串的定界符,要看它之前有没有 [===[.这里我给出一种定义,在这个定义中解决了首尾定界符等号个数配对的问题,但是解决不了用到的StringCore的定义问题.

LString3 = '[', StringCore2, ']';
StringCore2 = StringCore1 | '=', StringCore2, '=';
StringCore1 = '[', StringCore, ']';

这里的 StringCore 中使用字符其实比 LString1 和 LString2 都要自由.它可以是任何不包含右定界符(]], ]=],]==] 等)的字符串.但是具体不包含的是哪个定界符,是由前文中的左定界符种类决定的.而且更麻烦的是其实左右定界符有无数对.如果 Lua 中限定左右定界符是有限对的话,其实还是可以不厌其烦地写出每条排除规则然后通过 EBNF 定义这种字符串的.

数字字面值

数字的字面值定义其实也比较复杂,但是我们一般常用的十进制数字还是比较容易构造的.以下给出 Lua 中数字字面值的定义:

Numeral = Base10 | Base16;
Base10 = Base10Int, ['.', Base10Int], [Base10Power, Base10Int];
Base10Int = Base10Char, {Base10Char};
Base10Power = 'e' | 'E';
Base10Char = Digit;
Base16 = ('0X' | '0x'), Base16Int, ['.', Base16Int], [Base16Power, Base16Int];
Base16Int = Base16Char, {Base16Char};
Base16Power = 'p' | 'P';
Base16Char = Digit | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';

字符集定义

CharSet = Letter | Digit | Symbol | Space;
Letter = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' |i|j| 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
Symbol = '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')' | "'" | '"' | ',' | '.' | '<' | '>' | '-' | '_' | '=' | '+' | '`' | '~' | '{' | '}' | '[' | ']' | '/' | '?' | '\' | '|' | ';' | ':';
Space = ' '

以上包括了 ASCII 中的所有 95 个可打印字符(包括空格).其实水平制表符也可以用于 Lua 的字符串,但是考虑到很多编辑器中会把 tab 自动转换成若干个空格,而且这个符号本身的名字不太好写,我这里没有包括这个字符.(其实非可打印字符严格来说就不可能用可打印字符串定义.最后都要归结到引用串上.)