我目前使用 ANTLR 在 Java 中实现了一种可用的、简单的语言。我想做的是将其嵌入纯文本中,与 PHP 类似。
例如:
Lorem ipsum dolor sit amet
<% print('consectetur adipiscing elit'); %>
Phasellus volutpat dignissim sapien.
我预计生成的令牌流将类似于:
CDATA OPEN PRINT OPAREN APOS STRING APOS CPAREN SEMI CLOSE CDATA
我怎样才能实现这个目标,或者有更好的方法吗?
对于可能超出范围的内容没有任何限制<%
堵塞。我假设类似<% print('%>'); %>
根据 Michael Mrozek 的回答,这是可能的,但在这种情况之外,<%
总是指示代码块的开始。
实施示例
我根据 Michael Mrozek 的答案中给出的想法开发了一个解决方案,使用 ANTLR 的门控语义谓词模拟 Flex 的启动条件:
lexer grammar Lexer;
@members {
boolean codeMode = false;
}
OPEN : {!codeMode}?=> '<%' { codeMode = true; } ;
CLOSE : {codeMode}?=> '%>' { codeMode = false;} ;
LPAREN : {codeMode}?=> '(';
//etc.
CHAR : {!codeMode}?=> ~('<%');
parser grammar Parser;
options {
tokenVocab = Lexer;
output = AST;
}
tokens {
VERBATIM;
}
program :
(code | verbatim)+
;
code :
OPEN statement+ CLOSE -> statement+
;
verbatim :
CHAR -> ^(VERBATIM CHAR)
;
但在这种情况之外,
在这种情况下,首先扫描文件中的嵌入代码,一旦获得这些代码,就使用专用解析器解析嵌入代码(没有之前的噪音)<%
并在之后%>
tags).
ANTLR 可以选择让词法分析器仅解析输入文件的一小部分并忽略其余部分。请注意,在这种情况下,您无法创建“组合语法”(解析器和词法分析器合二为一)。以下是创建这样一个“部分词法分析器”的方法:
// file EmbeddedCodeLexer.g
lexer grammar EmbeddedCodeLexer;
options{filter=true;} // <- enables the partial lexing!
EmbeddedCode
: '<%' // match an open tag
( String // ( match a string literal
| ~('%' | '\'') // OR match any char except `%` and `'`
| {input.LT(2) != '>'}?=> '%' // OR only match a `%` if `>` is not ahead of it
)* // ) <- zero or more times
'%>' // match a close tag
;
fragment
String
: '\'' ('\\' . | ~('\'' | '\\'))* '\''
;
如果您现在从中创建一个词法分析器:
java -cp antlr-3.2.jar org.antlr.Tool EmbeddedCodeLexer.g
并创建一个小测试工具:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String source = "Lorem ipsum dolor sit amet \n"+
"<% \n"+
"a = 2 > 1 && 10 % 3; \n"+
"print('consectetur %> adipiscing elit'); \n"+
"%> \n"+
"Phasellus volutpat dignissim sapien. \n"+
"foo <% more code! %> bar \n";
ANTLRStringStream in = new ANTLRStringStream(source);
EmbeddedCodeLexer lexer = new EmbeddedCodeLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
for(Object o : tokens.getTokens()) {
System.out.println("=======================================\n"+
"EmbeddedCode = "+((Token)o).getText());
}
}
}
全部编译:
javac -cp antlr-3.2.jar *.java
最后通过执行以下操作来运行主类:
// *nix/MacOS
java -cp .:antlr-3.2.jar Main
// Windows
java -cp .;antlr-3.2.jar Main
它将产生以下输出:
=======================================
EmbeddedCode = <%
a = 2 > 1 && 10 % 3;
print('consectetur %> adipiscing elit');
%>
=======================================
EmbeddedCode = <% more code! %>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)