2015-11-05 46 views
1

我試圖寫在Perl一個簡單的數據操縱語言(只讀,它的意思是SQL風格的查詢轉換爲過濾器和屬性使用vSphere Perl的API使用方法:http://pubs.vmware.com/vsphere-60/topic/com.vmware.perlsdk.pg.doc/viperl_advancedtopics.5.1.html_在Perl中編寫簡單的解析器:使用詞法分析器輸出,下一步要去哪裏?

我現在有類似的東西以詞法分析器輸出,如果我正確地理解它 - 像這樣(數據::哈希自卸車打印陣列)標記列表:

$VAR1 = { 
     'word' => 'SHOW', 
     'part' => 'verb', 
     'position' => 0 
    }; 
$VAR2 = { 
     'part' => 'bareword', 
     'word' => 'name,', 
     'position' => 1 
    }; 
$VAR3 = { 
     'word' => 'cpu,', 
     'part' => 'bareword', 
     'position' => 2 
    }; 
$VAR4 = { 
     'word' => 'ram', 
     'part' => 'bareword', 
     'position' => 3 
    }; 

現在我想要做的是建立一個語法樹。到目前爲止我看到的文檔主要是使用模塊並從BNF生成語法,但目前我無法將其包圍。

我想修改相對簡單的程序代碼,可能是遞歸的,自己做一些醜陋的實現。

什麼,我目前想的是這樣建立一個字符串的$token->{'part'}s

my $parts = 'verb bareword bareword ... terminator'; 

,然後運行一個又大又醜的正則表達式反對,(AB)使用Perl的能力嵌入代碼到正規表情:http://perldoc.perl.org/perlretut.html#A-bit-of-magic:-executing-Perl-code-in-a-regular-expression

$parts =~/
    ^verb(?{ do_something_smart })\s  # Statement always starts with a verb 
    (bareword\s(?{ do_something_smart }))+ # Followed by one or more barewords 
    | # Or 
    # Other rules duct taped here 
/x; 

不管我迄今發現需要CS和/或語言學的紮實的知識,而我沒有,甚至瞭解它。

我應該如何處理詞法分析器輸出以開始理解並且修補程序有適當的解析?像'構建一組代表語句的小部分的臨時哈希'或'刪除子字符串,直到字符串爲空,然後驗證您得到的結果。

我知道龍書和SICP​​,但我想要更輕的東西在這個時候。

謝謝!

+0

我會重新解釋這個問題。 –

+1

爲什麼不使用現有的解析器,如[Marpa :: R2](http://p3rl.org/Marpa::R2)或[Parse :: RecDescent](http://p3rl.org/Parse: :RecDescent的)? – choroba

+0

@choroba,文檔不會點擊。不瞭解足夠的理論來理解它。最初的問題是簡單的閱讀,但就像它會被關閉一樣。我仍然願意自己編寫解析器部分,即使它會很糟糕 - 它會幫助我理解解析器是如何工作的。如果純粹是爲了完成任務,我會選擇VMWare提供的'canned'請求和示例(它也可以使用它),但它似乎很簡單,同時也是有用的任務,可以幫助我學習新鮮玩意。 –

回答

0

正如一對夫婦的意見如上所述,但在這裏再次作爲一個真正的答案:

你可能會喜歡Parser::MGC。 (免責聲明:我是Parser::MGC的作者)

首先將各種令牌的現有(regexp?)定義,並使用generic_token方法將它們轉換爲「令牌_...」方法。

從這裏開始,您可以開始構建方法來解析您的語法的更大和更大的結構,方法是使用結構構建方法。

至於實際構建AST - 可能最簡單的做法是簡單地發出HASH引用,其中包含您的結構的命名部分。從問題中給出的例子很難說出一個語法結構,但是你可能會有一個「命令」的概念,它是一個「動詞」,後面跟着一些「名詞」。你可能會解析使用:

sub parse_command 
{ 
    my $self = shift; 

    my $verb = $self->token_verb; 

    my $nouns = $self->sequence_of(sub { $self->token_noun }); 
     # $nouns here will be an ARRAYref 

    return { type => "command", verb => $verb, nouns => $nouns }; 
} 

它通常圍繞此點以書面我決定我想要一些實際類型的對象,而不是單純的哈希引用解析器。一個簡單的方法來做到這一點是通過我的另一個模塊,Struct::Dumb

use Struct::Dumb qw(-named_constructors); 
struct Command => [qw(verb nouns)]; 

... 
return Command(verb => $verb, nouns => $nouns); 
相關問題