2012-06-11 2 views
2

나는 Ada에 익숙하지 않아 재귀 적으로 괜찮은 파서에서 Ada로 컴파일러 자습서의 코드를 변환하려고 시도하고 있습니다. 튜토리얼을 포팅하면서 Jack W. Crenshaw가 만든 "컴파일러를 만들어 봅시다"는 많은 언어를 배우는 가장 좋은 방법이었습니다. 단일 문자 토큰을 사용하여 제 3 장까지 모든 작업을했습니다. 다중 문자 토큰으로의 이동은 번거로운 작업이었습니다.Ada 문자로 입력 문자를 가져 오는 방법

procedure GetName is 
    token: Ada.Strings.Unbounded; 
begin 
    while IsAlNum(Look) loop 
    Token := Token & Look; 
    GetChar; 
    end loop 
end GetName; 

가 지금은 문자열이 정적하는 에이다 의도 알고

나는이 sudo는 코드와 같은 코드 뭔가가있다. 하지만 입력에서 가져온 각 새 문자를 토큰의 문자 모음에 연결할 수 있어야합니다. look은 전역 look-ahead 값 (입력 된 마지막 문자)입니다.

도움 주셔서 감사합니다. 또한 그물에 좋은 Ada 튜토리얼이나 요리법 사이트가 있습니까? 나는 C 프로그래머들을 위해 Lovelace와 Ada를 읽었다. Ada RM은 약간 공식적이고 사용하지 않는 사양만을 보여줍니다.

다시 한번 감사드립니다!

+0

"sudo"또는 pseudo? – Coffee

+0

IsAlNumOrUnderscore! –

답변

2

이 질문의 끝에서 Ada 문자열 처리에 도움을 요청하는 것 같습니다.

예, Ada 문자열은 실제로 크기를 조정할 수있는 버퍼가 아닌 정적 문자열로 처리하는 것이 가장 좋습니다. 이것을 처리 할 수있는 3 가지 typcial 방법이 있습니다.

첫 번째는 매우 큰 String 버퍼를 만들고, 문자열의 논리적 길이를 유지하는 변수 Natural을 별도로 지정하는 것입니다. 이것은 다소 고통스럽고 다소 오류가 발생하기 쉽지만 적어도 버퍼의 끝에서 null을 지속적으로 검색하는 C의 방법보다 빠릅니다.

둘째는 그냥 펀트하여 Ada.Strings.Unbounded.Unbounded_String을 사용하는 것입니다. 절차적인 방법으로 사고하는 데 익숙하다면 이것은 가장 쉬운 방법이므로 대부분의 사람들이하는 일입니다.

세 번째는 가능하면 문자열을 처리하는 것입니다. 입니다. 여기에 필요한 주요 통찰력은 Ada String이 실제로 정적이지만 수명을 제어 할 수 있으며 기능적으로 프로그램하면 정적 문자열을 원할 때마다 동적으로 만들 수 있습니다.

function Matches_Token (Scanned : String) return boolean; --// Returns true if the given string is a token 
function Could_Match_Longer (Scanned : String) return boolean; --// Returns true if the given string could be part of a larger token. 
function Get_Next_Char return Character; --// Returns the next character from the stream 
procedure Unget; --// Puts the last character back onto the stream 
procedure Advance (Amount : Natural); --// Advance the stream pointer the given amount 
function Longest_Matching_Token (Scanned : String) return String is 
    New_Token : constant String := Scanned & Get_Next_Char; 
begin 
    --// Find the longest token a further scan can match 
    if Could_Match_Longer(New_Token) then 
     declare 
      LMT : constant String := Longest_Matching_Token (New_Token); 
     begin 
      if LMT /= "" then 
       unget; 
       return LMT; 
      end if; 
     end; 
    end if; 

    --// See if this string at least matches. 
    if Matches_Token(New_Token) then 
     unget; 
     return New_Token; 
    else 
     unget; 
     return ""; 
    end if; 
end Build_Token; 

function Get_Next_Token return String is 
    Next_Token : constant String := Build_Token(""); 
begin 
    Advance (Next_Token'length); 
    return Next_Token; 
end Get_Next_Token; 

이 항상 문자열의 가장 효율적인 방법은 아닙니다 :

예를 들어, 나는 다음과 같은 일을 수행하여 내가 (이론적으로 무한 내다으로) 원하는 길이의 새로운 Token 문자열을 만들 수 있습니다 처리 (너무 많은 스택 사용),하지만 그것은 종종 가장 쉽습니다.

사실상, 스캐닝과 파싱은 실제로 버퍼 (방법 1)와 gotos와 같이 일반적으로 피해야하는 추악한 것들을 피하는 특별한 경우의 응용 프로그램입니다.

+0

안녕하세요. 정보를 제공해 주셔서 감사합니다. 이 컴파일러를 이식하는 것은 오랫동안 새로운 언어를 배우는 가장 좋은 방법 중 하나였습니다. 간단한 응용 프로그램에서 일반적으로 발생하지 않는 많은 문제를 일으키는 것으로 보입니다. 또한 언어 작업에 대한 좋은 벤치 마크를 제공합니다. 이 튜토리얼의 컴파일러는 68K 머신 용이지만, 이전에는 성공적으로 크로스 컴파일러로 사용하기 위해 8051, 6811, 8086 및 C로 변환했습니다. 지금 나는 Ada를 배우려고 노력하고 있으며, 실제로 그것으로 일하는 시간으로 가득 찬 손을 가지고 있습니다. 나는 정보를 찾기가 어려웠다. – user693336

+0

@ user693336 - Certianly 내가 언어를 배웠던 가장 좋은 방법은 그들에게 무언가를 프로그램하려고하는 것입니다. 문자열에 대한이 문제는 Ada 학습자가 가장 먼저 시도하는 것이며 Ada 배열 규칙에는 미묘한 (그러나 광범위한) 함의가 있습니다.함수형 언어에 익숙하지 않다면, 첫 번째 접근법은 대개 C 문자열 처리 메서드를 사용하려고 시도하는 것인데, 이는 대용량 좌절로 이어집니다 ('Ada.Strings.Unbounded'를 포기하고 사용하지 않는 한). 불행한 일은 아다의 가장 이상한 니트가 멍청한 놈들이하는 첫 번째 일이지만, 거기에 있습니다. –

2

Ada에 대한 단일 문자 "get"방법은 Ada.Text_IO.Get입니다. 또한 Text_IO 패키지의 해당 섹션에는 Look_Ahead 및 Get_Immediate 프로 시저가 있습니다.

로다 코드의 Ada Category은 많은 예제를 처리 할 수있는 좋은 예입니다.

+0

이미 하나의 문자를 얻을 수 있습니다. 내 문제는 다중 코드 입력 및 토큰을 허용하도록 기존 코드를 수정하는 것입니다. 현재 Ada.Text_IO.Get을 사용하고 있는데, 이는 단일 문자로 잘 작동합니다. 나는 Ada에서 단일 문자 토큰에서 다중 문자 토큰으로 변경하는 것이 C/C++, Pascal, PHP, Python에서 많은 작업을 필요로한다는 것을 발견했습니다. 그러나 Ada의 엄격한 유형 검사는 변경 사항이 코드 전체에 전파된다는 것을 의미합니다. 그러나 새로운 언어에 대해 배우기 위해 그것이이 운동의 핵심이라고 생각합니다. – user693336

+1

@ user693336 - 이것은 Ada (C 사용자를 종종 좌절시키는)에 대한 아주 기본적인 것입니다. Ada에서 여전히 "해킹"할 수 있지만 강력한 유형 시스템은 근본적인 객체 역할을 변경하면 작업을 중단하고 * 재 설계해야합니다. 이것은 실제로 언어에 관한 최고의 것들 중 하나입니다. –

+0

그냥 OpenToken을 보았습니다. 나는 내 벨트 아래 에이다의 몇 주를 얻으면 이걸 가지고 놀아야 할 것입니다! 그것은 큰 소리! – user693336

2

Ada 2005 이상 버전의 경우 (실제로는 95 버전이있을 수 있지만 완전히 모름), 스트림을 사용할 수 있습니다. 이 같은 것 :

+0

감사합니다. 또한 생각을 조금 바꾸고 문자 배열을 정의하고 입력 길이를 제한함으로써 강제 해결책을 찾았습니다. 그러나 문자 배열을 사용하면 다른 절차에서 문제가 발생했습니다. Ada는 유형과 데이터 크기를 강제한다는 점에서 C/C++과 매우 다릅니다. – user693336

+0

알아요. 나는 그것을 정말로 좋아한다. 확실히, 때때로 약간의 어려움이있을 수 있지만, 신비스럽고 간헐적 인 실패의 프로그램을 디버그해야 할 필요는 없을 것이다. – Shark8

+0

원래 OpenToken (Ada 컴파일러 생성 툴킷)을 작성한 사람으로서 사용하기 쉽도록 Text_IO 대신 스트림 입력을 사용했습니다. 그러나 실제로이 컴파일러를 사용하려면 작은 패키지/클래스를 작성하여 가능한 한 많은 파일을 RAM에 넣은 다음 해당 버퍼에서 문자를 가져 오는 것이 도움이 될 수 있습니다. 당신이하는 I/O가 적을수록 좋습니다. –

2

필자는 입력에서 가져온 각각의 새로운 문자를 연결하여 함수를 작성하여 문자열로 반환합니다. 필요한 것을하기 위해 적응할 수도 있습니다.

FUNCTION get_a_string (ch : IN Character) RETURN String IS 
----------------------------------------------------------------- 
--| Recursively hack out a string from a stream of single 
--| character input. Starting with an ESC sentinel and ending 
--| with an EOL sentinel. 
--| ESC is the ESC character and EOL is a space. 
---------------------------------------------------------------- 
    next : Character; 
    ch2s : String(1..1); 
BEGIN -- get_a_string 
    Ada.Text_IO.Put("Waiting: ");--BARF 
    Ada.Text_IO.Get(Item => next); 

    IF ch = ESC THEN -- start 
     RETURN get_a_string(next); 
    ELSIF next = EOL THEN --Escape Case 
     ch2s(1) := ch; 
     RETURN ch2s; 
    ELSE -- Keep getting input 
     RETURN ch & get_a_string(next); 
    END IF; 
END get_a_string; 

는 경우 내 강사 또는 TA 내가하지 못했습니다. 내가 쓴 코드 일치로이 발견, 그래서 나는 부정하고 있지 않다.

관련 문제