gpt4 book ai didi

Java System.in、换行符和解析命令行

转载 作者:行者123 更新时间:2023-11-29 04:11:26 28 4
gpt4 key购买 nike

我正在尝试使用 JFlex 和 Jacc 在 Java 中创建一个简单的解析器。为了进行测试,我编写了一个简单的词法分析器组合来识别字符串和数字。我设法连接了词法分析器和解析器,但无法处理从 System.io 发送的换行符 (ASCII 10)。

这里是 lexer.flex

import java.io.*;

%%

%class Lexer
%implements ParserTokens

%function yylex
%int

%{

private int token;
private String semantic;

public int getToken()
{
return token;
}

public String getSemantic()
{
return semantic;
}

public int nextToken()
{
try
{
token = yylex();
}
catch (java.io.IOException e)
{
System.out.println("IO exception occured:\n" + e);
}
return token;
}

%}


ID = [a-zA-Z_][a-zA-Z_0-9]*
NUMBER = [0-9]+
SPACE = [ \t]
NL = [\n] | [\r] | [\n\r]


%%

{ID} { semantic = yytext(); return ID; }
{NUMBER} { semantic = yytext(); return NUM; }
{SPACE} { }
{NL} { System.out.println("Kill the bugger!"); }
<<EOF>> { }

解析器.jacc:

%{

import java.io.*;

%}

%class Parser
%interface ParserTokens

%semantic String

%token <String> ID
%token <String> NUM
%token <String> SPACE

%type <String> inp


%%

inp : inp sim { System.out.println($2); }
| sim { System.out.println($1); }
;

sim : ID
| NUM
;


%%

private Lexer lexer;

public Parser(Reader reader)
{
lexer = new Lexer(reader);
}


public void yyerror(String error)
{
System.err.println("Error: " + error);
}

public static void main(String args[]) throws IOException
{
Parser parser = new Parser(
new InputStreamReader(System.in));

parser.lexer.nextToken();
parser.parse();
}

终端 session 示例:

[johnny@test jacc]$ java Parser
a b c
a
b
Kill the bugger!
1 2 3 4
c
1
2
3
Kill the bugger!

所以当我输入“a b c”时,解析器打印“a”、“b”,然后是该死的 ASCII 10。接下来我输入“1 2 3 4”,然后解析器才打印“c”等。我在Linux/Java 9。

最佳答案

So when I enter "a b c" the parser prints "a", "b" and then the wretched ASCII 10. Next I type "1 2 3 4" and only then the parser prints "c" etc. I am on Linux / Java 9.

这是意料之中的。您的解析器仅打印语义值 sim 符号,并且仅当将它们缩减为或转换为 inp 时。它不会在没有先行标记的情况下执行这样的减少,尽管在您的特定解析器中,当队列末尾的符号是 sim 时,选择总是减少。但是您的词法分析器会在获取此类先行标记的过程中扫描换行符后立即打印换行符消息,然后再进行导致打印先前语义值的缩减。

如果换行符对您的语法很重要,那么您的词法分析器应该为它们发出标记而不是直接对它们进行操作,并且您的语法应该考虑这些标记。例如:

inp : line         { System.out.print($1); }
| inp NL line { System.out.println("NEWLINE WAS HERE"); System.out.print($3); }
;

line : /* empty */ { $$ = new StringBuilder(); }
| line sim { $$ = $1.append($2).append('\n'); }
;

sim : ID
| NUM
;

假定词法分析器发出一个NL 标记而不是 打印消息。请注意,该示例中的所有打印都发生在同一级别。如果打印是您真正想要做的,那么在一个级别上完成所有操作可以大大更容易地控制和预测打印顺序。

注意:解析器有点快而且脏,包含移位/归约冲突。换档的默认分辨率在那里是正确的。除非你让你的词法分析器在输入的末尾插入一个合成的 NL 标记,否则这个冲突很难正确地解决。此外,您当然需要为 line 符号设置正确的标记类型。

另一方面,如果换行符对语法重要,那么您应该完全忽略它们。在这种情况下,您的问题根本不会出现。

关于Java System.in、换行符和解析命令行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54873246/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com