【问题标题】:How can I improve the following grammar?如何改进以下语法?
【发布时间】:2012-08-01 14:27:03
【问题描述】:

我试图找出我在下面的代码中出错的地方。

弹性输入:

%{
        #include "jq.tab.h"
        void yyerror(char *);
%}
method          add|map|.. and other methods go here

%%

"/*"            { return CS; }

"*/"            { return CE; }

"jQuery"        {
                printf("%s is yytext\n", yytext);
                return *yytext;
                }

"args"          { return ARGUMENT; }

{method}        { return METHOD; }

[().\n]         { return *yytext; }

[ \t]+          { return WS; }

.               { return IGNORE; }

%%

int yywrap(void) {
        return 1;
}

野牛输入:

%{
        #include <stdio.h>
        int yylex(void);
        void yyerror(char *);
%}

%token ARGUMENT METHOD IGNORE WS CS CE
%error-verbose

%%

stmts:
        stmt '\n'               { printf("A single stmt\n"); }
        | stmt '\n' stmts       { printf("Multi stmts\n"); }
        ;

stmt:
        jQuerycall                      { printf("A complete call ends here\n"); }
        | ignorechars                   { printf("Ignoring\n"); }
        | ignorechars WS jQuerycall     { printf("ignore+js\n"); }
        | jQuerycall WS ignorechars     { printf("js+ignore\n"); }
        | optionalws stmt optionalws
        | CS stmt CE                    { printf("comment\n"); }
        ;

jQuerycall:
        'jQuery' '(' ARGUMENT ')' '.' methodchain       { printf("args n methodchain\n"); }
        | 'jQuery' '(' ')' '.' methodchain              { printf("methodchain\n"); }
        | 'jQuery' '(' ARGUMENT ')'                     { printf("args\n"); }
        | 'jQuery' '(' ')'                              { printf("empty call\n"); }
        ;

methodchain:
        methodchain '.' methodcall
        | methodcall
        ;

methodcall:
        METHOD '(' ')'
        ;

ignorechars:
        IGNORE
        | IGNORE optionalws ignorechars
        ;

optionalws:
        | WS
        ;

%%

void yyerror(char *s) {
        fprintf(stderr, "%s\n", s);
}

int main(void) {
        yyparse();
        return 0;
}

我的目标是识别任何 jQuery 调用及其所有元素,并忽略任何其他语句/字符串。也忽略 cmets。现在,这段代码做了很多假设——比如 'args' 是 jQuery() 中唯一的选择器元素。

编辑

我正在使用以下输入输出案例。像 10 和 12 这样的案例是我想要弄清楚的:

> 1.input: statement\n output: Ignoring
> 
> 2.input: statement statement\n output: Ignoring
> 
> 3.input: statement statement statement\n output: Ignoring
> 
> 4.input: jQuery()\n output: jQuery is yytext empty call A complete call ends here
> 
> 5.input: jQuery(args)\n output: jQuery is yytext args A complete call ends here
> 
> 6.input: jQuery().add()\n output: jQuery is yytext methodchain A complete call ends here
> 
> 7.input: jQuery(args).add().map()\n output: jQuery is yytext args n methodchain A complete call ends here
> 
> 8.input: /*comment*/\n output: Ignoring comment
> 
> 9.input: /*jQuery()*/\n output: jQuery is yytext empty call A complete call ends here comment
> 
> 10.input: /* comment */\n output: syntax error, unexpected CE, expecting IGNORE
> 
> 11.input: var a = b\n output: Ignoring
> 
> 12.input: var a = jQuery(args)\n output: jQuery is yytext syntax error, unexpected 'jQuery', expecting IGNORE

【问题讨论】:

  • 如果您需要帮助,请告诉我们您的问题的症状是什么,以及为什么您很难诊断出根本原因。我们很少有人会费心阅读您的代码来尝试猜测您的症状是什么。如果你很懒,我们也是。
  • @IraBaxter,'已经编辑了描述以包括我关心的案例。谢谢你:)

标签: jquery parsing bison flex-lexer


【解决方案1】:

在您的 lex 文件中,规则:

"jQuery"        {
                printf("%s is yytext\n", yytext);
                return *yytext;
                }

当它看到 jQuery 的输入字符串时返回标记 'j'。由于您的野牛文件从不使用令牌 'j' 做任何事情,这通常会给您一个语法错误。

您需要将 JQUERY 添加到您的 %token 声明中,并让此 lex 规则返回。

编辑

通常注释可以出现在程序中的任何位置(在任何两个其他标记之间)并且完全被忽略。所以处理它们的最简单方法是在词法分析器中:

%x comment
%%
"/*"           { BEGIN comment; }
<comment>.     ;
<comment>"*/"  { BEGIN 0; }

这将跳过 cmets(根本不返回任何标记),因此语法不需要担心它们。如果您不想使用词法分析器启动状态,则可以改用复杂的正则表达式:

"/*"([^*]|\*+[^*/])*\*+"/"          ;

【讨论】:

  • 好的,我修好了。还有规则ignorechars:IGNORE | IGNORE optionalws ignorechars 有一个正确的递归。也修复了.. 修复案例 10
【解决方案2】:

我想我可以给你一个解决案例 10 的解决方案,但还有一个更深层次的问题。

既然案例 8 给出了你期望的结果,我推断输入

/*comment*/

得到骄傲的认可

stmt: CS stmt CE

也就是说字符串“comment”被识别为stmt。但是,当您在 CSstmt 之间添加空格时,解析失败,这是您的情况 10。您可以通过将您的产品重写为来修补此问题

stmt: CS optionalws stmt optionalws CE

但更深层次的问题是您的解析器无法识别其他 cmets,例如

/* This is a remarkable remark, isn't it? */ 

/**
 * This is a multi-line comment.
 */

【讨论】:

    猜你喜欢
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    相关资源
    最近更新 更多