2017-11-13 16 views
0

일부 명령을 구문 분석하는 문법을 만들고 싶습니다. 대부분은 완벽하게 작동하지만 "if (조건, then-value, else-value)"가 "out"명령과 함께 작동하지 않아 일부 값을 표시합니다. 그것은 잘 작동하는 경우에 출력 명령은 외부에있는 경우-명령을if commm에서 실행을 억제하는 PEG 문법

out(if(1,42,43)) 
출력 →

하고 확인을 예상대로 42을 반환

그러나 순간에 출력 명령은 해당 시점의 내부 및 다른입니다 OK 예상

if(1,out(42),out(43)) 

→은 여전히 ​​42을 반환하지만, 출력 기능 (42, 43)

,691 회 호출 (보다 직관적 일 필요가있다)는 part의 실패

Expression 
    = Int 
/"if(" cond:Expression "," ok:Expression "," nok:Expression ")" { return cond?ok:nok; } 
/"out(" num:Expression ")" { window.alert(num); return num;} 

Int = [0-9]+ { return parseInt(text(), 10); } 

은 "창 : 다음과 같은 매우 간단한 문법을 ​​사용하는 경우 내가 페그/다리 파서 생성기 here 문제와 C에서 일하고 있어요

도 PEG.js 온라인 파서 생성기 here로 재현. alert() "는 필요한 출력 함수의 자리 표시 자일 뿐이므로이 문제는 동일하게 작동합니다. 스캐너가 전체 if 명령을 과 일치시키고, 닫는 괄호 ")"까지 else 값과 일치해야합니다. 따라서 두 명령 모두 일치하고 정의 된 함수를 실행합니다. 이는 예상 한 것과 다릅니다.

일부 문자와 일치 시키려면 peg/leg에 방법이 있지만 상황에 따라 해당 함수의 실행을 억제 할 수 있습니까?

(나는 이미 성공없이 "&"술어 요소로 실험 한)

는 (아마도 오른쪽 재귀 대 여기에 도움이 될 수 재귀 왼쪽 만 사용 PEG/다리 발전기에는 오른쪽 지원 보인다 재귀)

답변

1

일부 문자와 일치하지만 일부 상황에서는 해당 함수의 실행을 억제하는 방법이 있습니까?

나는이 도구에 익숙하지 않지만 이것이 가능하다면 나를 놀라게 할 것이다. 그리고 루프가 구현 되더라도 비슷한 문제가 발생합니다. 이제 액션을 여러 번 실행해야합니다.

당신이 필요로하는 것은 당신의 행동이 코드를 직접 실행하지 않고 그것을 실행하는데 사용할 수있는 것을 되돌려주는 것입니다.

인터프리터가 작동하는 일반적인 방법은 파서가 바이트 코드 또는 AST와 같은 소스 코드 표현을 생성하고 별도의 단계로 실행한다는 것입니다.

너무 많이 변경하지 않고 파서가 작동하도록 만드는 가장 단순한 방법 (아마도 가장 깨끗하지는 않음)은 0 인수 함수에서 모든 작업을 래핑하는 것입니다. 하위 표현식에 의해 반환 된 함수를 호출 할 수 있습니다. 그리고 루프를 구현하려면 함수를 여러 번 호출하면됩니다.

+0

와우,이 내 문법의 완전한 재 설계로 이어질 것이다 다음과 다른 장애인 재귀의 경우-명령의 중복 정의입니다. 지금은 20 개 이상의 함수가 패턴 뒤의 문법 내에 {}로 구현되어 있습니다. 대부분은 매우 간단합니다. 바이트 코드 트리를 생성하고 실행하면 실제로 유효한 해결책이 될 것입니다. 현재 다른 선택의 여지가 없습니다. Achim에게 감사드립니다. – Achim

0
조건부 표현식 "& {식}"이용 될 수있는 용액

Expression 
  = Function 
   
Function 
  = Int 
  / "if(" IfCond "," ok:Function "," nok:FunctionDisabled ")" { return ok; } 
  / "if(" FunctionDisabled "," ok:FunctionDisabled "," nok:Function ")" { return nok; } 
  / "out(" num:Function ")" { window.alert("Out:"+num); return num;} 
  
FunctionDisabled 
  = Int 
/"if(" IfCond "," ok:FunctionDisabled "," nok:FunctionDisabled ")" { return ok; } 
  / "if(" FunctionDisabled "," ok:FunctionDisabled "," nok:FunctionDisabled ")" { return nok; } 

/"out(" num:FunctionDisabled ")" { return num;} 

IfCond 
  = cond:FunctionDisabled   &{ return cond; } 
                    
Int = [0-9]+ { return parseInt(text(), 10); } 

아이디어는 1 회, 2 회) (아웃을 정의하는 것이다 (술어 요소 "& 요소"혼동하지 말 것)

실제로 무언가를하고 두 번째는 출력하지 않고 사용할 수 없습니다. if 명령의 조건은 {} 안에있는 코드를 사용하여 계산되므로 조건이 거짓이면 전체 식 일치가 실패합니다.

보이는 단점은

+0

문법이 커짐에 따라 코드 중복 (문법이 점점 더 복잡 해짐) 외에도이 방법은 루프에 도움이되지 않습니다. 이것은 또한 if-conditions가 더 이상 부작용을 실행하지 않아서 원하는 동작과 완전히 일치하지 않는 것으로 보입니다 (두 번 실행되지 않도록하기 위해 의도적으로 수행 한 것으로 가정). – sepp2k