Parsing 使用lexer和解析器的ANTLR令牌识别错误

Parsing 使用lexer和解析器的ANTLR令牌识别错误,parsing,antlr,antlr4,Parsing,Antlr,Antlr4,我正在编写一个ANTLR词法分析器和语法分析器,它将解析非常类似于Java类的文本。最终,它将解析如下所示的文本: reference schema:"https://schema.org/"; reference dc:"https://www.dublincore.org/"; type dc:Author { } 我正在慢慢地构建Lexer和Parser。我成功地解析了引用s,但在解析类型时遇到了问题 在添加对类型的支持之前我能够在解析器中对空格、冒号和分号使用字符串文本,但在遇到无法

我正在编写一个ANTLR词法分析器和语法分析器,它将解析非常类似于Java类的文本。最终,它将解析如下所示的文本:

reference schema:"https://schema.org/";
reference dc:"https://www.dublincore.org/";

type dc:Author {
}
我正在慢慢地构建Lexer和Parser。我成功地解析了
引用
s,但在解析
类型
时遇到了问题

在添加对
类型的支持之前
我能够在解析器中对空格、冒号和分号使用字符串文本,但在遇到
无法为字符串文本创建隐式标记
错误之后。我为每个字符定义了一个lexer规则,并用该规则替换了所有出现的文本。然而,这破坏了
reference
s的解析

我已经在下面介绍了成功解析
reference
s的lexer和parser(还有一个示例输入和解析的抽象语法树)以及不起作用的改进版本。我没有收到任何编译错误,但有大量的
令牌识别错误
s(下面包括屏幕截图)

处理解析的正确方法是什么

工作 雷克瑟 分析器 输入 输出

进化(不工作) 雷克瑟 分析器 输出


接下来,我对lexer和parser语法进行了两次更新,并取得了不同的成功

第一次更新 此更改正确解析类型定义,但前提是删除lexer规则以供参考。我认为这是因为这两个规则是相同的(即
带前缀的\u REFERENCE:SPACE->pushMode(PrefixedReferenceMode);
用于引用和
带前缀的\u NAME:SPACE->pushMode(PrefixedNameMode);
用于类型)——也就是说,它们都在一个空间上匹配。我的第二次更新试图解决这个问题,但是下面是完整的lexer和parser语法

雷克瑟 分析器 第二次更新 为了解决这个问题,我将
reference
type
关键字移动到对应部分的Lexer规则中,但这仅在删除所有Lexer规则以供参考时解析类型。但是,引用被正确解析

雷克瑟 分析器 输出 对于以下输入:

reference schema:"https://schema.org/";
reference dc:"https://www.dublincore.org/";

type dc:Author;
这是输出:

line 4:0 token recognition error at: 't'
line 4:1 token recognition error at: 'y'
line 4:2 token recognition error at: 'p'
line 4:3 token recognition error at: 'e'
line 4:4 token recognition error at: ' '
line 4:5 token recognition error at: 'd'
line 4:6 token recognition error at: 'c'
line 4:7 token recognition error at: ':'
line 4:8 token recognition error at: 'A'
line 4:9 token recognition error at: 'u'
line 4:10 token recognition error at: 't'
line 4:11 token recognition error at: 'h'
line 4:12 token recognition error at: 'o'
line 4:13 token recognition error at: 'r;'
我使用模式的理由是限制规则的范围。这是一种我可以控制的语言,但我不希望对其进行太大的更改。这种语言比我在这里展示的要多得多,我们已经有了语法(目前是组合语法),但它非常脆弱。我试图做一个改变,以防止前缀中出现大写字符,但允许它们出现在本地名称中,但这滚雪球和其他规则开始应用。研究表明,模式是处理这种情况的一种方法,但我对ANTLR不太熟悉,所以我可能误解了它


遇到以下错误/警告时:

line 4:0 token recognition error at: 't'
line 4:1 token recognition error at: 'y'
line 4:2 token recognition error at: 'p'
line 4:3 token recognition error at: 'e'
...
这意味着lexer无法为输入构造令牌(
type…
)。在您的情况下,这意味着lexer无法以当时的模式从输入创建令牌

我试图做一个改变,以防止前缀中出现大写字符,但允许它们出现在本地名称中,但这滚雪球和其他规则开始应用

解决此类问题有两种选择:

  • 只需像解析任何普通标识符一样解析前缀(大写或小写),解析后,遍历生成的解析树,并使用ANTLR访问者或侦听器验证前缀标识符是否真正小写(请参阅:)
  • 在lexer中区分大小写标识符,并在解析器规则中相应地使用它们,类似这样的方法可能会奏效:

  • 模式是用来输入两种(或更多)语言的。例如解析HTML文件:有内容(文本)和带有属性的标记。依我看,你并不是在使用它,因为它是用来使用的,我想。

    这太完美了,非常感谢你的帮助,还问了一个问题:“你到底想解决什么?”。
    lexer grammar NotWorkingLexerGrammar;
    
    WS: ('\t' | '\n' | '\r' )+ -> skip ;
    
    fragment Colon : ':';
    fragment SemiColon: ';';
    fragment Underscores: '_'+ ;
    fragment Digits: [0-9]+ ;
    fragment LowercaseLetters: [a-z]+ ;
    fragment UppercaseLetters: [A-Z]+ ;
    fragment String: '"' .*? '"' ;
    fragment Prefix: (Underscores | Digits | LowercaseLetters)+ ;
    
    COLON: Colon;
    SEMICOLON: SemiColon;
    SPACE: ' ';
    
    REFERENCE_KEYWORD: 'reference' ;
    TYPE_KEYWORD: 'type' ;
    
    PREFIXED_REFERENCE: SPACE -> pushMode(PrefixedReferenceMode) ;
    
    mode PrefixedReferenceMode;
    REFERENCE_PREFIX: Prefix;
    REFERENCE_PREFIX_SEPARATOR: COLON -> pushMode(IriMode);
    END_IRI: SEMICOLON -> popMode;
    
    mode IriMode;
    IRI: String  -> popMode;
    
    PREFIXED_NAME: SPACE -> pushMode(PrefixedNameMode) ;
    
    mode PrefixedNameMode;
    NAME_PREFIX: Prefix;
    NAME_PREFIX_SEPARATOR: COLON -> pushMode(LocalNameMode);
    END_NAME: SEMICOLON -> popMode;
    
    mode LocalNameMode;
    LOCAL_NAME: (Underscores | Digits | LowercaseLetters | UppercaseLetters)+  -> popMode;
    
    parser grammar NotWorkingParserGrammar ;
    
    options { tokenVocab=NotWorkingLexerGrammar; }
    
    document: reference* type* EOF ;
    
    prefixedReference: REFERENCE_PREFIX COLON IRI;
    reference: REFERENCE_KEYWORD SPACE prefixedReference SEMICOLON;
    
    prefixedName: NAME_PREFIX SPACE LOCAL_NAME;
    type: TYPE_KEYWORD SPACE prefixedName;
    
    lexer grammar NotWorkingLexerGrammar;
    
    WS: ('\t' | '\n' | '\r' )+ -> skip ;
    
    fragment Underscores: '_'+ ;
    fragment Digits: [0-9]+ ;
    fragment LowercaseLetters: [a-z]+ ;
    fragment UppercaseLetters: [A-Z]+ ;
    fragment String: '"' .*? '"' ;
    fragment Prefix: (Underscores | Digits | LowercaseLetters)+ ;
    
    fragment COLON: ':';
    fragment SEMICOLON: ';';
    fragment SPACE: ' ';
    
    fragment REFERENCE_KEYWORD: 'reference' ;
    fragment TYPE_KEYWORD: 'type' ;
    
    PREFIXED_REFERENCE: SPACE -> pushMode(PrefixedReferenceMode) ;
    
    mode PrefixedReferenceMode;
    REFERENCE_PREFIX: Prefix;
    REFERENCE_PREFIX_SEPARATOR: COLON -> pushMode(IriMode);
    END_IRI: SEMICOLON -> popMode;
    
    mode IriMode;
    IRI: String  -> popMode;
    
    PREFIXED_NAME: SPACE -> pushMode(PrefixedNameMode) ;
    
    mode PrefixedNameMode;
    NAME_PREFIX: Prefix;
    NAME_PREFIX_SEPARATOR: COLON -> pushMode(LocalNameMode);
    END_NAME: SEMICOLON -> popMode;
    
    mode LocalNameMode;
    LOCAL_NAME: (Underscores | Digits | LowercaseLetters | UppercaseLetters)+  -> popMode;
    
    parser grammar NotWorkingParserGrammar ;
    
    options { tokenVocab=NotWorkingLexerGrammar; }
    
    document: reference* type* EOF ;
    
    prefixedReference: REFERENCE_PREFIX REFERENCE_PREFIX_SEPARATOR IRI;
    reference: REFERENCE_KEYWORD PREFIXED_REFERENCE prefixedReference END_IRI;
    
    prefixedName: NAME_PREFIX NAME_PREFIX_SEPARATOR LOCAL_NAME;
    type: TYPE_KEYWORD PREFIXED_NAME prefixedName END_NAME;
    
    lexer grammar NotWorkingLexerGrammar;
    
    WS: ('\t' | '\n' | '\r' )+ -> skip ;
    
    fragment Underscores: '_'+ ;
    fragment Digits: [0-9]+ ;
    fragment LowercaseLetters: [a-z]+ ;
    fragment UppercaseLetters: [A-Z]+ ;
    fragment String: '"' .*? '"' ;
    fragment Prefix: (Underscores | Digits | LowercaseLetters)+ ;
    
    fragment COLON: ':';
    fragment SEMICOLON: ';';
    fragment SPACE: ' ';
    
    fragment REFERENCE_KEYWORD: 'reference' ;
    fragment TYPE_KEYWORD: 'type' ;
    
    PREFIXED_REFERENCE: REFERENCE_KEYWORD SPACE -> pushMode(PrefixedReferenceMode) ;
    
    mode PrefixedReferenceMode;
    REFERENCE_PREFIX: Prefix;
    REFERENCE_PREFIX_SEPARATOR: COLON -> pushMode(IriMode);
    END_IRI: SEMICOLON -> popMode;
    
    mode IriMode;
    IRI: String  -> popMode;
    
    TYPE_DEFINITION: TYPE_KEYWORD SPACE -> pushMode(PrefixedNameMode) ;
    
    mode PrefixedNameMode;
    NAME_PREFIX: Prefix;
    NAME_PREFIX_SEPARATOR: COLON -> pushMode(LocalNameMode);
    END_NAME: SEMICOLON -> popMode;
    
    mode LocalNameMode;
    LOCAL_NAME: (Underscores | Digits | LowercaseLetters | UppercaseLetters)+  -> popMode;
    
    parser grammar NotWorkingParserGrammar ;
    
    options { tokenVocab=NotWorkingLexerGrammar; }
    
    document: reference* type* EOF ;
    
    prefixedReference: REFERENCE_PREFIX REFERENCE_PREFIX_SEPARATOR IRI;
    reference: PREFIXED_REFERENCE prefixedReference END_IRI;
    
    prefixedName: NAME_PREFIX NAME_PREFIX_SEPARATOR LOCAL_NAME;
    type: TYPE_DEFINITION prefixedName END_NAME;
    
    reference schema:"https://schema.org/";
    reference dc:"https://www.dublincore.org/";
    
    type dc:Author;
    
    line 4:0 token recognition error at: 't'
    line 4:1 token recognition error at: 'y'
    line 4:2 token recognition error at: 'p'
    line 4:3 token recognition error at: 'e'
    line 4:4 token recognition error at: ' '
    line 4:5 token recognition error at: 'd'
    line 4:6 token recognition error at: 'c'
    line 4:7 token recognition error at: ':'
    line 4:8 token recognition error at: 'A'
    line 4:9 token recognition error at: 'u'
    line 4:10 token recognition error at: 't'
    line 4:11 token recognition error at: 'h'
    line 4:12 token recognition error at: 'o'
    line 4:13 token recognition error at: 'r;'
    
    line 4:0 token recognition error at: 't'
    line 4:1 token recognition error at: 'y'
    line 4:2 token recognition error at: 'p'
    line 4:3 token recognition error at: 'e'
    ...
    
    document
     : reference* type* EOF
     ;
    
    reference
     :  K_REFERENCE LOWER_ID COL STRING SCOL
     ;
    
    type
     : K_TYPE LOWER_ID COL id OPAR CPAR
     ;
    
    id
     : LOWER_ID
     | ID
     ;
    
    K_REFERENCE : 'reference';
    K_TYPE      : 'type';
    LOWER_ID    : [a-z_] [a-z_0-9]*;
    ID          : [a-zA-Z_] [a-zA-Z_0-9]*;
    STRING      : '"' ~["]* '"';
    SCOL        : ';';
    COL         : ':';
    OPAR        : '{';
    CPAR        : '}';
    SPACES      : [ \t\r\n] -> skip;