2016-04-19 11 views
0

シンプルなトークナイザを実装しようとしています。インスタンスSWIプロローグを使用するシンプルなトークナイザ

phrase(lexer(L), "read N; SUM := 0; "), write(L). 

のために戻ってくる:

[key(read),id(N),sep(;),id(SUM),sep(:=), int(0)] 

これは私が持っているものです。

lexer([Token | Tail]) --> 
    lexem(Token), //is this way to get tokens? 
    lexer(Tail). 
lexer([]) --> 
    []. 

lexem --> ????? 

作業用トークナイザを作成するためにどのように開発するかについてのアドバイスに感謝します。

+0

私は 'あなたが'レクサー(テール) '意味' LEX(​​テール)で想定しています。そして 'lexem - > ?????'は 'lexem(token) - > ?????'でなければなりません。 '?????'は、トークンの外観を表します。 DCGへの入力ストリームは、一度に1文字ずつ文字列になります。だから、そこから始めて、どのようにトークン全体を見たのかを文字ごとに知ることができます。 – lurker

+0

ええ、それは私の間違いでした。残念ながら、私はsuccesfulyそれを動作させることはできません。あなたは私に短い例を教えてください。例えば、lexem(トークン) - > ????? generete [sep(;)]ですか? – Dago

+1

[this](http://stackoverflow.com/a/29048653/874024)を参照してください – CapelliC

答えて

2

レクゼムが何であるかを説明するDCGルールを追加できます。たとえば、次のように

lexem(key(K)) --> % key(K) is a lexem 
    key(K).   % if K is a key 
lexem(sep(S)) --> % sep(S) is a lexem 
    sep(S).   % if S is a separator 

% rules for your keywords here 
key(read) --> 
    "read". 
key(write) --> 
    "write". 

% rules for your seperators 
sep(;) --> 
    ";". 
sep(:=) --> 
    ":=". 

あなたはまた、例えば、空白のためにあなたのレクサーにルールを追加したい場合があります

lexer(Ts) --> 
    whitespace,   % whitespace is ignored 
    lexer(Ts). 

whitespace --> 
    [W], 
    {char_type(W,space)}. % space is whitespace 

この最小限の例では既に少しを照会することができます

?- phrase(lexer(L), "read ; write"). 
L = [key(read),sep(;),key(write)] ? ; 
no 

識別子と数字はちょっとややこしいですが、おそらく最も長い入力一致が必要です。 はid('S'), id('U'), id('M')の代わりにid('SUM')と一致します。だから、識別子// 1を書くことは、最初の解として最長一致を生成し、さらなる解を探索しないようにカットを使用するようにしてください。組み込み述語atom_chars/2とnumber_chars/2を使用して、原子/文字列と数値/文字列を変換することができます。残りはかなり自明です:

lexem(id(IA)) --> 
    identifier(I), 
    !,      % longest input match 
    {atom_chars(IA,I)}. 
lexem(int(NA)) --> 
    number(A), 
    !,      % longest input match 
    {number_chars(NA,A)}. 

identifier([C|Cs]) --> % identifiers are 
    capital(C),   % capital letters 
    ident(Cs).    % followed by other cl's 

ident([C|Cs]) --> 
    capital(C), 
    ident(Cs). 
ident([]) --> 
    []. 

capital(C) --> 
    [C],     % capitals are 
    {char_type(C,upper)}. % uppercase letters 

number([D|Ds]) -->  % numbers are 
    digit(D),    % a digit followed 
    digits(Ds).   % by other digits 

digits([D|Ds]) --> 
    digit(D), 
    digits(Ds). 
digits([]) --> 
    []. 

digit(D) -->    % a single digit 
    [D], 
    {char_type(D,digit)}. 

今、あなたは上記の例を照会することができます

?- phrase(lexer(L), "read N; SUM := 0; "). 
L = [key(read), id('N'), sep(;), id('SUM'), sep(:=), int('0'), sep(;)] ; 
false. 
+0

私はexpl explationを試しましたが、与えられた例では私は虚偽しか表示されません;/ – Dago

+0

これは現在動作していますが、私はsep(;)の代わりにsep((;))を持っています。何故ですか? – Dago

+0

@ダゴ:おそらくあなたは偶然、余分な括弧を付け加えました。ルールの頭をチェックしてください。ところで、上の例で数字と識別子を一致させるために私の答えを更新しました。 – tas

関連する問題