3

我正在使用 xtext 2.4。我想要做的是类似 SQL 的语法。让我感到困惑的是我不确定哪些东西应该被视为终端/数据类型/解析器规则。到目前为止,我的语法相关MyTerm是:

Model:
    (terms += MyTerm ';')*
;

MyTerm:
    constant=MyConstant | variable?='?'| collection_literal=CollectionLiteral 
;

MyConstant
    : string=STRING 
    | number=MyNumber
    | date=MYDATE 
    | uuid=UUID 
    | boolean=MYBOOLEAN
    | hex=BLOB
;

MyNumber:
    int=SIGNINT | float=SIGNFLOAT
;


SIGNINT returns ecore::EInt:
    '-'? INT
;


SIGNFLOAT returns ecore::EFloat:
    '-'? INT '.' INT;
;

CollectionLiteral:
    => MapLiteral | SetLiteral | ListLiteral
;

MapLiteral:
    '{' {MapLiteral} (entries+=MapEntry (',' entries+=MapEntry)* )? '}'
;

MapEntry:
    key=MyTerm ':' value=MyTerm
;

SetLiteral:
    '{' {SetLiteral} (values+=MyTerm (',' values+=MyTerm)* )+ '}'
;

ListLiteral:
    '[' {ListLiteral} ( values+=MyTerm (',' values+=MyTerm)* )? ']'
;

terminal MYDATE:
  '0'..'9' '0'..'9' '0'..'9' '0'..'9' '-'
  '0'..'9' '0'..'9' '-'
  '0'..'9' '0'..'9'
;

terminal HEX:
    'a'..'h'|'A'..'H'|'0'..'9'
;   

terminal UUID:
    HEX HEX HEX HEX HEX HEX HEX HEX '-'
    HEX HEX HEX HEX '-'
    HEX HEX HEX HEX '-'
    HEX HEX HEX HEX '-'
    HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
;

terminal BLOB:
    '0' ('x'|'X') HEX+
;

terminal MYBOOLEAN returns ecore::EBoolean:
    'true' | 'false' | 'TRUE' | 'FALSE'
;

几个问题:

  • 如何定义带符号的整数?如果我定义另一个终端规则terminal SIGNINT: '-'? '0'..'9'+;,antlr 会抱怨 INT 变得无法访问。因此我将其定义为数据类型规则SIGNINT: '-'? INT;这是正确的方法吗?

  • 如何定义带符号的浮点数?我所做的与使用符号定义整数完全相同SIGNFLOAT: '-'? INT '.' INT;,但不确定这是否正确。

  • 如何定义日期规则?我想使用解析器规则在字段中存储年/月/日信息,但将其定义为MyDate: year=INT '-' month=INT '-' date=INT;antlr 会抱怨Decision can match input such as "RULE_INT '-' RULE_INT '-' RULE_INT" using multiple alternatives: 2, 3 As a result, alternative(s) 3 were disabled for that input

  • 我还有一些其他的规则,比如

以下

RelationCompare:
    name=ID compare=COMPARE term=MyTerm
;

a=4不会是有效的RelationCompare,因为a并且4将被视为HEXs。我发现这是因为如果我将关系更改为j=44那么它就可以工作。在这篇文章中,它说早期定义的终端规则将影响后面定义的规则。但是,如果我terminal ID在语法中重新定义,无论是放在 of 的前面还是后面terminal HEX,antlr 都会抱怨The following token definitions can never be matched because prior tokens match the same input: RULE_HEX,RULE_MYBOOLEAN。这个问题也发生在k=0x00bk=0xaab是有效的,但k=0x00b不是。

有什么建议吗?

4

2 回答 2

3

后来我找到了我想做的原始 antlr 语法,因此我简单地将 antlr 语法翻译成 xtext 语法。以下是我定义这些基本类型的方式:

terminal fragment A: 'a'|'A';  
   ... 
terminal fragment Z: 'z'|'Z';

terminal fragment DIGIT: '0'..'9';
terminal fragment LETTER: ('a'..'z'|'A'..'Z');
terminal fragment HEX: ('a'..'f'|'A'..'F'|'0'..'9'); 

terminal fragment EXPONENT: E ('+'|'-')? DIGIT+;
terminal INTEGER returns ecore::EInt: '-'? DIGIT+;
terminal FLOAT returns ecore::EFloat: INTEGER EXPONENT | INTEGER '.' DIGIT* EXPONENT?;

terminal BOOLEAN: T R U E | F A L S E;

原始语法中的日期规则被视为字符串。

关于规则名称(规则:Antlr Grammar => xtext Grammar)

  • 解析器规则:以小写开头 => 以大写开头的规则(每个都是 Java 类)
  • 终端规则:以大写开头 => 使用所有大写和terminal前缀
  • 片段终端规则:fragmentID => terminal fragmentID

在 antlr 中,参数列表定义如下:

functionArgs
  : '(' ')'
  | '(' t1=term ( ',' tn=term )* ')'
;

对应的xtext文法为:

FunctionArgs
 : '(' ')'
 | '(' ts+=Term  (',' ts+=Term )* ')'
;

对于那些带有参数的解析器规则[ ]

properties[PropertyDefinitions props]
  : property[props] (K_AND property[props])*
;

大多数情况下,它们可以移动到左侧

Properties
  : props+=Property (K_AND props+=Property)*
;

现在它按预期工作。

于 2013-08-13T23:57:28.603 回答
3

你如何定义一个带符号的整数?

  • 将其视为两个单独的标记'-'INT,并使用解析器规则而不是词法分析器规则。

你如何定义一个带符号的浮点数?

  • 将其视为两个单独的标记'-'FLOAT,并使用解析器规则而不是词法分析器规则。

您如何定义日期规则?

  • 将其视为五个单独的标记并使用解析器规则而不是词法分析器规则。

我不知道最后一个问题的答案,因为这是在 Xtext 中,而不仅仅是 ANTLR。

于 2013-08-07T00:20:32.113 回答