2013-09-06 2 views
3

이 답변은 Very basic dcg prolog syntax 조금 도와 줬지만 [X]는 다음 문자 만 가져옵니다. 전체 문자를 읽고 싶습니다.DCG : DCG {} 코드 내의 변수에 나머지를 할당

GNU Prolog를 사용하여 명령 옵션 파서를 작성하고 있는데 DCG 지점에 머물러 있습니다. 나는 "foo는 --as = JSON"에 대한 예를 들어 보이는이 문법 규칙을 가지고, 난 그냥 "어떤"의 결과에 코드 내 손을 얻는 방법 작동하지 않을 수 있습니다

as_opt --> "--as=", anything, { c(as_opt)}, !. 
anything --> [], {c(anything_match)}. 

을 그리고 그 gprolog 확장은 다음과 같습니다

as_opt([45, 45, 97, 115, 61|A], B) :- 
     anything(A, C), 
     c(as_opt), !, 
     C = B. 

anything(A, B) :- 
     c(anything_match), !, 
     A = B. 

은 "C()"조건은 간단 단지 형식()으로 실행 규칙이 그래서 그것을 실행으로 무슨 일이 일어나고 있는지 볼 수 stdout에 있음을 추적하는 데 사용됩니다. 나는 손으로 코드를 작성했다면 내가 할 것이다 :

%% for completeness here! 
c(Msg) :- format("Processed ~w~n", [Msg]). 

as_opt([45, 45, 97, 115, 61|A], B) :- 
     anything(A, C), 
     c(as_opt), !, 
     C = B, 
     { g_assign(gvValue, B)}. %% just for example 

원래 DCG로 돌아 간다 :

as_opt --> "--as=", anything, { c(as_opt), gassign(gvValue, ???)}, !. 

은 그래서가는 곳 "???" 입니다. 그것은 가능한가 ... 그것은 틀림 없다. DCP 규칙을 다시 확장하는 방법에 대한 gprolog 규칙을 다시 읽으 려합니다. 그러나 (facepalm) 나 자신에 대한 것이지만 그 동안은 도움이 가장 환영받을 것입니다.

감사합니다. Sean.

답변

3

당신은 어떤 목록을 설명하는 간단한 DCG 비 터미널 중 하나를 요구하고 :

list([]) --> []. 
list([L|Ls) --> [L], list(Ls) 
:

list --> []. 
list --> [_], list. 

실제로 설명되는 목록에 액세스하기를, 당신은 인수를 소개합니다

다음과 같이 사용할 수 있습니다.

as_opt(Option) --> "--as=", list(Option). 
+0

매트, 좋은 대답. 나는 Prolog와 멍청이이고 DCG 규칙은 아직 미묘한 차이를 느껴야한다고 생각합니다! 나는 그걸로 일할 것이고 의심의 여지가 그것을 추적하는 것은 나를 더럽 히게 도움이 될 것입니다. 감사. 좋은 간결한 대답. –

+0

Bummer. 코드를 해봤어야, 너무 흥분 했어! 그것은 아직 나를 위해 작동하지 않습니다. 옵션의 값으로 "[]"을 출력합니다. 나는 더 열심히 노력할 것이다. .. 곧 나는 추측한다. .. –

+0

매트, 나는 규칙의 순서가 틀리다라고 생각한다. 빈 목록 케이스를 넣으면 마지막 것이 훨씬 좋아 보인다! 그 부분에 대한 감시가 당신 생각입니까? –

1

저는 전역 변수를 사용하지 않아야한다고 생각합니다. 대신, 값을 다시 얻기 위해, DCG 절에 인자 (들)을 추가

anything([C|Cs]) --> [C], anything(Cs). 
anything([]) --> []. 

그렇지 않으면, 나머지 구문/3의 마지막 인수로 사용할 수 있습니다, 규칙이 제목 일치 '소모', succeded 후.

+0

나는 프롤로그 비교적 새로운 오전. 나는 구두법에 대한 설명서를 읽어야한다. 나는 명령 행 인수를 반복적으로 반복하여 "손으로"시작 규칙을 부르고 있기 때문에 추측한다. gprolog를 사용하여 대규모 응용 프로그램을 작성 중이므로 전역 변수를 사용했습니다. 명령 행 옵션을 구문 분석하는 것은 내가해야 할 일 중 하나 일뿐입니다. 이는 코드의 다른 비트를 쉽게 만들며 내 전역 변수는 명령 행 모듈에서 설정 한 후에 만 ​​엄격하게 읽혀집니다. 나는 당신의 예약을 완전히 이해합니다. –

3

더 나은 해결책이 있습니다. 더 빠르고 더듬 거리는 선택 포인트를 피할 수있는 매트에 의해 늑골이 붙어 있지만, 예를 들어,에 발견 된 바와 같이 call//1 내장형 비 터미널에 대한 지원이 필요합니다. SWI-Prolog, GNU Prolog 및 기타 Prolog 컴파일러. 또한 Logtalk. 고려 : SWI - 프롤로그 사용

as_opt(Option) --> "--as=", list(Option). 

list([L|Ls]) --> [L], list(Ls). 
list([]) --> []. 

as_opt2(Option) --> "--as=", call(rest(Option)). 

rest(Rest, Rest, _). 

더 차이를 설명하기 위해 :

?- phrase(as_opt(Option), "--as=json"). 
Option = [106, 115, 111, 110] ; 
false. 

?- phrase(as_opt2(Option), "--as=json"). 
Option = [106, 115, 111, 110]. 

?- time(phrase(as_opt(Option), "--as=json")). 
% 9 inferences, 0.000 CPU in 0.000 seconds (57% CPU, 562500 Lips) 
Option = [106, 115, 111, 110] ; 
% 2 inferences, 0.000 CPU in 0.000 seconds (63% CPU, 133333 Lips) 
false. 

?- time(phrase(as_opt2(Option), "--as=json")). 
% 6 inferences, 0.000 CPU in 0.000 seconds (51% CPU, 285714 Lips) 
Option = [106, 115, 111, 110]. 

스퓨리어스 선택 점은 list//1 비 터미널의 정의에서 비롯됩니다. 성능 차이는 call//1은 암시 적 목록 인수에 단순히 액세스 할 수 있지만 list//1 비 터미널은 암시 적 인수의 요소별로 목록 복사 요소를 수행하고 있습니다.call//1 성능, 접두사 후 문자 수의 독립적 인 일정 동안 결과적으로, list//1 버전의 성능은 --as= 접두사 다음 문자에 선형은 다음과 같습니다

?- time(phrase(as_opt(Option), "--as=jsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjson")). 
% 54 inferences, 0.000 CPU in 0.000 seconds (83% CPU, 2700000 Lips) 
Option = [106, 115, 111, 110, 106, 115, 111, 110, 106|...] ; 
% 4 inferences, 0.000 CPU in 0.000 seconds (69% CPU, 137931 Lips) 
false. 

?- time(phrase(as_opt2(Option), "--as=jsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjson")). 
% 6 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 333333 Lips) 
Option = [106, 115, 111, 110, 106, 115, 111, 110, 106|...]. 
+0

우연히! 파울로, 아주 좋은 대답 인 것 같지만 이해의 측면에서 내 머리 위로 똑바로입니다! 나는 Prolog를 한두 달 동안 사용 해왔다. 나는 당신이 aobut 선택 지점을 의미한다는 것을 알 수 있습니다. 그것은 실제로 좋은 점이며, 여전히 머리를 완전히 풀 필요가 있습니다. 현실은 DCG가 한 번만 실행되어 아마도 4 ~ 5 개 이상의 명령 줄 인수를 구문 분석하지 않습니다. 그냥 일해야합니다. 그래도 고마워. :) –

+0

'call // 3' 비 - 터미널 호출은 첫 번째 인수 ('rest (Rest)'클로저)가 공유되고 두 개의 추가 인수가있는'call/3' 내장 된 조건부 호출로 변환됩니다 'call/3' 호출에서)은 DCG 규칙의 두 가지 암시적인 인수입니다. 'rest/3' 술어의 정의는 closure 인수를 첫 번째 (일명 "입력") 암시 적 인수와 통합합니다. 'call // 1' 내장 비 - 터미널을 보조 조건 자 (예 :'rest/3')를 필요로하지 않는 인수로 람다 표현식을 사용하는 대안 솔루션으로 사용할 수 있습니다. 그러나 이것은 불쾌한 속임수입니다. 게시하지 마십시오. –

+0

Paulo, 우린 절대로 실제 생활을해서는 안됩니다. 뇌와 내 두뇌가 서로 협력하면 폭발이 치명적일 수 있습니다 ... 감사합니다! :) –