2015-02-13 3 views
6

Ich verwende die folgende ANTLR-Grammatik, um eine Funktion zu definieren.ANTLR analysiert gierig, obwohl die Regel mit hoher Priorität übereinstimmen kann

definition_function 
    : DEFINE FUNCTION function_name '[' language_name ']' 
     RETURN attribute_type '{' function_body '}' 
    ; 

function_name 
    : id 
    ; 

language_name 
    : id 
    ; 

function_body 
    : SCRIPT 
    ; 

SCRIPT 
    : '{' ('\u0020'..'\u007e' | ~('{' | '}'))* '}' 
     { setText(getText().substring(1, getText().length()-1)); } 
    ; 

Aber wenn ich versuche, wie unten zwei Funktionen zu analysieren,

define function concat[Scala] return string { 
    var concatenatedString = "" 
    for(i <- 0 until data.length) { 
    concatenatedString += data(i).toString 
    } 
    concatenatedString 
}; 
define function concat[JavaScript] return string { 
    var str1 = data[0]; 
    var str2 = data[1]; 
    var str3 = data[2]; 
    var res = str1.concat(str2,str3); 
    return res; 
}; 

Dann ANTLR nicht diese wie zwei Funktionsdefinitionen analysieren, sondern wie eine einzige Funktion mit dem folgenden Körper,

var concatenatedString = "" 
    for(i <- 0 until data.length) { 
    concatenatedString += data(i).toString 
    } 
    concatenatedString 
}; 
define function concat[JavaScript] return string { 
    var str1 = data[0]; 
    var str2 = data[1]; 
    var str3 = data[2]; 
    var res = str1.concat(str2,str3); 
    return res; 

Können Sie dieses Verhalten erklären? Der Körper der Funktion kann alles enthalten. Wie kann ich diese Grammatik korrekt definieren?

Antwort

0

Es sei denn, Sie absolut SCRIPT benötigen ein Token (durch eine Lexer Regel anerkannt) zu sein, können Sie eine Parser Regel verwenden, die verschachtelten Blöcke (unter der Block Regel) erkennt. Die Grammatik, die hier enthalten ist, sollte Ihr Beispiel als zwei verschiedene Funktionsdefinitionen analysieren.

DEFINE : 'define'; 
FUNCTION : 'function'; 
RETURN : 'return'; 
ID : [A-Za-z]+; 
ANY : . ; 
WS : [ \r\t\n]+ -> skip ; 

test : definition_function* ; 

definition_function 
    : DEFINE FUNCTION function_name '[' language_name ']' 
     RETURN attribute_type block ';' 
    ; 

function_name : id ; 
language_name : id ; 
attribute_type : 'string' ; 
id : ID; 

block 
    : '{' ((~('{'|'}'))+ | block)* '}' 
    ; 
+1

Beachten Sie, dass Lexer Regeln auch rekursiv enthalten (Lexer) Regeln. Beachten Sie, dass innerhalb einer Parser-Regel '~ ('{' | '}')' nicht * mit irgendeinem char ** anders als '{' und '}' übereinstimmt, sondern ** mit einem anderen Token ** die Token, die mit '{' und '}' übereinstimmen. –

3

Ihre Regel entspricht, dass viel, weil '\u0020'..'\u007e' der Regel '{' ('\u0020'..'\u007e' | ~('{' | '}'))* '}' Matches sowohl { und }.

Die Regel sollte funktionieren, wenn Sie es wie folgt definieren:

SCRIPT 
    : '{' (SCRIPT | ~('{' | '}'))* '}' 
    ; 

Dies wird jedoch fehlschlagen, wenn der Skriptblock enthält, sagt, Strings oder Kommentare, die { oder } enthalten. Hier ist ein Weg, um eine SCRIPT Token übereinstimmen, einschließlich der Kommentare und Stringliterale die { und ‚}‘ enthalten könnte:

SCRIPT 
: '{' SCRIPT_ATOM* '}' 
; 

fragment SCRIPT_ATOM 
: ~[{}] 
| '"' ~["]* '"' 
| '//' ~[\r\n]* 
| SCRIPT 
; 

Eine vollständige Grammatik, die richtig analysiert Ihre Eingabe dann würde wie folgt aussehen:

grammar T; 

parse 
: definition_function* EOF 
; 

definition_function 
: DEFINE FUNCTION function_name '[' language_name ']' RETURN attribute_type SCRIPT ';' 
; 

function_name 
: ID 
; 

language_name 
: ID 
; 

attribute_type 
: ID 
; 

DEFINE 
: 'define' 
; 

FUNCTION 
: 'function' 
; 

RETURN 
: 'return' 
; 

ID 
: [a-zA-Z_] [a-zA-Z_0-9]* 
; 

SCRIPT 
: '{' SCRIPT_ATOM* '}' 
; 

SPACES 
: [ \t\r\n]+ -> skip 
; 

fragment SCRIPT_ATOM 
: ~[{}] 
| '"' ~["]* '"' 
| '//' ~[\r\n]* 
| SCRIPT 
; 

die auch richtig die folgende Eingabe analysiert:

define function concat[JavaScript] return string { 
    for (;;) { 
    while (true) { } 
    } 
    var s = "}" 
    // } 
    return s 
}; 
+0

Danke, das hat funktioniert :) – Ayash

Verwandte Themen