首页 文章

如何从函数调用中删除逗号和括号

提问于
浏览
0

在使用快乐解析器编写的函数式语言编译器中,与yacc / bison非常相似,我使用以下规则实现了列表并列出了一些核心函数 mapconcatfilter

Exp:
...
| concat '(' Exp ',' Exp ')'         { Concat $3 $5 }
| map '(' Exp ',' Exp ')'            { Map $3 $5 }
| filter '(' Exp ',' Exp ')'         { Filter $3 $5 }

这很好用,但在大多数函数式语言中没有paranthesis或逗号,所以我宁愿写 map myfun [1,2,3] 而不是 map(myfun, [1,2,3]) . 语法中的明显修改如下:

Exp:
...
| concat Exp Exp         { Concat $2 $3 }
| map Exp Exp            { Map $2 $3 }
| filter Exp Exp         { Filter $2 $3 }

但是这种修改包括许多减少 - 减少冲突 . 如何在没有逗号和paranthesis的情况下实现函数调用的解析?

我能提取的最小的冲突语法是这样的:

Exp :
    -- Math
     Exp '+' Exp                         { Op $1 Add $3 }
    | Exp '-' Exp                        { Op $1 Sub $3 }

    -- Literals
    | num                                { Num $1 }
    | '-' num %prec NEGATIVE             { Num (-$2) }

    -- Lists
    | map Exp Exp                        { Map $2 $3 }

它产生4个减少/减少冲突 . 删除任何规则也会导致冲突 . 如果你有兴趣,这是full grammar .

1 回答

  • 1

    问题在于,由于函数应用程序中没有令牌,基于令牌的优先级冲突解决方案不能很好地工作 - 当它试图决定可能是函数应用程序的转移并减少其他表达式时,先行标记是参数表达式的开头;没有可以使用的“空格”标记 .

    要解决该问题并使其工作,您需要将可能是表达式(FIRST(Exp)中的每个标记)的每个标记的优先级设置为函数应用程序的优先级 . 如果这些令牌中的任何一个需要一些其他优先权(例如,任何可能是中缀或前缀的令牌),这会变得更加棘手并且可能无法工作 .

    可能更好的替代方法是根本不使用优先级规则 - 而是使用针对每个优先级的不同规则消除语法歧义:

    Exp: Term | Exp '+' Term
    Term: Factor | Term '*' Factor
    Factor: Primary | Factor Primary
    Primary: num | id | '(' Exp ')'
    

相关问题