Anltr4的编写解释器

Tiny在上周上线TinyUiEnterprise的http://www.tinygroup.org/组件,经过反馈测试发现模板引擎的性能一直有问题,请查看jprofile
Anltr4的编写解释器_第1张图片

 当然很多性能问题,我们正在完善中,诸如:非递归DFS、大对象生命周期、异步调用......

但是放在我面前的却是把原先ClassLoader加载后,进行调用执行的方式变更为使用anltr的解释性语言去执行。

通过一周左右的攻克,总算把最难啃的骨头给啃掉了,这离不开beetl的贡献,这里有些运用了其中核心代码,通过bytewrite的方式进行调用

本文不在过多论述anltr到底是什么玩意,我感觉这类文章在网上搜索一大堆,推荐去阅读http://blog.csdn.net/dc_726/article/details/45399371

核心代码

		}
        //语法分析
		BeetlLexer lexer = new BeetlLexer(input);
		lexer.removeErrorListeners();
		lexer.addErrorListener(syntaxError);

		//token就是语法树上节点,递归下降解析器
		CommonTokenStream tokens = new CommonTokenStream(lexer);
		//语法树
		BeetlParser parser = new BeetlParser(tokens);
		// 测试代码

		ProgContext tree = parser.prog();
		// begin parsing at init rule
		AntlrProgramBuilder pb = new AntlrProgramBuilder(gt);
		ProgramMetaData data = pb.build(tree);

 判断ASTNode的节点类型

if (node instanceof TinyTemplateParser.BlockContext) {
			TinyTemplateParser.BlockContext bc = (TinyTemplateParser.BlockContext) node;
			int count = bc.getChildCount();
			for (int i = 0; i < count; i++) {
				String str = bc.getChild(i).getText();
				int position = 0;
				if (!this.gt.getConf().directByteOutput) {
					StaticTextASTNode textNode = new StaticTextASTNode(
							position, null);
					return textNode;
				} else {
					StaticTextByteASTNode textNode = new StaticTextByteASTNode(
							position, null);
					return textNode;
				}
			}
			Statement block = parseBlock(bc.value(), node);
			return block;

		}

 本案例中采用最简单的模板,里面就是读取变量,没有用到自定义宏

那么如何不通过classloader,而是直接write出来呢?

ctx.byteWriter.write((char[]) ctx.staticTextArray[textIndex]);

 

  /*
  注意:此文档初始版本来自jetbrick-template,后经过修改成为Tiny模板引擎词法文件
  * jetbrick-template
  * http://subchen.github.io/jetbrick-template/
  *
  * Copyright 2010-2013 Guoqiang Chen. All rights reserved.
  * Email: [email protected]
  */
lexer grammar TinyTemplateLexer;
/*
@header {
package jetbrick.template.parser.grammer;
}
*/
// *******************************************************************
// ------- DEFAULT mode for Plain Text -------------------------------
COMMENT_LINE           : '##' ~[\r\n]* NEWLINE          ;
COMMENT_BLOCK2            : '#*' .*? '*#'                 ;
COMMENT_BLOCK1            : '#--' .*? '--#'                  ;
fragment NEWLINE        : ('\r'? '\n' | EOF)              ;

TEXT_PLAIN              : ~('$'|'#'|'\\')+                ;
TEXT_CDATA              : '#[[' .*? ']]#'                 ;
TEXT_ESCAPED_CHAR       : ('\\#'|'\\$'|'\\\\')            ;
TEXT_SINGLE_CHAR        : ('#'|'$'|'\\')                  ;
PARA_SPLITER           :[ \t]* (',')?[ \t]*    ;
I18N_OPEN              : '$${'                            -> pushMode(INSIDE) ;

//VALUE_COMPACT_OPEN              : '$'                    ;
VALUE_OPEN              : '${'                            -> pushMode(INSIDE) ;
VALUE_ESCAPED_OPEN      : '$!{'                           -> pushMode(INSIDE) ;

DIRECTIVE_OPEN_SET      : ('#set'|'#!set' )     ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_IF       : '#if'       ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_ELSEIF   : '#elseif'   ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_FOR      : ('#for'|'#foreach')      ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_BREAK    : '#break'    ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_CONTINUE : '#continue' ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_STOP     : '#stop'     ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_INCLUDE  : '#include'  ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_CALL  : '#call'  ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_CALL  : '#@call'  ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_LAYOUT_IMPL  : '#@layout'  ARGUMENT_START      -> pushMode(INSIDE) ;

DIRECTIVE_OPEN_MACRO    : '#macro'    [ \t]+ ID ARGUMENT_START -> pushMode(INSIDE) ;

DIRECTIVE_OPEN_LAYOUT   : '#layout' ARGUMENT_START -> pushMode(INSIDE) ;

fragment ID             : [_a-zA-Z$][_a-zA-Z$0-9]*        ;
fragment ARGUMENT_START : [ \t]* '('                      ;

DIRECTIVE_SET           : '#set'|'#!set'                          ;
DIRECTIVE_IF            : '#if'                           ;
DIRECTIVE_ELSEIF        : '#elseif'                       ;
DIRECTIVE_FOR           : '#for'                          ;
DIRECTIVE_INCLUDE       : '#include'                      ;
DIRECTIVE_BREAK         : '#break'                        ;
DIRECTIVE_CONTINUE      : '#continue'                     ;
DIRECTIVE_STOP          : '#stop'                         ;
DIRECTIVE_MACRO         : '#macro'                        ;

DIRECTIVE_ELSE          : '#else'|'#{else}'                   ;
DIRECTIVE_END           : '#end'|'#{end}'                 ;
DIRECTIVE_BLANK         : '#b'|'#{b}'                       ;
DIRECTIVE_END_OF_LINE           : '#eol'|'#{eol}'                 ;
DIRECTIVE_TABS           : '#t'|'#{t}'                 ;
DIRECTIVE_TABS_INDENT           : '#]'|'#{]}'                 ;
DIRECTIVE_TABS_DENT           : '#['|'#{[}'                 ;
DIRECTIVE_BODYCONTENT  : '#bodyContent'|'#{bodyContent}' ;
DIRECTIVE_IMPORT  : '#import' ARGUMENT_START      -> pushMode(INSIDE) ;

//DIRECTIVE_CALL    : '#' ID      ;
DIRECTIVE_MACRO_INVOKE    : '#' ID     ARGUMENT_START      -> pushMode(INSIDE) ;
DIRECTIVE_OPEN_MACRO_INVOKE    : '#@' ID    ARGUMENT_START -> pushMode(INSIDE) ;

// It is a text which like a directive.
// It must be put after directive defination to avoid confliction.
TEXT_DIRECTIVE_LIKE     : '#' [a-zA-Z0-9]+                ;


// *******************************************************************
// -------- INSIDE mode for directive --------------------------------
mode INSIDE;

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

LEFT_PARENTHESE         : '('                              -> pushMode(INSIDE) ;
RIGHT_PARENTHESE        : ')'                              -> popMode ;
LEFT_BRACKET            : '['                              ;
RIGHT_BRACKET           : ']'                              ;
LEFT_BRACE              : '{'                              -> pushMode(INSIDE) ;
RIGHT_BRACE             : '}'                              -> popMode ;
IN                       : 'in'                             ;
OP_ASSIGNMENT           : '='                              ;

OP_DOT_DOT              :  '..'                              ;
OP_DOT_INVOCATION       : '.'                              ;
OP_DOT_INVOCATION_SAFE  : '?.'                             ;

OP_EQUALITY_EQ          : '=='                             ;
OP_EQUALITY_NE          : '!='                             ;

OP_RELATIONAL_GT        : '>'                              ;
OP_RELATIONAL_LT        : '<'                              ;
OP_RELATIONAL_GE        : '>='                             ;
OP_RELATIONAL_LE        : '<='                             ;

OP_CONDITIONAL_AND      : '&&'                             ;
OP_CONDITIONAL_OR       : '||'                             ;
OP_CONDITIONAL_NOT      : '!'                              ;

OP_MATH_PLUS            : '+'                              ;
OP_MATH_MINUS           : '-'                              ;
OP_MATH_MULTIPLICATION  : '*'                              ;
OP_MATH_DIVISION        : '/'                              ;
OP_MATH_REMAINDER       : '%'                              ;
OP_MATH_INCREMENT       : '++'                             ;
OP_MATH_DECREMENT       : '--'                             ;

OP_BITWISE_AND          : '&'                              ;
OP_BITWISE_OR           : '|'                              ;
OP_BITWISE_NOT          : '~'                              ;
OP_BITWISE_XOR          : '^'                              ;
OP_BITWISE_SHL          : '<<'                             ;

OP_BITWISE_SHR        : '>>'                             ;
OP_BITWISE_SHR_2      : '>>>'                            ;

OP_CONDITIONAL_TERNARY  : '?'                              ;

OP_SIMPLE_CONDITION_TERNARY      : '?:'                           ;

COMMA                   : ','                              ;
COLON                   : ':'                              ;
AT                      : '@'                              ;

KEYWORD_TRUE            : 'true'                           ;
KEYWORD_FALSE           : 'false'                          ;
KEYWORD_NULL            : 'null'                           ;


IDENTIFIER              : [_a-zA-Z][_a-zA-Z0-9]*         ;

INTEGER                 : INT [lLfFdD]?                    ;
INTEGER_HEX             : '0x' HEX+ [lL]?                  ;
FLOATING_POINT          : INT ('.' FRAC)? EXP? [fFdD]?     ;
fragment INT            : '0' | [1-9] [0-9]*               ;
fragment FRAC           : [0-9]+                           ;
fragment EXP            : [Ee] [+\-]? INT                  ;

STRING_DOUBLE           : '"'  (ESC|.)*? '"'               ;
STRING_SINGLE           : '\'' (ESC|.)*? '\''              ;
fragment ESC            : '\\' ([btnfr"'\\]|UNICODE)       ;
fragment UNICODE        : 'u' HEX HEX HEX HEX              ;
fragment HEX            : [0-9a-fA-F]                      ;

 

 

 /*
 注意:此文档初始版本来自jetbrick-template,后经过修改成为Tiny模板引擎语法文件
 * jetbrick-template
 * http://subchen.github.io/jetbrick-template/
 *
 * Copyright 2010-2013 Guoqiang Chen. All rights reserved.
 * Email: [email protected]
 */
parser grammar TinyTemplateParser;

options {
    tokenVocab = TinyTemplateLexer; // use tokens from JetTemplateLexer.g4
}

/*
@header {
package jetbrick.template.parser.grammer;
}
*/

// -------- rule ---------------------------------------
template    :   block
            ;

block       :   (comment | directive | text | value)*
            ;


text        :   TEXT_PLAIN
            |   TEXT_CDATA
            |   TEXT_SINGLE_CHAR
            |    COMMENT_LINE
            |   COMMENT_BLOCK1
            |   COMMENT_BLOCK2
            |   TEXT_ESCAPED_CHAR
            |   TEXT_DIRECTIVE_LIKE
            ;
comment        :     COMMENT_LINE
            |   COMMENT_BLOCK1
            |   COMMENT_BLOCK2
            ;
value       :   //VALUE_COMPACT_OPEN  identify_list
               VALUE_OPEN         expression '}'
            |   VALUE_ESCAPED_OPEN expression '}'
            |  I18N_OPEN  identify_list '}'
            ;


directive   :   set_directive
            |   if_directive
            |   for_directive
            |   break_directive
            |   import_directive
            |   continue_directive
            |   stop_directive
            |   include_directive
            |   macro_directive
            |   call_block_directive
            |   layout_directive
            |   layout_impl_directive
            |   call_directive
            |   endofline_directive
            |   blank_directive
            |   tabs_directive
            |   indent_directive
            |   dent_directive
            |   call_macro_directive
            |   call_macro_block_directive
            |   bodycontent_directive
            |   invalid_directive
            ;
identify_list
            :IDENTIFIER ('.' IDENTIFIER)*
            ;

define_expression_list
            :   define_expression (','? define_expression)*
            ;
para_expression_list
            :   para_expression (','? para_expression)*
            ;
para_expression
            :   IDENTIFIER '=' expression
            |   expression
            ;

define_expression
            :   IDENTIFIER ('=' expression)?
            ;

set_directive
            :   DIRECTIVE_OPEN_SET set_expression (','? set_expression)* ')'
            ;
set_expression
            :    IDENTIFIER '=' expression
            ;
endofline_directive
            :    DIRECTIVE_END_OF_LINE
            ;
tabs_directive
            :    DIRECTIVE_TABS
            ;
blank_directive
            :    DIRECTIVE_BLANK
            ;
indent_directive
            :    DIRECTIVE_TABS_INDENT
            ;
dent_directive
            :    DIRECTIVE_TABS_DENT
            ;

if_directive
            :   DIRECTIVE_OPEN_IF expression ')' block elseif_directive* else_directive? DIRECTIVE_END
            ;
elseif_directive
            :   DIRECTIVE_OPEN_ELSEIF expression ')' block
            ;
else_directive
            :   DIRECTIVE_ELSE block
            ;

for_directive
            :   DIRECTIVE_OPEN_FOR for_expression ')' block else_directive? DIRECTIVE_END
            ;
for_expression
            :    IDENTIFIER (':'|'in') expression
            ;

break_directive
            :   DIRECTIVE_OPEN_BREAK expression?')'
            |   DIRECTIVE_BREAK
            ;
import_directive
            :   DIRECTIVE_IMPORT expression ')'
            ;

continue_directive
            :   DIRECTIVE_OPEN_CONTINUE expression? ')'
            |   DIRECTIVE_CONTINUE
            ;
stop_directive
            :   DIRECTIVE_OPEN_STOP expression? ')'
            |   DIRECTIVE_STOP
            ;

include_directive
            :   DIRECTIVE_OPEN_INCLUDE expression (','? '{' hash_map_entry_list? '}')? ')'
            ;


macro_directive
            :   DIRECTIVE_OPEN_MACRO define_expression_list? ')' block DIRECTIVE_END
            ;

layout_directive
            :   DIRECTIVE_OPEN_LAYOUT IDENTIFIER ')' block DIRECTIVE_END
            ;

call_block_directive
            :   DIRECTIVE_OPEN_CALL  expression (','?  para_expression_list )? ')' block DIRECTIVE_END
            ;
layout_impl_directive
            :   DIRECTIVE_OPEN_LAYOUT_IMPL IDENTIFIER ')' block DIRECTIVE_END
            ;

call_directive
            :   DIRECTIVE_CALL  expression ( ','? para_expression_list )? ')'
            ;

call_macro_block_directive
            :  DIRECTIVE_OPEN_MACRO_INVOKE   para_expression_list? ')' block DIRECTIVE_END
            ;

bodycontent_directive
            :DIRECTIVE_BODYCONTENT
            ;
call_macro_directive
            :  DIRECTIVE_MACRO_INVOKE   para_expression_list? ')'
            ;
invalid_directive
            :   DIRECTIVE_SET
//            |   DIRECTIVE_PUT
            |   DIRECTIVE_IF
            |   DIRECTIVE_ELSEIF
            |   DIRECTIVE_FOR
            |   DIRECTIVE_INCLUDE
//            |   DIRECTIVE_OPEN_CALL_MACRO
//            |   DIRECTIVE_BODY_CALL
            |   DIRECTIVE_MACRO
            ;

expression  :   '(' expression ')'                                           # expr_group
            |   constant                                                     # expr_constant
            |   IDENTIFIER                                                   # expr_identifier
            |   '[' (expression_list |expression_range)?  ']'       # expr_array_list
            |   '{' hash_map_entry_list? '}'                                 # expr_hash_map
            |   expression ('.'|'?.') IDENTIFIER '(' expression_list? ')'    # expr_member_function_call
            |   expression ('.'|'?.') IDENTIFIER                             # expr_field_access
            |   IDENTIFIER '(' expression_list? ')'                          # expr_function_call

            |   expression ('?')? '[' expression ']'                         # expr_array_get
            |   expression ('++'|'--')                                       # expr_single_right
            |   ('+' <assoc=right> |'-' <assoc=right>)  expression           # expr_math_unary_prefix
            |   ('++'|'--')       expression                                 # expr_single_left
            |   '~' <assoc=right> expression                                 # expr_math_unary_prefix
            |   '!' <assoc=right> expression                                 # expr_math_unary_prefix
            |   expression ('*'|'/'|'%')  expression                         # expr_math_binary_basic
            |   expression ('+'|'-')      expression                         # expr_math_binary_basic
            |   expression ('<<'|'>>'|'>>>') expression             # expr_math_binary_shift
            |   expression ('>='|'<='|'>'|'<') expression                    # expr_compare_relational
            |   expression ('=='|'!=') expression                            # expr_compare_equality
            |   expression '&'  expression                                   # expr_math_binary_bitwise
            |   expression '^' <assoc=right> expression                      # expr_math_binary_bitwise
            |   expression '|'  expression                                   # expr_math_binary_bitwise
            |   expression '&&' expression                                   # expr_compare_condition
            |   expression '||' expression                                   # expr_compare_condition
            |   expression '?' <assoc=right> expression ':' expression       # expr_conditional_ternary
            |   expression '?:' expression       # expr_simple_condition_ternary
            ;

constant    :   STRING_DOUBLE
            |   STRING_SINGLE
            |   INTEGER
            |   INTEGER_HEX
            |   FLOATING_POINT
            |   KEYWORD_TRUE
            |   KEYWORD_FALSE
            |   KEYWORD_NULL
            ;

expression_list
            :   expression (',' expression)*
            ;

hash_map_entry_list
            :   expression ':' expression (',' expression ':' expression)*
            ;

expression_range
            :   expression '..' expression
            ;


 

你可能感兴趣的:(tr)