我正在开发一种旧语言的语法。
语言相当复杂,但我想专注于一个特定的问题,所以我做了一个简单的版本。轻量版允许指定赋值语句和简单的表达式,如数学运算或字符串连接。
像这样:
@assign[@var1 (1+3)*2]
@assign[@var2 "foo" $ "bar"]
注意:在赋值语句中,变量不能以 @ 字符开头。该语句也可以写成多行,所以下面的赋值是等价的:
@assign[@var2 "foo" $ "bar"]
@assign[var2 "foo" $ "bar"]
@assign
[@var2 "foo"
$ "bar"]
@assign
[var2 "foo"
$ "bar"]
在这种语言中,您还可以打印出变量的值。问题是没有特定的命令(如@print[...]),编写变量就足够了。像这样:
@var1 @var2
所以,输出代码
@assign[@var1 (1+3)*2]
@assign[@var2 "foo" $ "bar"]
@var1 @var2
是:
8 foobar
这是我到目前为止从 Mu 语法文件开始编写的语法:
grammar Grammar;
////////////////
// PARSER //
////////////////
file
: block EOF
;
block
: stat*
;
stat
: assignment
| print
;
assignment
: ASSIGN LBRACKET variable expr RBRACKET
;
print
: AT ID
;
expr
: expr CONCAT expr #concatExpr
| expr MUL expr #mulExpr
| expr DIV expr #divExpr
| expr ADD expr #addExpr
| expr SUB expr #subExpr
| atom #atomExpr
;
variable
: AT ID
| ID
;
atom
: LPARENS expr RPARENS #parExpr
| INT #intAtom
| STRING #stringAtom
| variable #variableAtom
;
///////////////
// LEXER //
///////////////
ASSIGN : AT 'assign' ;
AT : '@' ;
ID : [a-zA-Z_] [a-zA-Z_0-9]* ;
INT
: [0-9]+
;
LBRACKET : '[' ;
RBRACKET : ']' ;
LPARENS : '(' ;
RPARENS : ')' ;
CONCAT : '$' ;
ADD : '+' ;
SUB : '-' ;
MUL : '*' ;
DIV : '/' ;
WS : [ \t\r\n] -> skip ;
COMMENT : '[*' .*? '*]' -> skip ;
STRING : '"' (~["\r\n] | '""')* '"' ;
为了打印出变量,我开发了一个定制的访问者。访问visitPrint方法,我知道有两个令牌:AT和ID。
现在的问题。
如何修改我的语法,以便以下示例代码
@assign[@var1 "one"]
@assign[var2 "two"]
@assign[var3 var1 $ var2]
Value of var3 is: @var3
生成这个输出?
Value of var3 is: onetwo
目标是使语法能够打印一些自由文本。
我想我必须重写打印规则。但是……怎么办?
print
: AT ID
| ?????? //Help!
;
在这种情况下,目标也是“var3 的值是:”应该是单个标记(不是每个单词一个标记)。
这肯定是错误的方法!
print
: AT ID
| .+?
;
提前致谢。