0

我正在处理我的 dsl 项目。但是当我想让它像python(Whitespace-Aware Languages)一样工作时,它给了我错误“不匹配的输入'\ t'期待RULE_BEGIN”。终端规则 BEGIN 是什么意思?为什么下面的例子不能工作?这是我的语法:

grammar org.pythonDSL.PythonDSL

hidden(WS)

generate pythonDSL "http://www.pythonDSL.org/PythonDSL"

import "http://www.eclipse.org/emf/2002/Ecore" as ecore

PythonDSL:
    (elements+=AbstractElement)*;
 
AbstractElement:
    type=(Stmt|Config);
 
QualifiedName:
    ID ('.' ID)*;
    
Comment:
    name=(ML_COMMENT|SL_COMMENT);

Import:
    'import' importedNamespace=QualifiedNameWithWildcard;

Config:
    {Config} 'config' configs=Dictionary;

KeyValue:
    name=QualifiedValue ':' value=QualifiedValue;

QualifiedNameWithWildcard:
    QualifiedName '.*'?;

QualifiedIndex:
INT|STRING;

Dictionary:
    {Dictionary} '{' (elements+=KeyValue)+ '}';

Set:
    {Set} '{' (elements+=QualifiedValue)* '}';

List:
    {List} '[' (elements+=QualifiedValue)* ']';

QualifiedValue:
STRING|'True'|'False'|INT;

VarDec:
name=ID('['index=QualifiedIndex']')? '=' value=QualifiedValue;

Stmt:
 type=(Exp|Import) NEXT_LINE | type=If | type=Comment;

If:
    'if' (not='not')? condition=Exp ':' NEXT_LINE?
     (BEGIN ( ifStmts+=Stmt)* END)
    (=> elseIfClause+=ElseIf)*
    (=> elseClause=Else)?;

ElseIf:
    'elif'  condition=Exp ':' NEXT_LINE?
     (BEGIN ( elseIfStmts+=Stmt)* END);

Else:
    {Else} 'else' NEXT_LINE? (BEGIN ( elseStmts+=Stmt)* END);

Exp:
    left=Equal;

Ret:
    'return' name=ID;

Var:
    name=ID;


Val:
    name=QualifiedValue | type=(Dictionary|List|Set);

Dot returns Exp:
    left=Array ({Dot.left=current} op='.'right=Array)*
;

Array returns Exp:
    left=Primary ({Array.left=current} op='['right=Primary']')*
;

Primary returns Exp:
   op='(' left=Equal ')' |left=Var|left=Val|left=FuncCall;

ArgList:
    {ArgList} (args+=Equal)? (',' args+=Equal)*;

FuncCall:
    name=Var (op='(' right=ArgList ')');

Equal returns Exp:
    left=AddAndSub ({Euqal.left=current} op='=' right=AddAndSub)*;

AddAndSub returns Exp:
    left=MulAndDiv ({AddAndSub.left=current} op=('+'|'-') right=MulAndDiv)*;

MulAndDiv returns Exp:
    left=Dot ({MulAndDiv.left=current} op=('*'|'/') right=Dot)*;

terminal BEGIN: 'synthetic:BEGIN';  // increase indentation
terminal END: 'synthetic:END';      // decrease indentation

terminal ID:
    '^'?('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
 
terminal INT returns ecore::EInt:
    ('0'..'9')+;
 
terminal STRING:
    '"' ( '\\'('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') | !('\\'|'"') )* '"' |
    "'" ( '\\'('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') | !('\\'|"'") )* "'";
 
terminal ML_COMMENT:
    "'''" -> "'''";
 
terminal SL_COMMENT:
    '#' !('\n'|'\r')* ('\r'? '\n')?;
 
terminal WS:
    (' ')+;
/*    
terminal TAB:
    ('\t')+;
    */
terminal NEXT_LINE:
    ('\n'|'\r')+;

terminal ANY_OTHER:
    .;

这是我的例子:

a = b
if a.b:
    el.click()
elif c:
    '''les '''
    e.go()
elif m:
    if lake:
        pik()
else:
    e1.click()

主要问题是 if-else 子句,该子句需要检测缩进。而且我需要 NEXT_LINE 规则来确保一个 stmt 只有一行。在简单的语法中,BEGIN 和 END 规则都可以工作。但是当我添加 NEXT_LINE 规则时,它失败了。

4

0 回答 0