解析上下文敏感语言

时间:2011-02-26 12:03:52

标签: parsing compiler-construction antlr context-sensitive-grammar

我正在读Terence Parr的最终ANTLR参考文献,他说:

  

语义谓词是一种强大的功能   识别上下文敏感的方法   允许的语言结构   要运行的运行时信息   识别

但书中的例子非常简单。我需要知道的是:ANTLR可以解析context-sensitive规则,如:

xAy - > XBY

如果ANTLR无法解析这些规则,是否还有另一种工具可以处理上下文敏感的语法?

2 个答案:

答案 0 :(得分:9)

ANTLR只解析LL(*)的语法。它无法使用语法解析完整的上下文相关语言,例如您提供的示例。我认为Parr的意思是ANTLR可以解析某些需要某些(左)上下文约束的语言。

特别是,可以在“减少动作”上使用语义谓词(我们为GLR解析器执行此操作) 由我们的DMS Software Reengineering Toolkit使用,但我认为ANTLR的想法类似于检查解析器到目前为止收集的任何数据,或者作为其他语义动作的临时副作用,或者在部分构建的解析树中。

对于基于DMS的DMS-based Fortran front end,有一个上下文相关检查,以确保DO循环正确排列。考虑:

 DO  20, I= ...
   DO 10, J = ...
       ...
20  CONTINUE
10  CONTINUE

从解析器的角度来看,词汇流看起来像这样:

DO  <number> , <variable> =  ...
    DO <number> , <variable> = ...
         ...
<number> CONTINUE
<number> CONTINUE

然后解析器如何知道哪个DO语句与哪个CONTINUE语句一起使用? (说每个DO匹配其最接近的CONTINUE将不起作用,因为FORTRAN可以 与多个DO头共享一个CONTINUE语句。

我们在减少以下规则时使用语义谓词“CheckMatchingNumbers”:

block = 'DO' <number> rest_of_do_head newline 
         block_of_statements
         <number> 'CONTINUE' newline ; CheckMatchingNumbers

检查DO关键字后面的数字,以及CONTINUE关键字后面的数字是否匹配。如果语义谓词表明它们匹配,则此规则的减少成功,并且我们已将DO头与正确的CONTINUE对齐。如果谓词失败,则不提出减少(并且从解析本地上下文的候选者中删除此规则);其他一些规则必须解析文本。

使用共享continue来处理FORTRAN嵌套的实际规则和语义谓词比这更复杂,但我认为这是重点。

您想要的是完整的上下文相关解析引擎。我知道人们已经构建了它们,但我不知道任何完整的实现,并且不要指望它们很快。

我确实关注了Quinn Taylor Jackson's MetaS grammar system一段时间;这听起来像是接近实际的尝试。

答案 1 :(得分:0)

Prolog中编写上下文敏感的解析器相对容易。该程序解析字符串[a,is,less,than,b,and,b,is,less,than,c],将其转换为[a,<,b,<,c]

:- initialization(main).
:- set_prolog_flag('double_quotes','chars').

main :-
    rewrite_system([a,is,less,than,b,and,b,is,less,than,c],X),writeln('\nFinal output:'),writeln(X).

rewrite_rule([[A,<,B],and,[B,<,C]],[A,<,B,<,C]).
rewrite_rule([A,is,less,than,B],[A,<,B]).
rewrite_rule([[A,<,B],and,C,than,D],[[A,<,B],and,A,is,C,than,D]).
rewrite_rule([A,<,B],[[A,<,B]]).

rewritten(A) :- atom(A);bool(A).
bool(A) :- atom(A).
bool([A,<,B,<,C]) :- atom(A),atom(B),atom(C).
bool([A,and,B]) :- bool(A),bool(B).


% this predicate is from https://stackoverflow.com/a/8312742/975097
replace(ToReplace, ToInsert, List, Result) :-
    once(append([Left, ToReplace, Right], List)),
    append([Left, ToInsert, Right], Result).

rewrite_system(Input,Output) :-
    rewritten(Input),Input=Output;
    rewrite_rule(A,B),
    replace(A,B,Input,Input1),
    writeln(Input1),
    rewrite_system(Input1,Output).

使用相同的算法,我还编写了一个adaptive parser,可以从其输入中“学习”新的重写规则。