Stack iniettabile, Poppable

0

Sfondo

Un progetto comporta la conversione di una mappa di espressioni relazionali ( rxm ) in un'istruzione XML / SQL. La mappa è simile a:

root               > people,            # "root" keyword starts the document
person             > person,            # maps table context to a node
.first_name        > first,             # maps a column to a node
.last_name         > name/last,         # maps a column to an ancestor node
.age               > @age,              # @ maps a column to an attribute node
account.person_id +> person.person_id,  # +> performs an INNER JOIN
account            > account,           # context is now "account" node
.id                > @id,               # account id attribute
^,                                      # pop stack to previous context
address            > address,           # switch context to "address" node
.*,                                     # .* globs all columns
account.person_id -> company.person_id, # -> performs an OUTER JOIN
;                                       # Starts the optional WHERE clause

Il rxm viene convertito in classi Java usando ANTLR.

Camminando attraverso AST utilizza un pattern Visitor che chiama i metodi per entrare e uscire da varie parti dell'albero. Ad esempio:

  @Override
  public void enterRoot( QueryParser.RootContext context ) {
    System.out.println( "Root: " + context.getChild(2).getText() );
  }

  @Override
  public void exitRoot( QueryParser.RootContext context ) {
    System.out.println( "<< root" );
  }

Problema

Il codice deve generare un'istruzione XML / SQL sulla falsariga di:

XMLROOT (
  XMLELEMENT (
    NAME people,
    XMLELEMENT (
      NAME person,
      XMLATTRIBUTE( ... )
    )
  ),
  VERSION ’1.0’,
  STANDALONE YES
)

Nel momento in cui vengono chiamati enterRoot o exitRoot , non è noto se ci sarà un'altra linea mappata usando rxm . Idealmente, mi piacerebbe scrivere:

  @Override
  public void enterRoot( QueryParser.RootContext context ) {
    String root = context.getChild(2).getText();
    getStack().push( "SELECT XMLROOT( XMLELEMENT( NAME " + root );
    getStack().push( "VERSION '1.0', STANDALONE YES )" );
  }

Domanda

L'utilizzo di uno stack sembra essere un buon modo per generare la query in base al modello di visitatore.

Quale struttura dati useresti per convertire una mappa lineare in una query gerarchica?

Sarebbe possibile, ad esempio, inserire semplicemente l'ultimo elemento dallo stack (ad esempio, la riga contenente la parentesi di chiusura), archiviarlo localmente, quindi reinserirlo in seguito?

    
posta Dave Jarvis 03.03.2015 - 02:56
fonte

1 risposta

2

Usa una struttura dati Tree e convertilo in una stringa usando i metodi polimorfo toString ricorsivi.

Consentitemi di ripetere la vostra domanda con parole mie per assicurarmi di aver capito bene:

Sembra che tu stia scrivendo un Domain Specific Language (DSL) che desideri convertire direttamente l'output desiderato tramite la manipolazione della stringa senza alcuna rappresentazione intermedia. La tua domanda riguarda la tua attuale soluzione e la tua scelta della struttura dei dati richiesta per la costruzione della stringa finale.

Se le tue richieste di ricorsione sono troppo profonde, puoi creare una serie di classi per camminare sull'albero e costruire la stringa mentre visitano ogni nodo utilizzando una prima ricerca approfondita. Tutto ciò presuppone che tu non abbia riferimenti circolari nel tuo albero.

Dopo aver riletto la domanda, penso di avere una migliore comprensione di ciò che hai implementato e di quali strumenti stai usando. Avevo dato per scontato che stavi saltando l'intero processo della generazione di AST perché mi mancava quello nelle mie prime letture. Puoi controllare come i visitatori camminano sull'albero? Se inizi a costruire la tua stringa con il figlio più profondo e prima di iniziare a risalire la struttura, dovresti semplicemente avvolgere la stringa precedente con i tag di apertura e di chiusura del nodo corrente. Quindi non è necessario tracciare se devi inserire o meno un tag di chiusura, lo fai sempre.

    
risposta data 03.03.2015 - 20:58
fonte

Leggi altre domande sui tag