태그 보관물: php

php

명령 인터프리터 / 파서 작성 방법 .

문제 : 문자열 형태로 명령을 실행하십시오.

  • 명령 예 :

    /user/files/ list all;
    다음과 같습니다.
    /user/files/ ls -la;

  • 다른 것:

    post tw fb "HOW DO YOU STOP THE TICKLE MONSTER?;"

다음과 같습니다.
post -tf "HOW DO YOU STOP THE TICKLE MONSTER?;"

현재 솔루션 :

tokenize string(string, array);

switch(first item in array) {
    case "command":
        if ( argument1 > stuff) {
           // do the actual work;
        }
}

이 솔루션에서 볼 수있는 문제는 다음과 같습니다.

  • 각 케이스 안에 중첩 된 ifs-else 이외의 오류 검사가 없습니다. 대본은 매우 커지고 관리하기가 어렵습니다.
  • 명령과 응답은 하드 코딩됩니다.
  • 플래그가 올바른지 또는 매개 변수가 없는지 알 수있는 방법이 없습니다.
  • “$ command를 실행하고 싶을 수도있다”는 지적 부족.

그리고 내가 해결할 수없는 마지막 것은 다른 인코딩의 동의어입니다. 예 :

case command:
case command_in_hebrew:
    do stuff;
break;

마지막 것은 사소한 것일 수도 있지만, 내가보고 싶은 것은 이런 종류의 프로그램의 확실한 자금입니다.

나는 현재 이것을 PHP로 프로그래밍하고 있지만 PERL에서 그것을 할 수 있습니다.



답변

솔직히 인정하자면, 파서 작성은 지루한 작업이며 컴파일러 기술에 가깝지만 하나를 작성하는 것은 좋은 모험이 될 것입니다. 파서는 통역사와 함께 제공됩니다. 그래서 둘 다 만들어야합니다.

파서 및 통역사에 대한 빠른 소개

이것은 너무 기술적이지 않습니다. 그래서 전문가들은 걱정하지 않습니다.

일부 입력을 터미널에 공급하면 터미널이 입력을 여러 장치로 분할합니다. 입력을 표현이라고하고 여러 단위를 토큰이라고합니다. 이 토큰은 연산자 또는 기호 일 수 있습니다. 따라서 계산기에 4 + 5 를 입력하면 이 표현식은 3,4, +, 5 토큰으로 나뉩니다. 더하기 기호는 4 및 5 기호 인 동안 연산자로 간주됩니다. 이것은 연산자에 대한 정의를 포함하는 프로그램 (통역사로 간주)으로 전달됩니다. 정의 (이 경우 add)에 따라 두 기호를 추가하고 결과를 터미널에 반환합니다. 모든 컴파일러는이 기술을 기반으로합니다. 식을 여러 개의 토큰으로 나누는 프로그램을 렉서라고하며 추가 처리 및 실행을 위해 이러한 토큰을 태그로 변환하는 프로그램을 파서라고합니다.

Lex 및 Yacc 는 C 에서 BNF 문법을 기반으로하는 어휘 분석기 및 구문 분석기를 작성하기위한 표준 양식이며 권장되는 옵션입니다. 대부분의 파서는 Lex와 Yacc의 복제본입니다.

파서 / 분석가를 구축하는 단계

  1. 토큰을 기호, 연산자 및 키워드로 분류하십시오 (키워드는 연산자 임)
  2. BNF 양식을 사용하여 문법 작성
  3. 작업을위한 파서 함수 작성
  4. 프로그램으로 실행 컴파일

따라서 위의 경우 추가 토큰은 렉서에서 더하기 기호로 수행 할 작업에 대한 정의가있는 숫자 및 더하기 기호입니다.

노트와 팁

  • 왼쪽에서 오른쪽으로 LALR 을 평가하는 파서 기술을 선택하십시오.
  • 느낌을 얻으려면 컴파일러 에 대한이 용 책을 읽으십시오 . 나는 개인적으로 책을 끝내지 않았다
  • 링크 는 Python에서 Lex와 Yacc에 대한 초고속 통찰력을 제공합니다.

간단한 접근법

기능이 제한된 간단한 구문 분석 메커니즘이 필요한 경우 요구 사항을 정규식으로 바꾸고 전체 기능을 만드십시오. 예를 들어, 4 개의 산술 함수에 대한 간단한 구문 분석기를 가정하십시오. 따라서 연산자를 먼저 호출 한 다음 스타일의 함수 목록 (lisp와 유사) (+ 4 5)또는(add [4,5]) 다음 운영자와시 운영되는 기호의 목록을 얻을 수있는 간단한 정규식을 사용할 수 있습니다.

이 방법으로 가장 일반적인 경우를 쉽게 해결할 수 있습니다. 단점은 명확한 구문으로 많은 중첩 식을 가질 수 없으며 쉽게 고차 함수를 가질 수 없다는 것입니다.


답변

첫째, 문법이나 인수를 지정하는 방법에 관해서는 자신의 것을 발명하지 마십시오. GNU 스타일의 표준은 이미 매우 인기가 잘 알려져있다.

둘째, 허용되는 표준을 사용하고 있으므로 바퀴를 재발 명하지 마십시오. 기존 라이브러리를 사용하십시오. GNU 스타일 인수를 사용하는 경우 이미 선택한 언어로 된 성숙한 라이브러리가 거의 있습니다. 예를 들어 , c # , php , c 입니다.

좋은 옵션 파싱 라이브러리는 사용 가능한 옵션에 대한 도움말을 인쇄합니다.

12/27 수정

당신이 이것을보다 복잡하게 만드는 것처럼 보입니다.

명령 행을 보면 매우 간단합니다. 옵션과 그 옵션에 대한 인수 일뿐입니다. 복잡한 문제는 거의 없습니다. 옵션은 별명을 가질 수 있습니다. 인수는 인수 목록이 될 수 있습니다.

귀하의 질문에 대한 한 가지 문제는 처리하려는 명령 줄 유형에 대한 규칙을 실제로 지정하지 않았다는 것입니다. 나는 GNU 표준을 제안했으며, 당신의 예제는 그것에 가깝습니다 (그러나 첫 번째 항목으로 경로를 가진 첫 번째 예제를 실제로 이해하지 못합니까?).

우리가 GNU를 말하는 경우, 단일 옵션은 별칭으로 긴 형식과 짧은 형식 (단일 문자) 만 가질 수 있습니다. 공백이 포함 된 모든 인수는 따옴표로 묶어야합니다. 여러 개의 짧은 양식 옵션을 연결할 수 있습니다. 짧은 양식 옵션은 단일 대시로, 긴 양식은 두 개의 대시로 진행해야합니다. 마지막으로 연결된 짧은 양식 옵션 만 인수를 가질 수 있습니다.

매우 간단합니다. 매우 일반적입니다. 또한 5 번 이상 찾을 수있는 모든 언어로 구현되었습니다.

쓰지 마십시오. 이미 작성된 것을 사용하십시오.

표준 명령 줄 인수 이외의 것을 염두에 두지 않는 한, 기존에 테스트를 거친 많은 라이브러리 중 하나를 사용하십시오.

합병증은 무엇입니까?


답변

http://qntm.org/loco 와 같은 것을 이미 시도 했습니까 ? 이 접근 방식은 손으로 쓴 애드혹보다 훨씬 깔끔하지만 레몬과 같은 독립형 코드 생성 도구는 필요하지 않습니다.

편집 : 복잡한 구문으로 명령 줄을 처리하는 일반적인 방법은 인수를 공백으로 구분 된 단일 문자열로 다시 결합한 다음 도메인 특정 언어의 표현 인 것처럼 올바르게 구문 분석하는 것입니다.


답변

당신은 당신의 문법에 대한 많은 세부 사항을 제시하지 않았으며 몇 가지 예를 들었습니다. 내가 볼 수있는 것은 약간의 문자열, 공백 및 (아마도 귀하의 예가 귀하의 질문에 무관심합니다) 큰 따옴표로 묶인 문자열과 하나의 “;”가 있다는 것입니다 끝에.

PHP 구문과 비슷할 수 있습니다. 그렇다면 PHP에 파서가 제공되므로 재사용하고보다 구체적으로 확인할 수 있습니다. 마지막으로 토큰을 처리해야하지만 이것은 왼쪽에서 오른쪽으로 보이므로 실제로 모든 토큰에 대한 반복입니다.

PHP 토큰 파서 ( token_get_all) 를 재사용하는 몇 가지 예가 다음 질문에 대한 답변에 제공됩니다.

두 예제에는 간단한 파서도 포함되어 있으며 아마도 시나리오에 적합한 것과 유사한 것이 있습니다.


답변

당신의 요구가 단순하고 둘 다 시간이 있고 그것에 관심이 있다면, 나는 여기서 결정에 반대하고 자신의 파서를 작성하는 것을 부끄러워하지 말라고 말할 것입니다. 다른 것도 없다면 좋은 학습 경험입니다. 중첩 된 함수 호출, 배열 등보다 복잡한 요구 사항이있는 경우 시간이 오래 걸릴 수 있습니다. 자신의 롤링에 대한 가장 큰 장점 중 하나는 시스템과의 통합에 문제가 없다는 것입니다. 물론 단점은 모든 실수가 당신의 잘못이라는 것입니다.

그러나 토큰에 대한 작업은 하드 코딩 된 명령을 사용하지 마십시오. 그런 다음 비슷한 소리 명령과 관련된 문제가 사라집니다.

모든 사람은 항상 드래곤 북을 추천하지만, 나는 항상 Ronald Mak의 “쓰기 컴파일러와 통역사” 가 더 나은 소개가된다는 것을 알게되었습니다 .


답변

나는 그런 식으로 작동하는 프로그램을 작성했습니다. 하나는 유사한 명령 구문을 가진 IRC 봇이었습니다. 이 큰 파일 큰 스위치 문입니다. 작동하지만 빠르게 작동하지만 유지 관리가 다소 어렵습니다.

OOP 스핀이 더 많은 다른 옵션은 이벤트 핸들러를 사용하는 것입니다. 명령과 전용 기능을 사용하여 키-값 배열을 만듭니다. 명령이 주어지면 배열에 주어진 키가 있는지 확인합니다. 그렇다면 함수를 호출하십시오. 이것은 새로운 코드에 대한 나의 추천이 될 것입니다.


답변

컴파일러 나 인터프리터를 직접 구현하는 대신 도구를 사용하는 것이 좋습니다. Irony는 C #을 사용하여 대상 언어 문법 (명령 줄의 문법)을 표현합니다. CodePlex에 대한 설명은 “Irony는 .NET 플랫폼에서 언어를 구현하기위한 개발 키트입니다.”라고 말합니다.

CodePlex : Irony-.NET 언어 구현 키트 의 Irony 공식 홈페이지를 참조하십시오 .