使用自定义正则表达式拆分字符串 java
Split string using custom regex java
我正在构建一个编译器。其中一些规格如下:
- 字符串文字用美元符号 ("$") 括起来 - 例如。 $ 字符串示例 $
- 评论用“*”括起来 - 例如。 * 示例评论 *
- 评论可以存在于操作之间的任何地方 - 例如。 4 + * 示例评论 * 5 -(这是不允许的)
现在我必须拆分源代码行以对其进行标记。
案例:
PRINT $ THE FLOAT IS $ * DISPLAY THE RESULT *
正如我将标记化它一样,它应该产生:
PRINT - token is KEYWORD
THE FLOAT IS - token is STRING_LITERAL
DISPLAY THE RESULT - token is COMMENT
我想知道获得它的最有效方法。请注意,我仍然必须验证字符串文字和注释的出现。 (例如,检查是否正确封闭)。到目前为止,我的方法是用空格分隔每一行,当词位包含“$”或“*”时,我将验证字符串文字。这是我的实现:
private void getLexemes(){
for(String line : newSourceCode){
String[] lexemesInALine = line.trim().split("[\s]+");
for(String lexemeInALine : lexemesInALine){
if(!(lexemeInALine.contains("$"))){
lexemes.add(lexemeInALine);
tempTokens.add(findToken(lexemeInALine));
line = line.replaceFirst(lexemeInALine,"").trim();
}else{
validateStringType(line);
break;
}
}
感谢您的帮助。
我假设你的语言是确定性的和上下文无关的?
这意味着,您无法使用正则表达式正确解析它。
您需要的是一个处理令牌流的状态机。
Java 附带两个可能适合您的 类:StreamTokenizer
和 StringTokenizer
.
但您真正想要的是使用数十种解析器生成器中的一种。也许像 ANTLR 这样的东西。
这里有很多描述:
https://en.wikipedia.org/wiki/Comparison_of_parser_generators
如果这一切都失败了,它就是一个有限状态机。
类似的东西
public class Parsy {
enum State { string, comment, token }
void parse(StringTokenizer tokenizer) {
State state = State.token;
List<String> tokens = new ArrayList<>();
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
// figure out type of token
if (token.length() == 1) {
char delim = token.charAt(0);
switch (delim) {
case '$':
switch (state) {
case token: {
// a string literal has started, emit what we have, start a string
printOut(tokens, state);
tokens.clear();
tokens.add(token);
state = State.string;
break;
}
case string: { // parsing a string, so this ends it
printOut(tokens, state);
tokens.clear();
state = State.token;
break;
}
case comment: { // $ is ignored since we are in a comment
tokens.add(token);
break;
}
}
break;
// ...
}
} else {
// not a delimiter token
tokens.add(token);
}
} // end of while
if (state != State.token) {
System.out.println("Oops! Syntax error. I'm still parsing" + state);
}
}
}
我正在构建一个编译器。其中一些规格如下:
- 字符串文字用美元符号 ("$") 括起来 - 例如。 $ 字符串示例 $
- 评论用“*”括起来 - 例如。 * 示例评论 *
- 评论可以存在于操作之间的任何地方 - 例如。 4 + * 示例评论 * 5 -(这是不允许的)
现在我必须拆分源代码行以对其进行标记。 案例:
PRINT $ THE FLOAT IS $ * DISPLAY THE RESULT *
正如我将标记化它一样,它应该产生:
PRINT - token is KEYWORD
THE FLOAT IS - token is STRING_LITERAL
DISPLAY THE RESULT - token is COMMENT
我想知道获得它的最有效方法。请注意,我仍然必须验证字符串文字和注释的出现。 (例如,检查是否正确封闭)。到目前为止,我的方法是用空格分隔每一行,当词位包含“$”或“*”时,我将验证字符串文字。这是我的实现:
private void getLexemes(){
for(String line : newSourceCode){
String[] lexemesInALine = line.trim().split("[\s]+");
for(String lexemeInALine : lexemesInALine){
if(!(lexemeInALine.contains("$"))){
lexemes.add(lexemeInALine);
tempTokens.add(findToken(lexemeInALine));
line = line.replaceFirst(lexemeInALine,"").trim();
}else{
validateStringType(line);
break;
}
}
感谢您的帮助。
我假设你的语言是确定性的和上下文无关的? 这意味着,您无法使用正则表达式正确解析它。
您需要的是一个处理令牌流的状态机。
Java 附带两个可能适合您的 类:StreamTokenizer
和 StringTokenizer
.
但您真正想要的是使用数十种解析器生成器中的一种。也许像 ANTLR 这样的东西。 这里有很多描述:
https://en.wikipedia.org/wiki/Comparison_of_parser_generators
如果这一切都失败了,它就是一个有限状态机。 类似的东西
public class Parsy {
enum State { string, comment, token }
void parse(StringTokenizer tokenizer) {
State state = State.token;
List<String> tokens = new ArrayList<>();
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
// figure out type of token
if (token.length() == 1) {
char delim = token.charAt(0);
switch (delim) {
case '$':
switch (state) {
case token: {
// a string literal has started, emit what we have, start a string
printOut(tokens, state);
tokens.clear();
tokens.add(token);
state = State.string;
break;
}
case string: { // parsing a string, so this ends it
printOut(tokens, state);
tokens.clear();
state = State.token;
break;
}
case comment: { // $ is ignored since we are in a comment
tokens.add(token);
break;
}
}
break;
// ...
}
} else {
// not a delimiter token
tokens.add(token);
}
} // end of while
if (state != State.token) {
System.out.println("Oops! Syntax error. I'm still parsing" + state);
}
}
}