液体标记的ANTLR语法?

液体标记的ANTLR语法?,antlr,liquid,Antlr,Liquid,有人知道液体标记的ANTLR语法或可以使用它的JAVA库吗?我看了一眼,但似乎不太管用 谢谢 这里有一个语法: grammar Liquid; options { output=AST; ASTLabelType=CommonTree; } tokens { ASSIGNMENT; ATTRIBUTES; BLOCK; CAPTURE; CASE; COMMENT; CYCLE; ELSE; FILTERS; FILTER; FOR_AR

有人知道液体标记的ANTLR语法或可以使用它的JAVA库吗?我看了一眼,但似乎不太管用

谢谢

这里有一个语法:

grammar Liquid;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

tokens {
  ASSIGNMENT;
  ATTRIBUTES;
  BLOCK;
  CAPTURE;
  CASE;
  COMMENT;
  CYCLE; 
  ELSE;
  FILTERS;
  FILTER;
  FOR_ARRAY;
  FOR_RANGE;
  GROUP;
  IF;
  INCLUDE;
  LOOKUP;
  OUTPUT;
  PARAMS;
  PLAIN;
  RAW;
  TABLE;
  UNLESS;
  WHEN;
  WITH;
}

@parser::members {
  @Override
  public void reportError(RecognitionException e) {
    throw new RuntimeException(e); 
  }
}

@lexer::members {
  private boolean inTag = false;

  private boolean openTagAhead() {
    return input.LA(1) == '{' && (input.LA(2) == '{' || input.LA(2) == '\u0025');
  }

  @Override
  public void reportError(RecognitionException e) {
    throw new RuntimeException(e); 
  }
}

/* parser rules */
parse
 : block EOF -> block
 ;

block
 : (options{greedy=true;}: atom)* -> ^(BLOCK atom*)
 ;

atom
 : tag
 | output
 | assignment
 | Other -> ^(PLAIN Other)
 ;

tag
 : raw_tag
 | comment_tag
 | if_tag
 | unless_tag
 | case_tag
 | cycle_tag
 | for_tag
 | table_tag
 | capture_tag
 | include_tag
 ;

raw_tag
 : TagStart RawStart TagEnd raw_body TagStart RawEnd TagEnd 
   -> ^(RAW raw_body)
 ;

raw_body
 : ~TagStart*
 ;

comment_tag
 : TagStart CommentStart TagEnd comment_body TagStart CommentEnd TagEnd 
   -> ^(COMMENT comment_body)
 ;

comment_body
 : ~TagStart*
 ;

if_tag
 : TagStart IfStart expr TagEnd block else_tag? TagStart IfEnd TagEnd 
   -> ^(IF expr block ^(ELSE else_tag?))
 ;

else_tag
 : TagStart Else TagEnd block 
   -> block
 ;

unless_tag
 : TagStart UnlessStart expr TagEnd block else_tag? TagStart UnlessEnd TagEnd 
   -> ^(UNLESS expr block ^(ELSE else_tag?))
 ;

case_tag
 : TagStart CaseStart expr TagEnd when_tag+ else_tag? TagStart CaseEnd TagEnd 
   -> ^(CASE expr when_tag+ ^(ELSE else_tag?))
 ;

when_tag
 : TagStart When expr TagEnd block 
   -> ^(WHEN expr block)
 ;

cycle_tag
 : TagStart Cycle cycle_group? expr (Comma expr)* TagEnd 
   -> ^(CYCLE ^(GROUP cycle_group?) expr+)
 ;

cycle_group
 : expr Col -> expr
 ;

for_tag
 : for_array
 | for_range    
 ;

for_array // attributes must be 'limit' or 'offset'!
 : TagStart ForStart Id In lookup attribute* TagEnd block TagStart ForEnd TagEnd
   -> ^(FOR_ARRAY Id lookup ^(ATTRIBUTES attribute*) block)
 ;

attribute 
 : Id Col expr -> ^(Id expr)
 ;

for_range
 : TagStart ForStart Id In OPar expr DotDot expr CPar TagEnd block TagStart ForEnd TagEnd
   -> ^(FOR_RANGE Id expr expr block)
 ;

table_tag // attributes must be 'limit' or 'cols'!
 : TagStart TableStart Id In Id attribute* TagEnd block TagStart TableEnd TagEnd
   -> ^(TABLE Id Id ^(ATTRIBUTES attribute*) block)
 ;

capture_tag
 : TagStart CaptureStart Id TagEnd block TagStart CaptureEnd TagEnd
   -> ^(CAPTURE Id block)
 ;

include_tag
 : TagStart Include a=Str (With b=Str)? TagEnd 
   -> ^(INCLUDE $a ^(WITH $b?))
 ;

output
 : OutStart expr filter* OutEnd 
   -> ^(OUTPUT expr ^(FILTERS filter*))
 ;

filter
 : Pipe Id params? 
   -> ^(FILTER Id ^(PARAMS params?))
 ;

params
 : Col expr (Comma expr)*  -> expr+
 ;

assignment
 : TagStart Assign Id EqSign expr TagEnd 
   -> ^(ASSIGNMENT Id expr)
 ;

expr
 : or_expr
 ;

or_expr
 : and_expr (Or^ and_expr)*
 ;

and_expr
 : eq_expr (And^ eq_expr)*
 ;

eq_expr
 : rel_expr ((Eq | NEq)^ rel_expr)*
 ;

rel_expr
 : term ((LtEq | Lt | GtEq | Gt)^ term)?
 ;

term
 : Num
 | Str
 | True
 | False
 | Nil
 | lookup
 ;

lookup
 : Id (Dot Id)* -> ^(LOOKUP Id+)
 ;

/* lexer rules */
OutStart : '{{' {inTag=true;};
OutEnd   : '}}' {inTag=false;};
TagStart : '{%' {inTag=true;};
TagEnd   : '%}' {inTag=false;};

Str : {inTag}?=> (SStr | DStr);

DotDot : {inTag}?=> '..';
Dot    : {inTag}?=> '.';
NEq    : {inTag}?=> '!=';
Eq     : {inTag}?=> '==';
EqSign : {inTag}?=> '=';
GtEq   : {inTag}?=> '>=';
Gt     : {inTag}?=> '>';
LtEq   : {inTag}?=> '<=';
Lt     : {inTag}?=> '<';
Pipe   : {inTag}?=> '|';
Col    : {inTag}?=> ':';
Comma  : {inTag}?=> ',';
OPar   : {inTag}?=> '(';
CPar   : {inTag}?=> ')';
Num    : {inTag}?=> Digit+;
WS     : {inTag}?=> (' ' | '\t' | '\r' | '\n')+ {skip();};

Id
 : {inTag}?=> (Letter | '_') (Letter | '_' | '-' | Digit)*
   {
     if($text.equals("capture"))          $type = CaptureStart;
     else if($text.equals("endcapture"))  $type = CaptureEnd;
     else if($text.equals("comment"))     $type = CommentStart;
     else if($text.equals("endcomment"))  $type = CommentEnd;
     else if($text.equals("raw"))         $type = RawStart;
     else if($text.equals("endraw"))      $type = RawEnd;
     else if($text.equals("if"))          $type = IfStart;
     else if($text.equals("endif"))       $type = IfEnd;
     else if($text.equals("unless"))      $type = UnlessStart;
     else if($text.equals("endunless"))   $type = UnlessEnd;
     else if($text.equals("else"))        $type = Else;
     else if($text.equals("case"))        $type = CaseStart;
     else if($text.equals("endcase"))     $type = CaseEnd;
     else if($text.equals("when"))        $type = When;
     else if($text.equals("cycle"))       $type = Cycle;
     else if($text.equals("for"))         $type = ForStart;
     else if($text.equals("endfor"))      $type = ForEnd;
     else if($text.equals("in"))          $type = In;
     else if($text.equals("and"))         $type = And;
     else if($text.equals("or"))          $type = Or;
     else if($text.equals("tablerow"))    $type = TableStart;
     else if($text.equals("endtablerow")) $type = TableEnd;
     else if($text.equals("assign"))      $type = Assign;
     else if($text.equals("true"))        $type = True;
     else if($text.equals("false"))       $type = False;
     else if($text.equals("nil"))         $type = Nil;
     else if($text.equals("include"))     $type = Include;
     else if($text.equals("with"))        $type = With;
   }
 ;

Other
 : ({!inTag && !openTagAhead()}?=> . )+
   {
     String s = getText().replaceAll("\\s+", " ").trim();
     if(s.isEmpty()) {
       skip();
     }
     else {
       setText(s);
     }
   }
 ;

/* fragment rules */
fragment Letter : 'a'..'z' | 'A'..'Z';
fragment Digit  : '0'..'9';
fragment SStr   : '\'' ~'\''* '\'';
fragment DStr   : '"' ~'"'* '"';

fragment CommentStart : ;
fragment CommentEnd : ;
fragment RawStart : ;
fragment RawEnd : ;
fragment IfStart : ;
fragment IfEnd : ;
fragment UnlessStart : ;
fragment UnlessEnd : ;
fragment Else : ;
fragment CaseStart : ;
fragment CaseEnd : ;
fragment When : ;
fragment Cycle : ;
fragment ForStart : ;
fragment ForEnd : ;
fragment In : ;
fragment And : ;
fragment Or : ;
fragment TableStart : ;
fragment TableEnd : ;
fragment Assign : ;
fragment True : ;
fragment False : ;
fragment Nil : ;
fragment Include : ;
fragment With : ;
fragment CaptureStart : ;
fragment CaptureEnd : ;
语法流;
选择权{
输出=AST;
ASTLabelType=CommonTree;
}
代币{
分配
属性;
块
捕获;
案例
评论;
周期
其他的
过滤器;
过滤器;
对于_阵列;
对于_范围;
组;
如果;
包括,;
查找;
产出;
参数;
平原
未经加工的
桌子
除非;
什么时候
具有
}
@解析器::成员{
@凌驾
公共作废报告错误(识别异常e){
抛出新的运行时异常(e);
}
}
@lexer::成员{
私有布尔inTag=false;
私有布尔值openTagAhead(){
返回input.LA(1)='{'&&&(input.LA(2)='{'| | input.LA(2)='\u0025');
}
@凌驾
公共作废报告错误(识别异常e){
抛出新的运行时异常(e);
}
}
/*解析器规则*/
作语法分析
:block EOF->block
;
块
:(选项{greedy=true;}:原子)*->^(块原子*)
;
原子
:标记
|输出
|分配
|其他->^(普通其他)
;
标签
:原始标签
|注释标签
|if_标签
|除非有标签
|箱子标签
|循环标签
|用于标签
|表(u)标签
|捕获标签
|包含标签
;
原始标签
:TagStart RawStart TagEnd raw_body TagStart RawEnd TagEnd
->^(原始正文)
;
生坯
:~TagStart*
;
注释标签
:TagStart CommentStart TagEnd comment_body TagStart CommentEnd TagEnd
->^(评论)
;
评论(附体)
:~TagStart*
;
if_标签
:TagStart IfStart expr TagEnd block else_tag?TagStart IfEnd TagEnd
->^(如果expr块^(其他标记?)
;
else_标签
:TagStart Else TagEnd块
->挡块
;
除非有标签
:TagStart UnlessStart expr TagEnd block else_tag?TagStart UnlessEnd TagEnd
->^(除非expr block^(其他标签?)
;
箱子标签
:TagStart CaseStart expr TagEnd when_tag+else_tag?TagStart CaseEnd TagEnd
->^(当标签+^(其他标签?)
;
什么时候贴标签
:TagStart When expr TagEnd块
->^(当expr块时)
;
循环标签
:TagStart循环组?expr(逗号expr)*TagEnd
->^(周期^(组周期?)expr+)
;
循环群
:expr Col->expr
;
用于标签
:对于_数组
|对于_范围
;
对于_数组//属性必须为“limit”或“offset”!
:TagStart ForStart Id在查找属性中*TagEnd块TagStart ForEnd TagEnd
->^(用于数组Id查找^(属性*)块)
;
属性
:Id Col expr->^(Id expr)
;
对于_范围
:OPar expr DotDot expr CPar TAGND块TagStart ForEnd TAGND中的TagStart ForStart Id
->^(适用于范围Id expr expr块)
;
表\标记//属性必须为“limit”或“cols”!
:TagStart TableStart Id在Id属性中*TagEnd块TagStart TableEnd TagEnd
->^(表Id^(属性*)块)
;
捕获标签
:TagStart CaptureStart Id TagEnd块TagStart CaptureEnd TagEnd
->^(捕获Id块)
;
包含标签
:TagStart包括a=Str(带b=Str)?TagEnd
->^(包括$a^(含$b?)
;
输出
:OutStart expr过滤器*OutEnd
->^(输出表达式^(过滤器*)
;
滤波器
:管道Id参数?
->^(过滤器Id^(参数?)
;
params
:Col expr(逗号expr)*->expr+
;
分配
:TagStart Assign Id EqSign expr TagEnd
->^(分配Id expr)
;
expr
:或_expr
;
或_expr
:和_expr(或^和_expr)*
;
和_expr
:eq_expr(和^eq_expr)*
;
等式表达式
:rel|u expr((Eq | NEq)^rel|u expr)*
;
关系表达式
:术语((LtEq | Lt | GtEq | Gt)^术语)?
;
学期
:Num
|Str
|真的
|假的
|零
|查找
;
查找
:Id(点Id)*->^(查找Id+)
;
/*lexer规则*/
突出部分:{{{inTag=true;};
外端:'}}{inTag=false;};
标记开始:'{%'{inTag=true;};
TagEnd:'%}{inTag=false;};
Str:{inTag}?=>(SStr | DStr);
DotDot:{inTag}?=>“…”;
点:{inTag}?=>';
NEq:{inTag}?=>“!=”;
等式:{inTag}?=>'==';
方程式:{inTag}?=>'=';
GtEq:{inTag}?=>'>=';
Gt:{inTag}?=>'>';

LtEq:{inTag}?=>“Liquid看起来与Django的模板语言完全相同……是否存在相关性?是的,Django使用Liquid标记。非常感谢。我一定会告诉你我的里程数。