添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

M 文档是 Unicode 字符的有序序列。 M 允许在 M 文档的不同部分使用不同类别的 Unicode 字符。 有关 Unicode 字符类的信息,请参阅 Unicode 标准,版本 3.0 中的第 4.5 节。

文档要么由一个表达式组成,要么由组织成节的多组定义构成 。 第 10 章对节进行了详细说明。 从概念上讲,以下步骤用于从文档中读取表达式:

  • 文档根据其字符编码方案被解码为一个 Unicode 字符序列。

  • 执行词法分析,从而将 Unicode 字符流转换为令牌流。 本节余下的小节将介绍词法分析。

  • 执行词法分析,从而将令牌流转换为可计算的形式。 后续部分将介绍此过程。

    词法和句法用文法产生式来表示。 每个文法产生式定义一个非终端符号,以及该非终端符号可能扩展成一系列非终端或终端符号。 在文法产生式中,非终端+ 符号以斜体显示,终端符号以固定宽度字体显示。

    文法产生式的第一行是定义的非终端符号的名称,后跟冒号。 每一个后续缩进行都包含一个非终端符的可能扩展,该非终端符由一系列非终端符或终端符符号组成。 例如,产生式:

    if-expression:
    if if-condition then true-expression else false-expression

    定义一个 if-expression ,由令牌 if 后跟 if-condition ,令牌 then 后跟 true-expression 以及令牌 else 后跟 false-expression 组成。

    当非终端符号有多个可能的扩展时,替代项在单独的行中列出。 例如,产生式:

    variable-list:
    variable-list
    , variable

    定义一个 variable-list 由一个变量或 variable-list 后跟 variable 组成 。 换言之,这个定义是递归的,它指定变量列表由一个或多个(用逗号分隔的)变量组成。

    下标后缀“ opt ”用于指示可选符号。 产生式:

    field-specification:
    optional opt field-name = field-type

    为以下的简写:

    field-specification:
    field-name
    = field-type
    optional field-name = field-type

    并定义了 field-specification 可选地以终端符号 optional 开头,后跟 field-name、终端符号 = 和 field-type 。

    替代项通常在单独的行中列出,但在有许多替代项的情况下,“one of”一词可能出现在单行上给出的一列扩展之前。 这只是对在单独的行中列出每个替代项的简化。 例如,产生式:

    decimal-digit: one of
    0 1 2 3 4 5 6 7 8 9

    为以下的简写:

    decimal-digit:

    lexical-unit 产生式定义了 M 文档的词法语法。 每个有效的 M 文档都遵循此语法。

    lexical-unit:
    lexical-elements opt
    lexical-elements:
    lexical-element
    lexical-element
    lexical-elements
    lexical-element:
    whitespace
    token comment

    在词法级别,M 文档由一系列空白、注释和令牌元素组成 。 以下各节将介绍这些产生式。 在语法中,只有令牌元素是有意义的。

    空格用于分隔 M 文档中的注释和令牌。 空格包括空格字符(它是 Unicode 类 Zs 的一部分),以及水平和垂直制表符、换页符和换行符序列。 换行字符序列包括回车符、换行符、后跟换行符的回车符、下一行和段落分隔符。

    带有 Unicode 类 Zs 的任何字符
    水平制表符字符 ( U+0009 )
    垂直制表符 ( U+000B )
    换页符 ( U+000C )
    后跟换行符 ( U+000A ) 的回车符 ( U+000D )
    new-line-character
    new-line-character
    回车符 ( U+000D )
    换行符 ( U+000A )
    换行符 ( U+0085 )
    行分隔符 ( U+2028 )
    段落分隔符 ( U+2029 )

    为了与添加 end-of-file 标记的源代码编辑工具兼容,并使文档能够被看作正确终止的行序列,将按顺序对 M 文档应用以下转换:

  • 如果文档的最后一个字符是 Control-Z 字符 ( U+001A ),则删除此字符。

  • 如果文档非空并且文档的最后一个字符不是回车符 ( U+000D )、换行符 ( U+000A )、行分隔符 ( U+2028 ) 或段落分隔符 ( U+2029 ),则在文档末尾添加回车符 ( U+000D )。

    支持两种形式的注释:单行注释和分隔注释。 S 注释以字符 // 开头,并扩展到源行的末尾。 分隔注释以字符 /* 开头,以字符 */ 结尾。

    分隔注释可能跨多行。

    comment:
    single-line-comment
    delimited-comment
    single-line-comment:

    // single-line-comment-characters opt
    single-line-comment-characters:
    single-line-comment-character single-line-comment-characters opt
    single-line-comment-character:

    new-line-character 之外的任何 Unicode 字符
    delimited-comment:

    /* delimited-comment-text opt asterisks /
    delimited-comment-text:
    delimited-comment-section delimited-comment-text opt
    delimited-comment-section:

    asterisks opt not-slash-or-asterisk
    asterisks:

    * asterisks opt
    not-slash-or-asterisk:

    * / 之外的任何 Unicode 字符

    注释不嵌套。 字符序列 /* */ 在单行注释中没有特殊含义,字符序列 // /* 在分隔注释中没有特殊含义。

    不在文字串中处理注释。 示例

    /* Hello, world 
        "Hello, world"
    

    包含分隔注释。

    // Hello, world 
    "Hello, world" // This is an example of a text literal
    

    显示若干单行注释。

    令牌是标识符、关键字、文字、运算符或标点符号。 空白和注释用于分隔标记,但不会将其视为令牌。

    token:
          关键字 (keyword)
          operator-or-punctuator

    字符转义序列

    M 文本值可以包含任意 Unicode 字符。 然而,文字文本仅限于图形字符,需要对非图形字符使用转义序列。 例如,要在文字文本中包含回车符、换行符或制表符,可以分别使用 #(cr)#(lf)#(tab) 转义序列。 若要在文字文本中嵌入转义序列开始字符 #(# 本身需要进行转义:

    #(#)(
    

    转义序列也可以包含短(四个十六进制数字)或长(八个十六进制数字)Unicode 码位值。 因此,以下三个转义序列是等效的:

    #(000D)     // short Unicode hexadecimal value 
    #(0000000D) // long Unicode hexadecimal value 
    #(cr)       // compact escape shorthand for carriage return
    

    单个转义序列中可以包含多个转义码,用逗号分隔;因此,以下两个序列是等效的:

    #(cr,lf) 
    #(cr)#(lf)
    

    下面介绍 M 文档中字符转义的标准机制。

    character-escape-sequence:
          #(escape-sequence-list)
    escape-sequence-list:
          single-escape-sequence
          single-escape-sequence
    ,escape-sequence-list
    single-escape-sequence:
          long-unicode-escape-sequence
          short-unicode-escape-sequence
          control-character-escape-sequence
          escape-escape
    long-unicode-escape-sequence:
          hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit
    short-unicode-escape-sequence:
          hex-digit hex-digit hex-digit hex-digit
    control-character-escape-sequence:
          control-character
    control-character:

    escape-escape:

    文本是值的源代码表示形式。

    literal:
          logical-literal
          number-literal
          text-literal
          null-literal
          verbatim-literal

    null 文本

    null 文本用于写入 null 值。 null 值表示不存在的值。

    null-literal:

    逻辑文本用于写入值 truefalse,并生成逻辑值。

    logical-literal:
          false

    数字文字用于写入数值并生成数值。

    number-literal:
          decimal-number-literal
          hexadecimal-number-literal
    decimal-number-literal:
          decimal-digits
    .decimal-digits exponent-partopt
          .decimal-digits exponent-partopt
          decimal-digits exponent-partopt
    decimal-digits:
          decimal-digit decimal-digitsopt
    decimal-digit:
    one of
          0 1 2 3 4 5 6 7 8 9
    exponent-part:
          esignopt decimal-digits
          Esignopt decimal-digits
    sign:
    one of
    hexadecimal-number-literal:
          0xhex-digits
          0Xhex-digits
    hex-digits:
          hex-digit hex-digitsopt
    hex-digit:
    one of
          0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f

    通过在十六进制数字前面加上字符 0x,可以十六进制格式指定一个数字。 例如:

    0xff // 255
    

    请注意,如果数字文本中包含小数点,则它后面必须至少有一个数字。 例如,1.3 是数字文本,但 1.1.e3 不是。

    文本文字用于写入 Unicode 字符序列并生成文本值。

    text-literal:
          "text-literal-charactersopt"
    text-literal-characters:
          text-literal-character text-literal-charactersopt
    text-literal-character:
          single-text-character
          character-escape-sequence
          double-quote-escape-sequence
    single-text-character:

          除后跟 ( (U+0028) 的 " (U+0022) 或 # (U+0023) 外的任何字符
    double-quote-escape-sequence:
          "" (U+0022, U+0022)

    若要在文本值中包含引号,请重复使用引号,如下所示:

    "The ""quoted"" text" // The "quoted" text
    

    可使用 character-escape-sequence 产生式在文本值中写入字符,而无需在文档中将它们直接编码为 Unicode 字符。 例如,回车和换行可以用文本值写入:

    "Hello world#(cr,lf)"
    

    逐字文本用于存储用户作为代码输入但无法正确分析为代码的 Unicode 字符序列。 在运行时,它会生成一个错误值。

    verbatim-literal:
          #!"text-literal-charactersopt"

    标识符是用于引用值的名称。 标识符可以是常规标识符,也可以是带引号的标识符。

    identifier:
          regular-identifier
          quoted-identifier
    regular-identifier:
          available-identifier
          available-identifier dot-character regular-identifier
    available-identifier:

          不是 keyword 的 keyword-or-identifier
    keyword-or-identifier:
          identifier-start-character identifier-part-charactersopt
    identifier-start-character:
          letter-character
          underscore-character
    identifier-part-characters:
          identifier-part-character identifier-part-charactersopt
    identifier-part-character:
          letter-character
          decimal-digit-character
          underscore-character
          connecting-character
          combining-character
          formatting-character
    dot-character:

          . (U+002E)
    underscore-character:
          _ (U+005F)
    letter-character:
          Lu、Ll、Lt、Lm、Lo 或 Nl 类的 Unicode 字符
    combining-character:
          Mn 或 Mc 类的 Unicode 字符
    decimal-digit-character:
          Nd 类的 Unicode 字符
    connecting-character:
          Pc 类的 Unicode 字符
    formatting-character:
          Cf 类的 Unicode 字符

    带引号的标识符可用于允许零个或多个 Unicode 字符的任何序列用作标识符,包括关键字、空格、注释、运算符和标点符号。

    quoted-identifier:
          #"text-literal-charactersopt"

    注意,转义序列和用于转义引号的双引号可以在带引号的标识符中使用,就像在 text-literal 中一样 。

    以下示例对包含空格字符的名称使用标识符引号:

    #"1998 Sales" = 1000, #"1999 Sales" = 1100, #"Total Sales" = #"1998 Sales" + #"1999 Sales"

    以下示例使用标识符引号将 + 运算符包含在标识符中:

    #"A + B" = A + B, A = 1, B = 2

    通用化标识符

    在 M 中有两个地方没有由包含空格或关键字或数字文字的标识符引起的歧义。 这些位置是记录文本中记录字段的名称,在字段访问运算符 ([ ]) 中,M 允许这样的标识符,而不必使用带引号的标识符。

    Data = [ Base Line = 100, Rate = 1.8 ], Progression = Data[Base Line] * Data[Rate]

    用于命名和访问字段的标识符称为通用标识符,定义如下:

    generalized-identifier:
          generalized-identifier-part
          generalized-identifier
    separated only by blanks (U+0020)
    generalized-identifier-part
    generalized-identifier-part:
          generalized-identifier-segment
          decimal-digit-character generalized-identifier-segment
    generalized-identifier-segment:
          keyword-or-identifier
          keyword-or-identifier dot-character keyword-or-identifier

    关键字是保留的类似标识符的字符序列,不能用作标识符,除非使用标识引用机制允许使用通用标识符

    keyword: one of
           and as each else error false if in is let meta not null or otherwise
           section shared then true try type #binary #date #datetime
           #datetimezone #duration #infinity #nan #sections #shared #table #time

    运算符和标点符号

    有多种运算符和标点符号。 表达式中使用运算符来描述涉及一个或多个操作数的操作。 例如,表达式 a + b 使用 + 运算符添加两个操作数 ab。 标点符号用于分组和分隔。

    operator-or-punctuator: one of
          , ; = < <= > >= <> + - * / & ( ) [ ] { } @ ! ? ?? => .. ...

    即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:https://aka.ms/ContentUserFeedback

    提交和查看相关反馈

  •