2009-09-17 5 views
2

Je travaille sur l'écriture d'un interpréteur Prolog simple en Java.Comment puis-je trouver l'index du premier "élément" dans ma chaîne en utilisant Java?

Comment puis-je trouver le dernier indice de caractère du premier élément, soit l'élément head ou l'élément tail d'une chaîne dans "List Syntax"?

Liste Syntaxe ressemble:

(X)
(PAB)
(func (func2 a) (fonc3 XY))
(veille égale (mère cain))

La tête pour chacune de ces chaînes dans l'ordre sont:
Head: "X", Index: 1
Head: "p", Index: 1 012 Head: « Fonction », Index: 4
tête: « égal », Indice 5

Fondamentalement, je dois correspondre à la chaîne qui suit immédiatement la première « (» et se termine soit par un espace ou une fermeture ")", peu importe lequel vient en premier. J'ai besoin de l'index de caractère du dernier caractère de l'élément de tête.

Comment puis-je faire correspondre et obtenir cet index en Java?


La solution de Brabster est vraiment proche. Cependant, considérons le cas de:
((b X) Y)

Lorsque l'élément de tête est (b x). J'ai essayé de le réparer en enlevant "(" des délimiteurs de scanner mais il hoquet toujours à cause de l'espace entre "b" et "x".)

De même: ((((b W) X) Y) Z)

Lorsque la tête est (((pc) x) Y).

Répondre

4

classe Java de Scanner (introduit en Java 1.5) pourrait être un bon endroit pour commencer.

Voici un exemple que je pense fait ce que vous voulez (mis à jour pour inclure la capacité de compter les caractères)

public class Test { 

    public static void main(String[] args) { 

     String[] data = new String[] { 
       "(X)", 
       "(p a b)", 
       "(func (func2 a) (func3 X Y))", 
       "(equal eve (mother cain))", 
       "((b X) Y)", 
       "((((b W) X) Y) Z)" 
     }; 


     for (String line:data) { 
      int headIdx = 0; 
      if (line.charAt(1) == '(') { 
       headIdx = countBrackets(line); 
      } else { 
       String head = ""; 
       Scanner s = new Scanner(line); 
       s.useDelimiter("[)|(| ]"); 
       head = s.next(); 
       headIdx = line.indexOf(head) + head.length() - 1; 
      } 
      System.out.println(headIdx); 
     } 

    } 

    private static int countBrackets(String line) { 
     int bracketCount = 0; 
     int charCount = 0; 
     for (int i = 1; i < line.length(); i++) { 
      char c = line.charAt(i); 
      if (c == '(') { 
       bracketCount++; 
      } else if (c == ')') { 
       bracketCount--; 
      } 
      if (bracketCount == 0) { 
       return charCount + 1; 
      } 
      charCount++; 
     } 
     throw new IllegalStateException("Brackets not nested properly"); 
    } 
} 

Sortie:

1 
1 
4 
5 
5 
13 

Ce n'est pas une solution très élégante, mais regexes ne peut pas compter (à savoir supports). Je penserais à utiliser un générateur d'analyseur s'il y a plus de complexité là-dedans :)

+0

Il peut également être utile d'examiner les générateurs d'analyse syntaxique comme ANTLR ou JavaCC si vous ne voulez pas vous occuper de l'analyse vous-même. – Brabster

+0

@Brabster, comment traitez-vous la chaîne: "((b X) Y)" où (b x) était le chef de la liste? –

+0

@Brabster, j'ai essayé de supprimer "(" de la liste des délimiteurs mais j'ai encore des problèmes à cause de l'espace entre b et x –

0

Je vous suggère d'écrire un analyseur approprié (operator precedence dans le cas de Prolog) et de représenter les termes comme des arbres d'objets Java pour un traitement ultérieur .

+0

J'utilise ceci comme un exemple minimal et minimal d'une fonctionnalité dans prolog (unification), où je ne pense pas un lexer/parser est warran ted. –

+0

Ensuite, je voudrais construire les structures d'objets directement et ne pas déranger avec des chaînes. – starblue

+0

@starblue, c'est ce que je ferais probablement si je faisais cela, construire les structures d'objet à la main. – mmcdole

1

Y a-t-il une raison pour laquelle vous ne pouvez pas le forcer? Quelque chose comme ça?

public int firstIndex(String exp) { 
    int parenCount = 0; 
    for (int i = 1; i < exp.length(); i++) { 
     if (exp.charAt(i) == '(') { 
      parenCount++; 
     } 
     else if (exp.charAt(i) == ')') { 
      parenCount--; 
     } 
     if (parenCount == 0 && (exp.charAt(i+1) == ' ' || exp.charAt(i) == ')')) { 
      return i; 
     } 
    } 
} 

je manquer quelque chose ici, mais je pense qui fonctionnerait.

+0

J'ai raté le commentaire supplémentaire de Brabster où il mentionne faire exactement exactement cela. – Morinar

Questions connexes