Sie könnten DCG-Regeln hinzufügen, die beschreiben, was ein Lexem ist. Zum Beispiel:
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(:=) -->
":=".
Sie könnten auch Regeln gerne Ihre Lexer für Leerzeichen, zB hinzufügen:
lexer(Ts) -->
whitespace, % whitespace is ignored
lexer(Ts).
whitespace -->
[W],
{char_type(W,space)}. % space is whitespace
Mit diesem minimal Beispiel Sie bereits ein wenig abfragen kann:
?- phrase(lexer(L), "read ; write").
L = [key(read),sep(;),key(write)] ? ;
no
Die Bezeichner und die Nummer sind etwas kniffliger, da Sie wahrscheinlich die längste Eingabeübereinstimmung wünschen, z "SUM"
als id('SUM')
anstelle von id('S'), id('U'), id('M')
zugeordnet. Daher ist es angebracht, den Bezeichner // 1 so zu schreiben, dass er die längste Übereinstimmung als erste Lösung erzeugt und den Schnitt verwendet, um nicht nach weiteren Lösungen zu suchen. Sie können die integrierten Prädikate atom_chars/2 und number_chars/2 verwenden, um zwischen Atomen/Strings und Zahlen/Strings zu konvertieren. Der Rest ist selbsterklärend:
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)}.
Jetzt können Sie für Ihre obigen Beispiel abfragen:
?- phrase(lexer(L), "read N; SUM := 0; ").
L = [key(read), id('N'), sep(;), id('SUM'), sep(:=), int('0'), sep(;)] ;
false.
Ich gehe davon durch 'lex (Schwanz)' Sie meinen 'Lexer (Schwanz)'. Und 'lexem -> ?????' sollte 'lexem (Token) -> ?????' sein. '?????' beschreibt, wie ein Token aussieht. Der Eingabestream für Ihre DCG wird Ihre Zeichenfolge sein, ein Zeichen nach dem anderen. Fang also von dort an, denn du weißt, wie du ein ganzes Zeichen Charakter für Charakter gesehen hast. – lurker
Ja, das war mein Fehler. Leider kann ich es nicht erfolgreich machen. Könnten Sie mir bitte ein kurzes Beispiel geben, zum Beispiel wie lexem (Token) -> ????? würde generete [sep (;)]? – Dago
siehe [diese] (http://stackoverflow.com/a/29048653/874024) antwort – CapelliC