2

私は、C のような言語 (より単純な言語) 用のコンパイラ (lex や bison などのツールを使用せずに) の構築に取り組んでおり、lexer と parser を通過しました。パーサーの実行方法が正しいかどうかはわかりません。これまでのところ、構文が正しいかどうかを確認するなどの構文解析を行うために、リンクされたリストをまったく使用していません。基本的に、私のパーサーは次のようになります。

<program> ::= <program_header> <program_body>
<program_header>::= program <identifier> is
<program_body> ::= (<declaration>;)*
begin
(<statement>;)*
end program

私のプログラムは次のようになります。

parser()
{
char *next_token;
next_token = get_token();
check_for_program(next_token);
}
check_for_program(next_token)
{
check_for_program_header(next_token);
if (header_found)
check_for_program_body();
}...

私は基本的にすべての非端末用の関数を持っており、適切なタイミングでそれらを呼び出し、「strcmp」でキーワードをチェックしています。この方法は大丈夫ですか?

この時点から、意味解析を行うにはどうすればよいでしょうか? シンボル テーブルの作成はどこから始めればよいですか?

考えるための提案や指針は素晴らしいです! どうもありがとうございました

4

2 に答える 2

3

それを行うための一般的でかなり単純な方法は、再帰降下パーサーを作成することです。つまり、構文に対応する関数を作成します(これは、すでにやり始めているようです)。

例えば

<program> ::= <program_header> <program_body>
<program_header>::= program <identifier> is
<program_body> ::= (<declaration>;)*

次のようなものに対応します

void program()
{
  program_header();
  program_body();
}

void program_header() 
{
   char* program_token = get_token();
   char* identifier = get_token();
   if (identifier==NULL) report_error();
   ...
}

void program_body()
{
   declaration();
   ...
}

そして、各関数内にセマンティック チェックを配置します。スコープを処理したくない場合、またはシンボル テーブルのスタックのようなものを使用したくない場合は、グローバル コンストラクトであるシンボル テーブルが必要になります。

于 2011-01-26T00:02:45.833 に答える
0

はい、これは解析の 1 つの方法で、Recursive descent parserと呼ばれます。これは構文解析の非公式な方法です。つまり、文法を変更すると、解析コードを変更する必要があります。

LLSLRなどの正式な解析方法もあります。正式な方法には 2 つの利点があります。構文解析が文法で定義されているものを解析することを証明できます (これが正式と呼ばれる理由です)。互換性のある文法を解析します。

于 2011-01-26T00:05:14.957 に答える