语法不是终端?

Grammar not terminal?

我目前正在用 C、Bison 和 Flex 开发自己的 shell。

我刚开始学习,但我找不到摆脱语法的方法来让它发挥作用。

我的问题出在 argList 语法上(我认为)。 arg argList { ->next = ; $$ = ; } 用于允许我稍后将多个参数传递到列表中。

没有它,编译后的解析器将按预期工作:它允许我输入 MOS 令牌并执行该函数,然后允许我继续输入具有不同(但仅限于一个)参数的 MOS 令牌。

使用那段语法,解析器允许我输入 MOS 标记,但仅当我按 Ctrl+D 退出时才执行该函数。为什么?

感谢您的任何回答,如果它看起来很糟糕,我很抱歉,但我已经尝试阅读所有可用的文档,但我仍然无法弄清楚。

干杯。

BISON代码


commandList
  : command                { $$ = ; }
  | command commandList  { ->next = ; $$ = ; }
  ;


command
  : MOS argList             { $$ = insert_Mostra( NULL,  ); ExecuteCommands($$); }
  ;

argList
  : arg           { $$ = ; }
  | arg argList   { ->next = ; $$ = ; }
  ;

arg
  : VAR_VALUE { $$ = insert_Args(NULL, ); }
  ;

With that piece of grammar, the parser allows me to input the MOS token, but only executes that function when I Ctrl+D out of it. Why?

简而言之shell,因为 lex 和 yacc 解析器不适合交互式输入。

如果您希望您的 shell 是交互式的,而不仅仅是批处理脚本语言,您需要一种输入机制,从用户那里获取输入行,然后像处理小脚本一样解析它们.

如果您正在使用 lex,这意味着修改扫描器以便它可以从内存中的缓冲区获取输入,而不仅仅是从流中获取输入。

您不能通过调用 yyparse 来获得交互式 shell,它会调用 yylex,从 stdin 中提取字符。如果你这样做,你会 运行 解决各种问题。

首先,输入将被行缓冲(在内核中,在 TTY 级别)。 lex 在您按 Enter 之前看不到您键入的任何内容。

其次,词法分析器和解析器机器人使用 "lookahead"。为了识别标记,正则表达式驱动的词法分析器使用 N 字符前瞻。 LALR(1) 解析器使用一个先行标记。 Lookahead 增加了用户的困惑,因为机器一直在等待更多的输入,即使就用户而言它已经被赋予了一个完整的短语。

用户认为:"why isn't the machine just evaluating the complete, syntactically valid expression I typed?".

机器认为:"according to my grammar, this expression (though inarguably valid) could be just the prefix of a longer one; I need to see what, if anything, comes after it! I need either more input, or an EOF!".

(为什么词法分析器需要前瞻 N 个字符?例如,假设我们有一个具有三个固定标记的词法文法:aaaaabax。假设输入是 aaax。扫描器必须怀疑它可能正在查看 aaaaab 标记,因此它会读取所有 a 字符,直到它命中 x。在到那时,正则表达式自动机意识到 aaaaab 不可能匹配。并且由于令牌不以 x 开头,它必须查看 a 令牌。所以 a token 返回给解析器。因此,输入位置必须一直回溯到第二个 a。换句话说,机器必须超越第一个 aaax 来解析令牌:它使用了前瞻的三个字符。)

对自由格式输入的先行解析会使交互式最终用户产生无法恢复的错误;这是一个用户界面 nonstarter。