2010-09-09 20 views
2

J'utilise Cocor pour générer un scanner comme java/analyseur:
Je vais avoir quelques problèmes dans la création d'une expression EBNF pour correspondre à un bloc de code:Parsing un bloc de code avec l'expression EBNF

Je suppose un bloc de code est entouré de deux jetons bien connus: < & et &> exemple:

public method(int a, int b) <& 
various code 
&> 

Si je définis un symbole non terminal

codeblock = "<&" {ANY} "&>" 

Si le code à l'intérieur des deux symboles contient un caractère '<', le compilateur généré ne le traitera pas, donnant ainsi une erreur de syntaxe.

Un conseil?

Edit:

COMPILER JavaLike 
CHARACTERS 

nonZeroDigit = "123456789". 
digit   = '0' + nonZeroDigit . 
letter  = 'A' .. 'Z' + 'a' .. 'z' + '_' + '$'. 

TOKENS 
ident = letter { letter | digit }. 

PRODUCTIONS 
JavaLike = {ClassDeclaration}. 
ClassDeclaration ="class" ident ["extends" ident] "{" {VarDeclaration} {MethodDeclaration }"}" . 
MethodDeclaration ="public" Type ident "("ParamList")" CodeBlock. 
Codeblock = "<&" {ANY} "&>". 

J'ai omis certaines productions pour des raisons de simplicité.
Ceci est ma mise en œuvre réelle de la grammaire. Le bug principal est qu'il échoue si le code dans le bloc contient l'un des symboles '>' ou '&'.

Répondre

0

Vous pouvez étendre le terme ANY pour inclure <&, &> et un autre non terminal (appelez-le ANY_WITHIN_BLOCK dire).

Ensuite, vous utilisez juste

ANY = "<&" | {ANY_WITHIN_BLOCK} | "&>" 
codeblock = "<&" {ANY_WITHIN_BLOCK} "&>" 

Et puis le sens de {ANY} ne change pas si vous avez vraiment besoin plus tard. D'accord, je ne connaissais rien à CocoR et je vous ai donné une réponse inutile, alors essayons à nouveau. Comme je l'ai commencé à le dire plus tard dans les commentaires, je pense que le vrai problème est que votre grammaire pourrait être trop lâche et pas suffisamment bien spécifié. Quand j'ai écrit le CFG pour la langue que j'ai essayé de créer, j'ai fini par utiliser une sorte d'approche «se rencontrer dans le milieu»: j'ai écrit la structure de haut niveau ET le bas niveau immédiat. Les combinaisons de niveau de jetons d'abord, et ensuite travaillé pour les faire se rencontrer dans le niveau intermédiaire (à peu près au niveau des conditions et du flux de contrôle, je suppose).

Vous avez dit que cette langue est un peu comme Java, alors laissez-moi vous montrer les premières lignes que j'écrirais comme premier brouillon pour décrire sa grammaire (en pseudocode, désolé, en fait, c'est comme yacc/bison. J'utilise vos crochets au lieu de Java de):

/* High-level stuff */ 

program: classes 

classes: main-class inner-classes 

inner-classes: inner-classes inner-class 
      | /* empty */ 

main-class: class-modifier "class" identifier class-block 

inner-class: "class" identifier class-block 

class-block: "<&" class-decls "&>" 

class-decls: field-decl 
      | method 

method: method-signature method-block 

method-block: "<&" statements "&>" 

statements: statements statement 
      | /* empty */ 

class-modifier: "public" 
       | "private" 

identifier: /* well, you know */ 

et en même temps que vous faites tout ce que, figure vos combinaisons de jeton immédiates, comme par exemple la définition de « numéro » comme un flotteur ou un int et puis créer des règles pour ajouter/soustraire/etc. leur.

Je ne sais pas quelle est votre approche jusqu'à présent, mais vous voulez certainement vous assurer de bien spécifier tout et utiliser de nouvelles règles lorsque vous voulez une structure spécifique. Ne soyez pas ridicule avec la création de règles individuelles, mais n'ayez jamais peur de créer une nouvelle règle si cela vous aide à mieux organiser vos pensées.

+0

Comment définiriez-vous ANY_WITHIN_BLOCK? – nick2k3

+0

Comment définissez-vous ANY? –

+0

ANY est le jeton "jolly" dans CocoR: il correspond à tous les jetons. – nick2k3

1

Nick, retard à la fête ici ...

Un certain nombre de façons de le faire:

Define jetons pour <& et &> de sorte que le lexer connaît.

Vous pourriez être en mesure d'utiliser une directive COMMENTAIRES

COMMENTAIRES DE <& À &> - cité comme CoCo attend.

Ou faites hack NextToken() dans votre fichier scanner.frame. Faites quelque chose comme ceci (pseudo-code):

if (Peek() == CODE_START) 
{ 
    while (NextToken() != CODE_END) 
    { 
     // eat tokens 
    } 
} 

Ou peut remplacer la méthode Read() dans la mémoire tampon et de manger au plus bas niveau.

HTH