`
cywhoyi
  • 浏览: 422019 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Anltr4的编写解释器

 
阅读更多

Tiny在上周上线TinyUiEnterprise的http://www.tinygroup.org/组件,经过反馈测试发现模板引擎的性能一直有问题,请查看jprofile

 当然很多性能问题,我们正在完善中,诸如:非递归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: subchen@gmail.com
  */
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: subchen@gmail.com
 */
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
            ;


 

  • 大小: 130.5 KB
2
1
分享到:
评论

相关推荐

    anltr简易计算器

    在"anltr简易计算器"项目中,我们首先定义了计算器语言的语法规则,如表达式、算术操作符、数字等。例如,一个简单的表达式规则可能如下: ``` expr : term ( (PLUS | MINUS) term )* ; term : factor ( (MUL | DIV...

    anltr学习资料

    ANTLR生成的解析器是用Java编写的,但支持多种目标语言,包括C#、Python、JavaScript等。 ANTLR的核心功能在于它能生成LL(*)和LR解析器,这些解析器可以处理上下文敏感的语法,使得ANTLR在解析复杂的语言时表现出色...

    基于ANTLR4的CMM语言编译器

    ANTLR4是一种强大的解析器生成器,广泛用于构建语言、工具和框架。它能够读取、处理、执行或翻译结构化文本或二进制文件。在本项目“基于ANTLR4的CMM语言编译器”中,开发人员使用ANTLR4来创建了一个针对CMM(可能是...

    基于 Antlr4 的 Hive SQL 解析.zip

    Antlr4是一个强大的解析工具,用于生成解析器和词法分析器,它能处理各种语言的语法,包括SQL。而Hive SQL则是Apache Hive的数据仓库查询语言,常用于大数据处理。 Antlr4的核心功能是解析输入的文本(如SQL语句)...

    anltr-runtime-3.0.1源码

    在这个"anltr-runtime-3.0.1源码"中,我们主要关注的是ANTLR 3.0.1版本的运行时实现。这个源码可以帮助开发者深入了解ANTLR的工作原理,以及如何在自己的项目中自定义和扩展ANTLR的行为。 ANTLR运行时库的主要功能...

    Oracle SQL语法ANLTR

    Grammar for Oracle's SELECT statement for ANTLR v3, target C language

    antlr4rust:用于Rust编程语言的ANTLR4解析器生成器运行时

    ANTLR4工具(解析器生成器) 生成器部件当前位于我的antlr4叉rust-target分支中。此存储库中的版已自动构建为最新版本。 因此,如果您只想生成解析器,或者只想对运行时部分做出贡献,则不必自己构建它。 但是,如果...

    antlr4dart-runtime:Dart 的 ANTLR4 运行时库

    该工具的操作与其他解析器生成器类似,采用特殊的 ANTLR 元语言编写的语法规范,并生成实现识别功能的源代码。 虽然该工具本身是用 Java 实现的,但它具有可扩展的设计,允许使用其他编程语言生成代码。 为了实现 ...

    Antlr入门详解

    Antlr入门详解 中国知网论文:ANRLR安装、使用、文法详解

    antlr4-solidity:优化的antlr4

    具有优化功能的antlr4解析器 antrl4优化 ANTLR 4的优化前叉由Tunnel Vision Laboratories,LLC的Sam Harwell维护。 ANTLR 4的这种“漏洞”实现包含许多功能和性能优化,这些功能和性能优化未包含在参考版本中。 通常...

    klang:基于antlr4和LLVM构建的过程编程语言

    4. 运行构建命令,生成Klang的编译器或者解释器。 5. 使用生成的工具处理Klang源代码,生成可执行文件。 在实际的开发过程中,开发者还需要编写ANTLR4的语法定义文件(通常为`.g4`文件),定义Klang的语言语法规则...

    intellij-plugin-v4:ANTLR v4的IntelliJ插件

    ANTLR v4的IntelliJ Idea插件 适用于ANTLR v4的 2017.1 .. 2020.3插件( )。该插件适用于ANTLR v4语法,包括ANTLR 4.9.1。 与IntelliJ IDEA和其他基于IntelliJ的IDE... 处理单独的解析器和讲座,如TParser.g4和TLexer

    gradle-antlr4-plugin:Gradle插件添加了对ANTLR4的支持

    因为运行时的版本需要与生成器的版本匹配,所以阴影(AKA阴影)是必须的。 我自己进行预阴影(请参阅),因此必须更改生成的类以使用运行时类的新包。 因此,我将此添加为内置功能。用法buildscript { repositories...

    The Definitive ANTLR 4 Reference

    《The Definitive ANTLR 4 Reference》是一本详尽介绍 ANTLR 4 的书籍,由 Terence Parr 编写并出版于 The Pragmatic Bookshelf。本书不仅深入浅出地介绍了 ANTLR 4 的各种功能特性,还提供了大量的实践案例,帮助...

    antlr_psql:适用于Postgres SQL v10的A​​NTLR v4语法(正在进行中)

    PostgresSQL v10的A​​ntlr4语法。 该项目正在开发中。 有关按查询类型分类的测试结果的详细/test_coverage.html ,请参见/test_coverage.html 。 开发是测试驱动的,测试是通过直接从源postgres存储库中抓取sql...

    antlr-runtime-3.5-API文档-中英对照版.zip

    赠送jar包:antlr-runtime-3.5.jar; 赠送原API文档:antlr-runtime-3.5-javadoc.jar; 赠送源代码:antlr-runtime-3.5-sources.jar; 赠送Maven依赖信息文件:antlr-runtime-3.5.pom; 包含翻译后的API文档:antlr-...

    nginx-java-parser:基于ANTLR4语法的Nginx配置解析器

    特征使用ANTLR4解析功能将配置文件转换为AST树JavaCC同样可用(不建议使用) 重建配置文件并将其转储回* .conf 嵌套块支持如果语句支持位置/重写/如果语句支持内未引用的正则表达式评论支持安装将以下依赖项添加到您...

    antlr3.1.3+java2python

    ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架。在这个特定的项目“antlr3.1.3+java2python”,...

Global site tag (gtag.js) - Google Analytics