prolog,机器人用语法+解析器移动

时间:2016-01-05 12:17:22

标签: parsing prolog dcg

我在Prolog中坚持一些语法练习。这是我第一次使用语法(使用任何语言)。我需要创建一个解析器,它将计算机器人的目标坐标以及当前指向的方向(作为:n,s,w,e之一)。

可能的举措包括:[go,10](或任何数字),[turn, left][turn, right]。 编写识别正确句子的解析器很容易(我认为......),例如:[go,10,turn,right,go,10]

robot_p-->pol.

pol-->[go],num.
pol-->[go],num,pol.
pol-->[turn],[left].
pol-->[turn],[left],pol.
pol-->[turn],[right].
pol-->[turn],[right],pol.
num-->[D],{number(D)}.
robot(L):-robot_p(L,[]).

但是现在,我不知道,我怎么能积累每一步,所以对于我作为例子给出的句子,结果将是[10,10,e]。我想我应该写一些类似的东西:

robot_p(result)-->pol(result).

但如果是这样,它会怎么样呢?我可以将num更改为:

num(D)-->[D],{number(D)}.

接下来,这将开始:

pol([X,Y,N])-->[go],num(D),{N==n;//here I don't know what next}.

然而,我不确定它是否是好方法,如果是,那么现在该做什么。

修改

我忘了说,我需要传递起始坐标。 因此,对于[0,0,n]并移动[go,10,turn,right,go,10],结果为[10,10,e]

EDIT2:

非常感谢@BretC的帮助。我已按照您的提示创建了令我满意的版本。也许它会帮助某人:)

pol([X])-->[go],num(X).
pol([X| T])-->[go],num(X),pol(T).
pol([left])-->[turn],[left].
pol([left | T])-->[turn],[left],pol(T).
pol([right])-->[turn],[right].
pol([right | T])-->[turn],[right],pol(T).

commands(L,V):-pol(V,L,[]).
move([X,Y,D],V,[X1,Y,D]):-D==n,X1 is X+V.
move([X,Y,D],V,[X1,Y,D]):-D==s,X1 is X-V.
move([X,Y,D],V,[X,Y1,D]):-D==w,Y1 is Y-V.
move([X,Y,D],V,[X,Y1,D]):-D==e,Y1 is Y+V.
rotate(D,P,D1):-P==left,D==n,D1=w.
rotate(D,P,D1):-P==left,D==s,D1=e.
rotate(D,P,D1):-P==left,D==w,D1=s.
rotate(D,P,D1):-P==left,D==e,D1=n.
rotate(D,P,D1):-P==right,D==n,D1=e.
rotate(D,P,D1):-P==right,D==s,D1=w.
rotate(D,P,D1):-P==right,D==w,D1=n.
rotate(D,P,D1):-P==right,D==e,D1=s.
robot_H(D,[],D).
robot_H([X,Y,D],[H|T],K):-number(H),move([X,Y,D],H,ND),robot_H(ND,T,K).
robot_H([X,Y,D],[H|T],K):- \+number(H),rotate(D,H,D1),robot_H([X,Y,D1],T,K).

robot(S,P,K):-commands(P,P1),robot_H(S,P1,K).
num(X)-->[X],{number(X)}.

所以,例如:

?- robot([0,0,n],[go, 10, turn, left,turn,left, go, 20],K).
K = [-10, 0, s]

2 个答案:

答案 0 :(得分:3)

不确定这是否有帮助,但我会使用DGC构建一个代表自然语言的子句列表,然后处理这些子句。

例如,如果您将以下参数添加到语法中......

pol([move(X)])-->[go],num(X).
pol([move(X) | T])-->[go],num(X),pol(T).
pol([turn(left)])-->[turn],[left].
pol([turn(left) | T])-->[turn],[left],pol(T).
pol([turn(right)])-->[turn],[right].
pol([turn(right) | T])-->[turn],[right],pol(T).
num(D)-->[D],{number(D)}.

...现在你可以得到一个'命令'列表,例如......

4 ?- pol(X, [go,10,turn,left,go,10], []).
X = [move(10), turn(left), move(10)] .

这就是解析位,现在你需要编写子句来处理模拟,例如......

% Parses grammar and processes commands
robot(SENTANCE, XOut, YOut) :-
    % Parse the sentance
    pol(COMMANDS, SENTANCE, []),
    % Process the commands
    process(COMMANDS, north, 0, 0, XOut, YOut).

% process(COMMAND_LIST, HEADING, XSTART, YSTART, XOUT, YOUT)

% Case 1: No commands to process, return current position
process([], _, X, Y, X, Y).
% Case 2: Process a single command then process the rest of the commands
process([COMMAND | T], Heading, XIn, YIn, XOut, YOut) :-
    do_command(COMMAND, Heading, XIn, YIn, HeadingTmp, XTmp, YTmp),
    process(T, HeadingTmp, XTmp, YTmp, XOut, YOut).

% do_command(COMMAND, HEADING_START, XSTART, YSTART, HEADING_OUT, XOUT, YOUT).
% Move in current direction command
do_command(move(N), Heading, X, Y, Heading, XOut, YOut) :-
    x_delta(Heading, N, XDelta),
    y_delta(Heading, N, YDelta),
    XOut is X + XDelta,
    YOut is Y + YDelta.
% Turn command  
do_command(turn(Dir), HeadingIn, X, Y, HeadingOut, X, Y) :-
    turn(HeadingIn, Dir, HeadingOut).

% Utility clauses to help with deltas + turns
x_delta(north, _, 0).
x_delta(south, _, 0).
x_delta(east, X, X).
x_delta(west, X, Y) :- Y is -X.

y_delta(north, X, X).
y_delta(south, X, Y) :- Y is -X.
y_delta(east, _, 0).
y_delta(west, _, 0).

turn(north, right, east).
turn(east, right, south).
turn(south, right, west).
turn(west, right, north).

turn(north, left, west).
turn(east, left, north).
turn(south, left, east).
turn(west, left, south).

示例输出......

2 ?- robot([go, 10, turn, left, go, 11], X, Y).
X = -11,
Y = 10

答案 1 :(得分:2)

我会应用每个动作来改变当前状态,获得更新状态。

pol(Curr,Curr) --> [].
pol(Curr,Last) --> move(Curr,Next), pol(Next, Last).

move(s(X,Y,D), s(X1,Y1,D)) -->
    [go, N], {
     D == n -> X1 is X, Y1 is Y+N
    ;D == e -> X1 is X-N, Y1 is Y
     ...
    }.

move(s(X,Y,D), s(X,Y,D1)) -->
    [turn, left], { D == n -> D1 = e ; ... }.

并用短语/ 2

来调用它
?- phrase(pol(s(0,0,n),F), [go,10]).