next up previous contents index
Nächste Seite: C. API-Dokumentation Aufwärts: main Vorherige Seite: Unterparagraphüberschrift   Inhalt   Index

B. Programm

Als Beispiel für das Einbinden von Quelltext ist in diesem Anhang der Quelltext einer Parser-Grammatik dokumentiert. Für die Darstellung des Quelltextes wird das Paket listings und das darin enthaltenen Makro \lstinputlisting{} verwendet. Durch \lstinputlisting{} kann eine separate Datei mit Quelltext eingebunden werden. Alternativ kann der Quelltext direkt in der LATEX-Datei innerhalb der Umgebung lstlisting angegeben werden.

Weil die HTML-Ausgabe mittels LATEX2HTML das Pakt listings nicht unterstützt, ist hierfür eine separate Ausgabe des Quelltextes innerhalb einer verbatim-Umgebung notwendig. Hier kann das Makro \verbatiminput{} aus dem Paket verbatim verwendet werden, um eine separate Datei einzulesen. Für die direkte angabe von Quelltext innerhalb der LATEX-Datei kann die gewohnte verbatim-Umgebung verwendet werden.

Zuerst wird an dieser Stelle die vom Parser zum Einlesen von gültigen Zeichen benötigte Datei scanner.lex für die lexikalische Analyse durch JLex aufgeführt (vgl. Berk, 2000):


package yacs.parser;

import java_cup.runtime.Symbol;

%%

%cup
%public

ALPHA=[A-Za-z]
DIGIT=[0-9]

%%

";"                             {return new Symbol(sym.SEMI);}
","                             {return new Symbol(sym.COMMA);}
"="                             {return new Symbol(sym.EQUAL);}
"!="                            {return new Symbol(sym.NOT_EQUAL);}
">"                             {return new Symbol(sym.GREATER);}
"<"                             {return new Symbol(sym.LOWER);}
">="                            {return new Symbol(sym.GREATER_EQUAL);}
"<="                            {return new Symbol(sym.LOWER_EQUAL);}
"+"                             {return new Symbol(sym.PLUS);}
"-"                             {return new Symbol(sym.MINUS);}
"*"                             {return new Symbol(sym.TIMES);}
"/"                             {return new Symbol(sym.DIVIDE);}
"("                             {return new Symbol(sym.LPAREN);}
")"                             {return new Symbol(sym.RPAREN);}
"["                             {return new Symbol(sym.LBRACKET);}
"]"                             {return new Symbol(sym.RBRACKET);}
{DIGIT}+                        {return new Symbol(sym.NUMBER,
                                                   new Integer(yytext()));}
{DIGIT}+"."{DIGIT}+             {return new Symbol(sym.FLOAT,
                                                   new Double(yytext()));}
{ALPHA}({ALPHA}|{DIGIT}|_|".")* {return new Symbol(sym.VARIABLE, yytext());}
[ \t\r\n\f\b]                   {/* ignore white space. */}
.                               {System.err.println("Illegal character: "
                                                    +yytext());}

Von Scanner erfasste Zeichen werden an den Parser weitergegeben und anhand der Java-CUP-Grammatik in der Datei parser.cup ausgewertet (vgl. Hudson, 1999):


package yacs.parser;

import java.util.HashMap;

import yacs.domain.*;

import java_cup.runtime.*;

action code {:
  /* this is where the action code goes */

  /** der erzeugte Ausdruck */
  public Expression expression;

  /** HashtMap zum "Wiederfinden" der generierten Variablen */
  public HashMap actionVariablesMap = new HashMap();

  /** temporaere Variable zum Zwischenspeichern */
  public Variable tmpVariable;

:};

parser code {:
 /* this is where the parser code goes */

  /** HashtMap zum Zwischenspeichern der bereits vorhandenen Variablen */
  public HashMap parserVariablesMap = new HashMap();

 /**
  * Hinzufuegen bereits vorhandener Variablen. Anstatt neue Variablen
  * zu erzeugen, werden so die Referenzen bestehender Objekte
  * verwendet.
  * @param variablesMap HashMap
  */
  public void addVariablesMap(HashMap variablesMap) {
    this.parserVariablesMap.putAll(variablesMap);
  }

 /**
  * Gibt den gescannten und geparsten Ausdruck als Expression zurueck.
  * @return Expression
  */
  public Expression expression() {
    return action_obj.expression;
  }

:};

init with {:

  // Die in "parser" bereits befindlichen Variablenreferenzen in das
  // "action_obj" uebertragen. Dies muss hier separat geschehen, da
  // erst waehrend der "init"-Phase das "action_obj" instantiiert ist.
  action_obj.actionVariablesMap.putAll(this.parserVariablesMap);

:};

/* Terminals (tokens returned by the scanner). */
terminal          UMINUS, SEMI, LPAREN, RPAREN, COMMA, LBRACKET, RBRACKET;
terminal          PLUS, MINUS, TIMES, DIVIDE;
terminal          EQUAL, NOT_EQUAL, GREATER, LOWER, GREATER_EQUAL, LOWER_EQUAL;
terminal Integer  NUMBER;
terminal Double   FLOAT;
terminal String   VARIABLE;

/* Non Terminals */
non terminal             expr_all;
non terminal Expression  expr_list, expr, expr_part;

/* Precedences */
precedence left EQUAL, NOT_EQUAL, GREATER, LOWER, GREATER_EQUAL, LOWER_EQUAL;
precedence left PLUS, MINUS;
precedence left TIMES, DIVIDE;
precedence left UMINUS;

/* The grammar */

expr_all   ::= expr_list:e
               {:
                System.out.println(" => "+e.toString());
                this.expression = e;
               :}
             ;

expr_list  ::= expr:e
               {: RESULT = e; :}
             | expr_list:l expr:r
               {: RESULT = new BinaryOperator(sym.SEMI, ";", l, r); :}
             ;

expr       ::= expr_part:l EQUAL expr_part:r SEMI
               {: RESULT = new BinaryOperator(sym.EQUAL, "=", l, r); :}
             | expr_part:l NOT_EQUAL expr_part:r SEMI
               {: RESULT = new BinaryOperator(sym.NOT_EQUAL, "!=", l, r); :}
             | expr_part:l GREATER expr_part:r SEMI
               {: RESULT = new BinaryOperator(sym.GREATER, ">", l, r); :}
             | expr_part:l LOWER expr_part:r SEMI
               {: RESULT = new BinaryOperator(sym.LOWER, "<", l, r); :}
             | expr_part:l GREATER_EQUAL expr_part:r SEMI
               {: RESULT = new BinaryOperator(sym.GREATER_EQUAL, ">=", l, r); :}
             | expr_part:l LOWER_EQUAL expr_part:r SEMI
               {: RESULT = new BinaryOperator(sym.LOWER_EQUAL, "<=", l, r); :}
             ;

expr_part  ::= NUMBER:n
               {: RESULT = new Constant(n); :}
             | LBRACKET FLOAT:lo COMMA FLOAT:hi RBRACKET
               {: RESULT = new Constant(lo, hi); :}
             | LBRACKET NUMBER:lo COMMA NUMBER:hi RBRACKET
               {: RESULT = new Constant(lo.doubleValue(), hi.doubleValue()); :}
             | LBRACKET FLOAT:lo COMMA NUMBER:hi RBRACKET
               {: RESULT = new Constant(lo.doubleValue(), hi.doubleValue()); :}
             | LBRACKET NUMBER:lo COMMA FLOAT:hi RBRACKET
               {: RESULT = new Constant(lo.doubleValue(), hi.doubleValue()); :}
             | VARIABLE:v
               {: tmpVariable = (Variable)actionVariablesMap.get(v);
                  if (tmpVariable == null) {
                    // Variable mit leerer Domaene instantiieren:
                    tmpVariable = new Variable(v, new Domain());
                    actionVariablesMap.put(v, tmpVariable);
                  }
                  RESULT = tmpVariable;
               :}
             | expr_part:l PLUS expr_part:r
               {: RESULT = new BinaryOperator(sym.PLUS, "+", l, r); :}
             | expr_part:l MINUS expr_part:r
               {: RESULT = new BinaryOperator(sym.MINUS, "-", l, r); :}
             | expr_part:l TIMES expr_part:r
               {: RESULT = new BinaryOperator(sym.TIMES, "*", l, r); :}
             | expr_part:l DIVIDE expr_part:r
               {: RESULT = new BinaryOperator(sym.DIVIDE, "/", l, r); :}
             | MINUS expr_part:e
               {: RESULT = new UnaryOperator(sym.UMINUS, "-", e); :}
               %prec UMINUS
             | LPAREN expr_part:e RPAREN
               {: RESULT = e; :}
             ;


next up previous contents index
Nächste Seite: C. API-Dokumentation Aufwärts: main Vorherige Seite: Unterparagraphüberschrift   Inhalt   Index