Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift ANTLR如何决定终端是否应该用空格分隔?_Swift_Antlr_Antlr4_Lexical Analysis_Language Recognition - Fatal编程技术网

Swift ANTLR如何决定终端是否应该用空格分隔?

Swift ANTLR如何决定终端是否应该用空格分隔?,swift,antlr,antlr4,lexical-analysis,language-recognition,Swift,Antlr,Antlr4,Lexical Analysis,Language Recognition,我正在用Swift为Swift编写词汇分析器。我使用了ANTLR的语法,但我面临的问题是,我不明白ANTLR如何决定终端是否应该用空格分隔 语法如下: 假设我们有斯威夫特的演员。它还可以与可选类型(Int?,String?)和非可选类型(Int?,String?)一起操作。这里有一些有效的例子:“as?Int”、“as?Int”、“as?Int”。无效示例:“asInt”(它不是演员阵容)。我已经实现了逻辑,语法规则中的终端可以用0个或更多的WS(空白)符号分隔。但使用此逻辑,“asInt”与强

我正在用Swift为Swift编写词汇分析器。我使用了ANTLR的语法,但我面临的问题是,我不明白ANTLR如何决定终端是否应该用空格分隔

语法如下:

假设我们有斯威夫特的演员。它还可以与可选类型(Int?,String?)和非可选类型(Int?,String?)一起操作。这里有一些有效的例子:“as?Int”、“as?Int”、“as?Int”。无效示例:“asInt”(它不是演员阵容)。我已经实现了逻辑,语法规则中的终端可以用0个或更多的WS(空白)符号分隔。但使用此逻辑,“asInt”与强制转换匹配,因为它包含“as”和类型“Int”,并且具有0个或更多WS符号。但它应该是无效的

Swift语法包含以下规则:

DOT     : '.' ;
LCURLY  : '{' ;
LPAREN  : '(' ;
LBRACK  : '[' ;
RCURLY  : '}' ;
RPAREN  : ')' ;
RBRACK  : ']' ;
COMMA   : ',' ;
COLON   : ':' ;
SEMI    : ';' ;
LT      : '<' ;
GT      : '>' ;
UNDERSCORE : '_' ;
BANG    : '!' ;
QUESTION: '?' ;
AT      : '@' ;
AND     : '&' ;
SUB     : '-' ;
EQUAL   : '=' ;
OR      : '|' ;
DIV     : '/' ;
ADD     : '+' ;
MUL     : '*' ;
MOD     : '%' ;
CARET   : '^' ;
TILDE   : '~' ;
WS : [ \n\r\t\u000B\u000C\u0000]+
a : WS? 'str1' WS? 'str2' WS? '+' WS? 'str3' WS?
我使用它们时,就好像它们是这些规则一样:

DOT     : '.' ;
LCURLY  : '{' ;
LPAREN  : '(' ;
LBRACK  : '[' ;
RCURLY  : '}' ;
RPAREN  : ')' ;
RBRACK  : ']' ;
COMMA   : ',' ;
COLON   : ':' ;
SEMI    : ';' ;
LT      : '<' ;
GT      : '>' ;
UNDERSCORE : '_' ;
BANG    : '!' ;
QUESTION: '?' ;
AT      : '@' ;
AND     : '&' ;
SUB     : '-' ;
EQUAL   : '=' ;
OR      : '|' ;
DIV     : '/' ;
ADD     : '+' ;
MUL     : '*' ;
MOD     : '%' ;
CARET   : '^' ;
TILDE   : '~' ;
WS : [ \n\r\t\u000B\u000C\u0000]+
a : WS? 'str1' WS? 'str2' WS? '+' WS? 'str3' WS?
我想他们应该是这样的(我不知道,这就是问题所在):

(注意,WS在“str1”和“str2”之间不是可选的)

所以有两个问题:

  • 我说得对吗
  • 我错过了什么

  • 谢谢。

    以下是您的Swift语法中的ANTLR
    WS
    规则:

    WS : [ \n\r\t\u000B\u000C\u0000]+               -> channel(HIDDEN) ;
    
    ->channel(HIDDEN)
    指令告诉lexer将这些令牌放在一个单独的通道上,因此解析器根本看不到它们。你不应该把你的语法和
    WS
    规则混在一起-它会变得不可读

    ANTLR分两步工作:您有lexer和解析器。lexer生成标记,解析器试图从这些标记和语法中找出一个具体的语法树

    ANTLR中的lexer的工作原理如下:

    • 只要符合任何lexer规则,就使用字符
    • 如果有多条规则与您使用的文本相匹配,请使用语法中出现的第一条规则
    • 语法中的文字字符串(如
      'as'
      )被转换为隐式lexer规则(相当于
      标记_as:'as';
      ,但名称仅为
      'as'
      )。在lexer规则列表中,这些规则排在第一位
    例1 让我们看看将
    词法转换为?Int
    (末尾有空格)时的后果:

    • a
      。。。可能匹配
      标识符
      'as'
    • 作为
      。。。可能匹配
      标识符
      'as'
    • as?
      与任何lexer规则都不匹配
    因此,您将
    消费为
    ,这将成为令牌。现在,您必须决定哪一种是令牌类型。
    标识符
    'as'
    规则都匹配
    'as'
    是一个隐式的词法规则,被认为在语法中首先出现,因此优先。lexer发出一个类型为
    'as'
    的带有文本
    as
    的令牌

    下一个标记

    • 。。。可能与
      问题
      规则匹配
    • ?I
      与任何规则都不匹配
    因此,您从输入中消费
    ,并发出一个类型为
    QUESTION
    的标记,其中包含文本

    下一个标记

    • I
      。。。可能匹配
      标识符
    • 中的
      。。。可能匹配
      标识符
    • Int
      。。。可能匹配
      标识符
    • Int
      (后跟空格)与任何内容都不匹配
    因此,您从输入中使用
    Int
    ,并发出一个类型为
    Identifier
    的标记,其中包含文本
    Int

    下一个标记

    • 您在那里有一个空格,它与
      WS
      规则匹配
    您使用该空间,并在
    隐藏的
    频道上发出
    WS
    标记。解析器不会看到这一点

    例2 现在让我们看看
    asInt
    是如何标记的

    • a
      。。。可能匹配
      标识符
      'as'
    • 作为
      。。。可能匹配
      标识符
      'as'
    • asI
      。。。可能匹配
      标识符
    • asIn
      。。。可能匹配
      标识符
    • asInt
      。。。可能匹配
      标识符
    • asInt
      后跟空格与任何lexer规则都不匹配
    因此,您从输入流中使用
    asInt
    ,并发出一个带有文本
    asInt
    Identifier
    标记

    解析器 解析器阶段只对它获得的令牌类型感兴趣。它不关心它们包含什么文本。默认通道之外的令牌将被忽略,这意味着以下输入:

    • as?Int
      -令牌:
      'as'
      问题
      标识符
    • as?Int
      -令牌:
      'as'
      问题
      WS
      标识符
    • as?Int
      -令牌:
      'as'
      WS
      问题
      WS
      标识符

    所有这些都将导致解析器看到以下令牌类型:
    'as'
    问题
    标识符
    ,因为
    WS
    在单独的频道上。

    哇,谢谢。我认为lexer和parser规则在创建标记树时是同时工作的。不,它们是解析的不同阶段-这使得这个概念非常容易掌握,同时可以很好地与大多数语言配合使用。但是解析语言需要来自lexer中解析器的信息,这使得解析语言变得很困难。非常感谢!你帮我写了我的工具。以下是输出:我很高兴。很好,我很高兴能帮上忙:)