Parsing 为什么antlr4将我的句子解析为两个语句?

Parsing 为什么antlr4将我的句子解析为两个语句?,parsing,antlr,whitespace,grammar,antlr4,Parsing,Antlr,Whitespace,Grammar,Antlr4,我正在为表达式编写一个小解析器。目前,我只想让它识别二进制乘法(myId*myId)和类C的去引用指针(*myId),再加上一些赋值语句(myId*=myId) 使解析器抛出错误的输入是: x *= y; 。。。解析器在其上失败,并显示此消息和解析树: [line 1:1 mismatched input ' *' expecting {';', NEWLINE}] (sourceFile (statement (expressionStatement (expression (monoOpe

我正在为表达式编写一个小解析器。目前,我只想让它识别二进制乘法(myId*myId)和类C的去引用指针(*myId),再加上一些赋值语句(myId*=myId)

使解析器抛出错误的输入是:

x *= y;
。。。解析器在其上失败,并显示此消息和解析树:

[line 1:1 mismatched input ' *' expecting {';', NEWLINE}]
(sourceFile (statement (expressionStatement (expression (monoOperatedExpression (atomicExpression x))))  * =  ) (statement (expressionStatement (expression (monoOperatedExpression (atomicExpression y)))) ;) <EOF>)
[行1:1不匹配的输入'*'应为{';',换行符}]
(源文件(语句(表达式语句(表达式(单操作表达式(原子表达式x)))*=)(语句(表达式语句(表达式(单操作表达式(原子表达式y)));)
我挠头已经有一段时间了,但我看不出我的语法有什么错误(见下文)。有什么提示吗?提前谢谢

grammar Sable;

options {}

@header {
    package org.sable.parser;
}

ASSIGNMENT_OP:
    '='
    ;

BINARY_OP:
    '*'
    ;

WS_BUT_NOT_NEWLINE:
    WhiteSpaceButNotNewLineCharacter
    ;

NEWLINE:
    ('\u000D' '\u000A')
    | '\u000A'
    ;

WSA_BINARY_OP:
    (WS_BUT_NOT_NEWLINE+ BINARY_OP WS_BUT_NOT_NEWLINE+)
    | BINARY_OP
    ;

WSA_PREFIX_OP:
    (WS_BUT_NOT_NEWLINE+ '*' )
    ;

WS  :  WhiteSpaceCharacter+ -> skip
    ;

IDENTIFIER:
    (IdentifierHead IdentifierCharacter*)
    | ('`'(IdentifierHead IdentifierCharacter*)'`')
    ;

// NOTE: a file with zero statements is allowed because
// it can contain just comments.
sourceFile:
    statement* EOF;

statement:
    expressionStatement (';' | NEWLINE);

// Req. not existing any valid expression starting from
// an equals sign or any other assignment operator.
expressionStatement:
    expression (assignmentOperator expression)?;

expression:
    monoOperatedExpression (binaryOperator monoOperatedExpression)?
    ;

monoOperatedExpression:
    atomicExpression
    ;

binaryOperator:
    WSA_BINARY_OP
    ;

atomicExpression:
    IDENTIFIER ('<' type (',' type)* '>')? //TODO: can this be a lsv?
    ;

type:
    IDENTIFIER
    ;

assignmentOperator:
    ASSIGNMENT_OP
    ;

fragment DecimalDigit:
    '0'..'9'
    ;

fragment IdentifierHead:
    'a'..'z'
    | 'A'..'Z'
    ;
fragment IdentifierCharacter:
    DecimalDigit
    | IdentifierHead
    ;

fragment WhiteSpaceCharacter:
    WhiteSpaceButNotNewLineCharacter
    | NewLineCharacter;

fragment WhiteSpaceButNotNewLineCharacter:
    [\u0020\u000C\u0009u000B\u000C]
    ;

fragment NewLineCharacter:
    [\u000A\u000D]
    ;
语法;
选项{}
@标题{
包org.sable.parser;
}
作业(OP):
'='
;
二进制运算:
'*'
;
WS_但_非_新行:
空白但不换行字符
;
新行:
(“\u000D”\u000A”)
|“\u000A”
;
WSA_二进制运算:
(WS_但非NEWLINE+二进制操作WS_但非NEWLINE+)
|二进制运算
;
WSA_前缀_OP:
(WS_但不是新行+'*')
;
WS:WhiteSpaceCharacter+->skip
;
标识符:
(IdentifierHead IdentifierCharacter*)
|('`'(IdentifierHead IdentifierCharacter*)'`')
;
//注意:允许使用零语句的文件,因为
//它可以只包含注释。
源文件:
报表*EOF;
声明:
表达式语句(“;”|换行符);
//请求。不存在任何从开始的有效表达式
//等号或任何其他赋值运算符。
表达声明:
表达式(赋值运算符表达式)?;
表达方式:
monoOperatedExpression(二进制运算符monoOperatedExpression)?
;
单操作表达式:
原子表达式
;
二进制运算符:
WSA_二进制运算
;
原子表达式:
标识符(“”)//托多:这是lsv吗?
;
类型:
标识符
;
转让经营人:
作业
;
片段小数位数:
'0'..'9'
;
碎片识别头:
“a”…“z”
|“A”…“Z”
;
片段标识符字符:
小数位数
|识别头
;
片段空白字符:
空白但不换行字符
|换行符;
片段WhiteSpaceButNotNewLineCharacter:
[\u0020\u000C\u0009u000B\u000C]
;
片段换行符:
[\u000A\u000D]
;
编辑:应评论员的请求添加新版本的语法

grammar Sable;

options {}

@header {
    package org.sable.parser;
}

//
// PARSER RULES.

sourceFile              : statement* EOF;
statement               : expressionStatement (SEMICOLON | NEWLINE);
expressionStatement     : expression (ASSIGNMENT_OPERATOR expression)?;

expression:
    expression WSA_OPERATOR expression
    | expression OPERATOR expression
    | OPERATOR expression
    | expression OPERATOR
    | atomicExpression
    ;

atomicExpression:
    IDENTIFIER ('<' type (',' type)* '>')? //TODO: can this be a lsv?
    ;

type                    : IDENTIFIER;


//
// LEXER RULES.

COMMENT                 : '/*' .*? '*/'                    -> channel(HIDDEN);
LINE_COMMENT            : '//' ~[\000A\000D]*              -> channel(HIDDEN);

ASSIGNMENT_OPERATOR     : Operator? '=';

// WSA = White Space Aware token.
// These are tokens that occurr in a given whitespace context.
WSA_OPERATOR:
    (WhiteSpaceNotNewline+ Operator WhiteSpaceNotNewline+)
    ;

OPERATOR         : Operator;

// Newline chars are defined apart because they carry meaning as a statement
// delimiter.
NEWLINE:
    ('\u000D' '\u000A')
    | '\u000A'
    ;

WS                      : WhiteSpaceNotNewline -> skip;

SEMICOLON               : ';';


IDENTIFIER:
    (IdentifierHead IdentifierCharacter*)
    | ('`'(IdentifierHead IdentifierCharacter*)'`')
    ;

fragment DecimalDigit   :'0'..'9';

fragment IdentifierHead:
    'a'..'z'
    | 'A'..'Z'
    | '_'
    | '\u00A8'
    | '\u00AA'
    | '\u00AD'
    | '\u00AF' |
    '\u00B2'..'\u00B5' |
    '\u00B7'..'\u00BA'  |
    '\u00BC'..'\u00BE' |
    '\u00C0'..'\u00D6' |
    '\u00D8'..'\u00F6' |
    '\u00F8'..'\u00FF' |
    '\u0100'..'\u02FF' |
    '\u0370'..'\u167F' |
    '\u1681'..'\u180D' |
    '\u180F'..'\u1DBF' |
    '\u1E00'..'\u1FFF' |
    '\u200B'..'\u200D' |
    '\u202A'..'\u202E' |
    '\u203F'..'\u2040' |
    '\u2054' |
    '\u2060'..'\u206F' |
    '\u2070'..'\u20CF' |
    '\u2100'..'\u218F' |
    '\u2460'..'\u24FF' |
    '\u2776'..'\u2793' |
    '\u2C00'..'\u2DFF' |
    '\u2E80'..'\u2FFF' |
    '\u3004'..'\u3007' |
    '\u3021'..'\u302F' |
    '\u3031'..'\u303F' |
    '\u3040'..'\uD7FF' |
    '\uF900'..'\uFD3D' |
    '\uFD40'..'\uFDCF' |
    '\uFDF0'..'\uFE1F' |
    '\uFE30'..'\uFE44' |
    '\uFE47'..'\uFFFD'
    ;
fragment IdentifierCharacter:
    DecimalDigit
    | '\u0300'..'\u036F'
    | '\u1DC0'..'\u1DFF'
    | '\u20D0'..'\u20FF'
    | '\uFE20'..'\uFE2F'
    | IdentifierHead
    ;
// Non-newline whitespaces are defined apart because they carry meaning in
// certain contexts, e.g. within space-aware operators.
fragment WhiteSpaceNotNewline    : [\u0020\u000C\u0009u000B\u000C];

fragment Operator:
    '*'
    | '/'
    | '%'
    | '+'
    | '-'
    | '<<'
    | '>>'
    | '&'
    | '^'
    | '|'
    ;
语法;
选项{}
@标题{
包org.sable.parser;
}
//
//解析器规则。
sourceFile:statement*EOF;
语句:expressionStatement(分号|换行符);
表达式语句:表达式(赋值运算符表达式)?;
表达方式:
表达式WSA_运算符表达式
|表达式运算符表达式
|运算符表达式
|表达式运算符
|原子表达式
;
原子表达式:
标识符(“”)//托多:这是lsv吗?
;
类型:标识符;
//
//LEXER规则。
注释:'/*'.'*/'->通道(隐藏);
行注释:'/'~[\000A\000D]*->通道(隐藏);
赋值_运算符:运算符?'=';
//WSA=空白感知令牌。
//这些标记出现在给定的空白上下文中。
WSA_操作员:
(WhiteSpaceNotNewline+运算符WhiteSpaceNotNewline+)
;
操作员:操作员;
//换行符是分开定义的,因为它们作为一个语句具有意义
//定界符。
新行:
(“\u000D”\u000A”)
|“\u000A”
;
WS:WhiteSpaceNotNewline->skip;
分号:';';
标识符:
(IdentifierHead IdentifierCharacter*)
|('`'(IdentifierHead IdentifierCharacter*)'`')
;
片段小数位数:'0'..'9';
碎片识别头:
“a”…“z”
|“A”…“Z”
| '_'
|“\u00A8”
|“\u00AA”
|“\u00AD”
|“\u00AF”|
'\u00B2'..'\u00B5'|
“\u00B7”…“\u00BA”|
'\u00BC'..'\u00BE'|
'\u00C0'..'\u00D6'|
'\u00D8'..'\u00F6'|
'\u00F8'..'\u00FF'|
'\u0100'..'\u02FF'|
'\u0370'..'\u167F'|
'\u1681'..'\u180D'|
'\u180F'..'\u1DBF'|
'\u1E00'..'\u1ff'|
'\u200B'..'\u200D'|
'\u202A'..'\u202E'|
“\u203F”…“\u2040”|
“\u2054”|
“\u2060”…“\u206F”|
“\u2070”…“\u20CF”|
“\u2100”…“\u218F”|
'\u2460'..'\u24FF'|
“\u2776”…“\u2793”|
'\u2C00'..'\u2DFF'|
'\u2E80'..'\u2FFF'|
“\u3004”…“\u3007”|
'\u3021'..'\u302F'|
'\u3031'..'\u303F'|
'\u3040'..'\uD7FF'|
'\uF900'..'\uFD3D'|
'\uFD40'..'\uFDCF'|
'\uFDF0'..'\uFE1F'|
'\uFE30'..'\uFE44'|
'\uFE47'..'\uFFFD'
;
片段标识符字符:
小数位数
|'\u0300'..'\u036F'
|'\u1DC0'..'\u1DFF'
|'\u20D0'..'\u20FF'
|'\uFE20'..'\uFE2F'
|识别头
;
//非换行空格是分开定义的,因为它们在
//某些上下文,例如空间感知操作员内部。
片段WhiteSpaceNotNewline:[\u0020\u000C\u0009u000B\u000C];
片段运算符:
'*'
| '/'
| '%'
| '+'
| '-'
| ''
| '&'
| '^'
| '|'
;
规则

expression
    : monoOperatedExpression (binaryOperator monoOperatedExpression)?
    ;
不允许在
二进制运算符之后使用
=
。因此,运行时报告说,在使用
二进制\u OP
之后,它不知道下一个要使用的规则

语法可以通过一些重要的重组,最好是简化来固定

1-忽略空格/换行符可以大大简化处理

WS : [ \t\r\n] -> skip;
C族语言和类似Python的语言都是上下文无关的语言,有一些众所周知的上下文敏感的情况。ANTLR是一个上下文无关的解析器,具有许多方便的功能来处理上下文敏感性。因此,默认情况下忽略(或隐藏)空白

二,
STAR_EQUAL : '*=' ;
STAR       : '*'  ;
EQUAL      : '='  ;
expression     // list of all valid syntaxes for an `expression`
    : LPAREN expression RPAREN
    | expression ( COMMA expression )*
    | expression op expression 
    | unitary_op expression 
    | expression unitary_op 
    | << any other valid syntax >>
    | atom
    ;

 unitary_op : 2PLUS | 2DASH | .... ;
 op         : STAR_EQUAL | STAR | EQUAL | .... ;

 atom
    : STAR? IDENTIFIER   // pointer usage
    | NUMBER
    ;
grammar Sable;

@header {
    package org.sable.parser.gen;
}

sable
    : statement* EOF
    ;

statement
    : expression? SEMI
    ;

expression
    : LPAREN expression RPAREN
    | COMMA expression
    | expression op expression
    | unitary_op expression
    | expression unitary_op
    | STAR? IDENTIFIER
    | NUMBER
    ;

 unitary_op
    : DPLUS | DMINUS
    ;

 op : STAR_EQUAL | DIV_EQUAL | PLUS_EQUAL | MINUS_EQUAL | EQUAL
    | STAR | DIV | PLUS | MINUS
    ;


COMMENT     : Comment -> skip ;

STAR_EQUAL  : '*=' ;
DIV_EQUAL   : '/=' ;
PLUS_EQUAL  : '+=' ;
MINUS_EQUAL : '-=' ;
EQUAL       : '='  ;

STAR        : '*'  ; // mult or pointer
DIV         : '/'  ;
PLUS        : '+'  ;
MINUS       : '-'  ;

DPLUS       : '++' ;
DMINUS      : '--' ;

COMMA       : ','  ;
DOT         : '.'  ;
SEMI        : ';'  ;

LPAREN      : '('  ;
RPAREN      : ')'  ;
LBRACE      : '{'  ;
RBRACE      : '}'  ;
LBRACK      : '['  ;
RBRACK      : ']'  ;
LANGLE      : '<'  ;
RANGLE      : '>'  ;

NUMBER      : [0-9]+ ('.' [0-9]+)? ([eE] [+-]? [0-9]+)? ;
IDENTIFIER  : [a-zA-Z_][a-zA-Z0-9_-]*  ;

WS          : [ \t\r\n]+    -> skip;

ERRCHAR
    :   .   -> channel(HIDDEN)
    ;

fragment Comment
    :   '/*' .*? '*/'
    |   '//' ~[\r\n]*
    ;