어떻게 컴파일러는 명시 적 파스 트리를 구성하지 않고 할 수 있습니까? 명시 적 구문 분석 트리 구축의 이점과 단점은 무엇입니까?컴파일러 건축 : 명시 구문 분석 나무
은 그 컴파일러는 구문 분석하는 동안 그와 관련된 의미를 SDT를 사용하여 실행하여 명시 적 파스 트리없이 건설 할 수 있습니다 알고 있습니다. 하지만 명시 적 구문 분석 트리 구축의 이점과 단점을 알고 싶습니다.
어떻게 컴파일러는 명시 적 파스 트리를 구성하지 않고 할 수 있습니까? 명시 적 구문 분석 트리 구축의 이점과 단점은 무엇입니까?컴파일러 건축 : 명시 구문 분석 나무
은 그 컴파일러는 구문 분석하는 동안 그와 관련된 의미를 SDT를 사용하여 실행하여 명시 적 파스 트리없이 건설 할 수 있습니다 알고 있습니다. 하지만 명시 적 구문 분석 트리 구축의 이점과 단점을 알고 싶습니다.
임 그래서 나와 함께 paitient하시기 바랍니다 멍청한 놈 ... 들으 약간의 ...
가 이그러나 귀하의 질문에, (구문 분석 트리없이) 재귀 괜찮은 편집에 대답 만이 수행 할 수 있습니다 가장 간단한 경우는 전방 참조 및 기호가 선언의 포인트에서만 유효하고 전체 범위가 아닌 경우입니다.
는 분명히 실 거예요 자바 같은 언어와 함께 작동합니다. theres 전방 참조, 그럼 적어도 두 패스가 필요하고 세 가지 패스 theres 자바 (또는 당신이 3 미만으로 그것을 어떻게 다음 우리에게 계몽을 수행하는 방법을 알고있는 경우에 위에 overloaded 기능 위에 필요한 경우) . 이를 위해 파스 트리를 만듭니다.
간단한 구문 분석 트리 노드는 다음과 같이 보일 수 있습니다 (면책 조항 :이 실제 코드가 아닙니다).
package compiler;
import java.util.ArrayList;
import scanner.Token;
import scanner.TokenSet;
class Production
{
Token leading; // the first token in the production
int productionID; // a unique integer that identifies the production
ArrayList<Production> childNodes; // duh
Production mother; // mother node (may be null)
public Production (Token leading, int productionID)
{
this.leading = leading;
this.productionID = productionID;
childNodes = new ArrayList<Production>();
}
public void append (Production child) // add a new child node
{
child nodes.add(child);
child.mother = this;
}
public abstract void build1 (TokenSet follow, TokenSet anchor); // implements pass 1
public abstract void build2 ....
}
그러나 훨씬 더 강력한 접근 방식은 각 제품에 대한 새로운 서브 클래스를 파생시키고 필드 변수로 자식 노드를 선언하는 것입니다. 그런 다음 productionID를 제거하고 대신 instanceof 검사를 사용할 수 있습니다. 심볼을 정의하는 노드의 주어진 하위 클래스에 심볼 인터페이스를 구현하고 노드를 심볼 테이블에 직접 삽입 할 수도 있습니다. 중첩 된 스코프를 정의하는 프로덕션도 고유 한 심볼 테이블을 가질 수 있습니다 (여기서는 그렇게하지 않을 것입니다). 요점은 이런 방식으로 통사론과 의미 론적 분석이 모두 파스 트리 구조와 심지어 최종 번역에 통합 될 수 있다는 것입니다. 유일한 아래쪽은 그 끔찍한 자바 인터페이스입니다 : LOL : 당신이 그런 식으로 할 경우
// i wont bother with imports since this isnt real code
class DefinitionModule extends Production
{
Identifier name;
ArrayList<ImportClause> importClauses;
ArrayList<ExportClause> exportClauses;
ArrayList<Production> itemList; // CONST-,TYPE-, & VAR- declarators & function headers
public DefinitionModule() // no more productionID
{
super(lastTokenRead()); // always sits on DEFINITION
importClauses = new ArrayList<ImportClause>;
}
// build()
//
// DefinitionModule ::= DEFINITION MODULE Identifier ";" {ImportClause}{ExportClause}{HeaderItem} END Identifier
//
// where HeaderItem ::= ConstDeclarator | TypeDeclarator | VarDeclator | ProcedureHeader.
// Identifier, ImportClause, & ExportClause below are all derived from
// Production, above
public void build (TokenSet follow, TokenSet anchor)
{
Scanner.getToken(); // skip the DEFINITION
Scanner.expectToken(Token.ID_MODULE); // make sure MODULE is there & then skip it
name = name.build(new TokenSet(Token.ID_SEMICOLON));
expectToken(Token.ID_SEMICOLON);
while (lastTokenRead()==Token.ID_IMPORT || lastTokenRead()==Token.ID_FROM)
{
ImportClause IC = new ImportClause(lastTokenRead());
importClauses.add(IC.build(new TokenSet(Token.ID_SEMICOLON));
Scanner.expectToken(Token.ID_SEMICOLON);
}
while (lastTokenRead()==Token.ID_EXPORT)
{
ExportClause XC = new ExportClause(lastTokenRead());
exportClauses.add(XC.build(new TokenSet(Token.ID_SEMICOLON));
Scanner.expectToken(Token.ID_SEMICOLON);
}
// etc, etc, etc
}
}
이 컴파일러는 주위에 자신을 구축 할 것입니다, 우리는 모듈라 2 헤더 파일을 선언 할 수 예를 들어
컴파일러의 전통적인 패스가 아닌 언어의 기능.
행운을 빕니다 ...