使用ANTLR构建PowerScript语法分析器(4)

Posted by dohkoos on April 27th, 2008 (585 views)

什么是表达式
简单的来说,表达式就是操作数和操作符根据语法规则结合后的结果,它通常被用来执行在变量或值上的操作处理。

主表达式(Primary Expression)
到现在PowerScript的词法分析已经写的差不多了,接下来就要开始写语法分析。语法分析的主要组成部分是表达式(expression),而表达式的主要组成部分则是主表达式。主表达式包含了大部分简单的表达式,如文字量(Literals),字段存取,方法调用和数组存取等。带圆括号的表达式通常也被认为是主表达式。其常见形式如下:

(x)
x.y
f(x)
a[x]
x++
x--
new

super,parent,this分析
什么时候使用super
当直接子类中存在有和父类相同签名的事件或函数时

使用super有哪些限制
1. 不能调用父类中控件的脚本 (猜测super后只能跟随"::"符号)
2. 只能在直接子类的函数或事件中调用父类的事件或函数

在哪些脚本中可以使用parent
1. 窗口中的控件,此时parent指代包含该控件的窗口
2. 定制的用户对象中的控件,这时parent指代定制的用户对象
3. 菜单,这时候parent指代该菜单的上一级菜单

收集的一些script语句

this.ls_array[1]
this.event pfc_addrow()
this.event rowfocuschanged(ll_row)
this.uo_1.function hallo()
post function column_order_update_from_grid()
event ue_process()

close(parent)
parent.enabled
parent.hide()
parent.event ue_postconstructor()
parent.function static trigger wf_process( )

super::create
super::clicked;
super::event clicked()
super::event clicked(xpos, ypos, row, dwo)
super::of_remove_tail(anv_tailnode)
super::event trigger selectionchanging(oldindex, newindex)

iu_tab_postings.post of_enable_sort(dw_main, dw_detail, false)
w_main.event doubleclicked(flags, xpos, ypos)
dw_main.event pfc_retrieve()
cb_ok.event trigger clicked()
cb_ok.triggerevent(clicked!)

主表达式语法,还需要再继续完善

primary_expression
    :   '(' expression ')'
    |   IDENTIFIER '!'?    // build-in constant
    |   literal
    |   '::' IDENTIFIER    // global variables
    |   call_type IDENTIFIER arguments    // example: post function to_string()
    |   'create' 'using'? (STRING_LITERAL|IDENTIFIER)
    |   'destroy' IDENTIFIER
    |   'super' '::' call_type? IDENTIFIER arguments?
    |   objectname ('.' IDENTIFIER)* identifier_suffix?
    ;

objectname
    :   'this'
    |   'parent'
    |   IDENTIFIER
    ;

call_type
    :   ( 'function'
        | 'event'
        | 'static'
        | 'dynamic'
        | 'trigger'
        | 'post'
        )+
    ;

identifier_suffix
    :   arguments ('.' IDENTIFIER arguments)*    // cascaded calling
    |   '[' expression_list? ']'
    |   call_type IDENTIFIER arguments
    ;

arguments
    :   '(' expression_list? ')'
    ;

literal
    :   STRING_LITERAL
    |   INTEGER_LITERAL
    |   FLOAT_LITERAL
    |   BOOLEAN_LITERAL
    ;

Related Posts

People who read this, also read...

使用ANTLR构建PowerScript语法分析器(3)

Posted by dohkoos on September 7th, 2007 (354 views)

转义字符(Special ASCII Characters)
PowerScript中转义字符是以波浪号(~)开头。下图是PowerScript支持的完整的转义字符,#字符表示数字。Decimal由三个十进制数组成,范围是000-255;Hexadecimal由两个十六进制数组成,范围是00-FF;Octal由三个八进制数组成,范围是000-377。

Special ASCII Characters

注意:#表示数字是必须的。比如,必须用~007这种样式来表示转义字符,而不能是~7这种样式。

这里是转义字符的词法代码

ESCAPE
    :   '~' ('n'|'t'|'v'|'r'|'f'|'b'|'\"'|'\''|'~')
    |   DecimalEscape
    |   HexEscape
    |   OctalEscape
    ;

fragment
DecimalEscape
    :   '~' ('0'..'1') ('0'..'9') ('0'..'9')    // 000 - 199
    |   '~' '2' ('0'..'5') ('0'..'5')   // 200 - 255
    ;

fragment
HexEscape
    :   '~h' ('0'..'9'|'a'..'f'|'A'..'F') ('0'..'9'|'a'..'f'|'A'..'F')  // 00 - FF
    ;

fragment
OctalEscape
    :   '~o' ('0'..'3') ('0'..'7') ('0'..'7')   // 000 - 377
    ;

续行(Statement Continuation)
通常情况下,PowerScript的一条语句书写在一行上,语句书写完毕后,按Enter键转到下一行,开始下一条语句。有时候,为了阅读方便等原因,需要把一条语句书写在几行上,这时就需要使用续行符了。PowerScript的续行符是&字符,它放在一行的末尾指示下一行是当前行的继续,并且续行符必须是一行的最后一个字符。

CONTINUEDLINE
    :   '&' NEWLINE
    ;

字符和字符串常量(Character and String Literal)
PowerScript程序中字符和字符串文字常量没有明显的区别。字符文字常量是指由单引号(')或双引号(")括起来的一个ASCII字符,例如:
char c
c = 'T'
c = "T"
字符串文字常量则是指由单引号(')或双引号(")括起来的不多于1024个的ASCII字符,例如:
string s
s = 'This is a string'
s = "This is a string"
由于两者没有明显区别,因此在词法分析阶段只能将两者都作为字符串文字常量来处理。至于到底是字符还是字符串文字常量,只有到了语意分析阶段才能作出判断(字符串文字常量支持续行符)。

STRING_LITERAL
    :   ( '\'' (ESCAPE|CONTINUEDLINE|~('~'|'r'|'n'|'\''))* '\''
        | '\"' (ESCAPE|CONTINUEDLINE|~('~'|'r'|'n'|'\"'))* '\"'
        )
        {
            System.out.println("string>" + getText());
        }
    ;

数字和布尔常量(Numeric and Boolean Literal)

INTEGER_LITERAL
    :   ('0'|'1'..'9' ('0'..'9')*)
    ;

FLOAT_LITERAL
    :   ('0'..'9')+ '.' ('0'..'9')* Exponent?
    |   '.' ('0'..'9')+ Exponent?
    |   ('0'..'9')+ Exponent?
    ;

BOOLEAN_LITERAL
    :   ('true'|'false')
    ;

fragment
Exponent
    :   ('e'|'E') ('+'|'-')? ('0'..'9')+
    ;

标识符(Identifier)
标识符规则可以参看《PowerBuilder标识符versus Java标识符》一文,以下是标识符的词法代码。

DENTIFIER
    :   Letter (Letter|'0'..'9'|'$'|'#'|'%')*    // 暂时不支持短横线(-)
        {
            System.out.println("identifier>" + getText());
        }
    ;

fragment
Letter
    :   ('A'..'Z'|'a'..'z'|'_')
    ;

问题:PowerScript是否支持变量名的续行?
PowerBuilder V9.0 Build 5507 不支持
PowerBuilder V9.0.1 Build 7171 不支持
PowerBuilder V8.0.3 Build 9704 不支持

Do not split a line by inserting the continuation character within a variable name. This causes an error and the statement fails.

结论:PowerScript不支持变量名的续行。

Related Posts

People who read this, also read...

使用ANTLR构建PowerScript语法分析器(2)

Posted by dohkoos on September 3rd, 2007 (390 views)

在前篇文中写的词法分析文件存在有两个小问题:
1. 处理换行符和回车符的词法定义有重复,在WS和EndOfLine中都有出现
2. 像/* comments /* nested comments */ */这种嵌套注释会被输出成

antlr comments

第一个问题比较容易解决,只要将EndOfLine前的fragment去掉,再将WS改成下面这样就可以了。

WS
    :   (' '|'\t'|'\u000C') {$channel=HIDDEN;}
    ;

第二个问题则可以通过计数器来处理。先初始化一个计数器变量depthOfComments来标记块注释的深度,当遇到'/*'时就加一,遇到'*/'时则减一。输出时只要判断depthOfComments是否等于0就行了。

BLOCK_COMMENT
@init {
    int depthOfComments = 0;
}
    :   '/*' {depthOfComments++;}
        ( options {greedy=false;}
        : ('/' '*')=> BLOCK_COMMENT {depthOfComments++;}
        | '/' ~('*')
        | ~('/')
        )*
        '*/' {depthOfComments--;}
        {
            if (depthOfComments == 0) {
                System.out.println("bc>" + getText());
            }
        }
    ;

Related Posts

People who read this, also read...

使用ANTLR构建PowerScript语法分析器(1)

Posted by dohkoos on August 23rd, 2007 (534 views)

首先,让我们从最简单的做起,先实现一个能正确分析PowerScript注释的词法文件。PowerScript支持两种注释形式:单行注释(//)和多行注释(/*...*/)。

单行注释以双斜杠(//)起头,直到遇到行结束符为止,所以在这里要先明确一下行结束符用什么表示。在DOS系统中行结束符用'\r\n'表示,在Unix系统中行结束符用'\n'表示,现在的Mac系统也是以'\n'表示行结束符,但早期的Mac系统中行结束符则是以'\r'表示。所以兼容这几种操作系统的行结束符定义为:

fragment
EndOfLine
    :   '\r' '\n'   // DOS
    |   '\r'    // Mac
    |   '\n'    // Unix
    ;

现在,有了行结束符定义,就可以定义单行注释的词法规则了:

LINE_COMMENT
    :   '//' ~('\n'|'\r')* EndOfLine
    ;

通常的多行注释词法规则是这样的

BLOCK_COMMENT
    :   '/*' ( options {greedy=false;} : . )* '*/'
    ;

但由于PowerScript支持嵌套注释,所以上面的规则无效,必须重新定义。当词法分析器遇到'/*'后就进入了多行注释。这时假如遇到了'/'符号,词法分析器必须预取一个字符,看这个字符是否是'*'。如果是的话,就进入了嵌套的多行注释,否则,则还是处在多行注释中。

BLOCK_COMMENT
    :   '/*'
        ( options {greedy=false;}
        : ('/' '*')=> BLOCK_COMMENT    // 在多行注释中遇到'/*',用语法断言确定是嵌套多行注释
        | '/' ~('*')    // 在多行注释中只遇到'/',而没有紧跟着的'*'
        | ~('/')    // 在多行注释中没有遇到'/'
        )*
        '*/'
    ;

当然,我们还希望忽略空格、制表符、回车符、换行符等无意义字符。

WS
    :   (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;}
    ;

测试样例

/* This is a single-line comment.   */
/* /This is a single-line comment. */
/* *This is a single-line comment. */
/* This comment /* */*/
/* This comment /* The nested comment */ */
/*  This comment starts here.
 /*  This is the start of a nested comment.
 The nested comment ends here.  */
 The first comment ends here.  */
/* This comment starts here,
 continues to this line,&
 and finally ends here. */
// This entire line is a comment.
// This entire line is a comment. //
// /This entire line is a comment.
// /This entire line is a comment.
// This entire line is a comment. */
// This entire line is a comment. /*

语法文件PowerScript.g的内容如下:

grammar PowerScript;

program
    :   LINE_COMMENT+
    |   BLOCK_COMMENT+
    ;

LINE_COMMENT
    :   '//' ~('\n'|'\r')* EndOfLine
        {
            System.out.println("lc>" + getText());
        }
    ;

BLOCK_COMMENT
    :   '/*'
        ( options {greedy=false;}
        : ('/' '*')=>; BLOCK_COMMENT
        | '/' ~('*')
        | ~('/')
        )*
        '*/'
        {
            System.out.println("bc>" + getText());
        }
    ;

WS
    :   (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;}
    ;

fragment
EndOfLine
    :   '\r' '\n'   // DOS
    |   '\r'    // Mac
    |   '\n'    // Unix
    ;

Related Posts

People who read this, also read...