Willkommen bei Bartels
Einführung in die User Language Programmierung - Deutsche Version Introducing User Language Programming - English Version
Bartels

Bartels System GmbH
[13.07.2017 13:03:54 [UTC]] Willkommen bei Bartels / AktualisiertBartels
Bartels AutoEngineer
BAE Produktinfo
BAE Preisliste
BAE Downloads
BAE Dokumentation
BAE Installationsanleitung
BAE Benutzerhandbuch
BAE Bibliotheken
User Language Programmierhandbuch
Vorwort
1 Einleitung
2 Sprachbeschreibung
2.1 Einführung in die User Language Programmierung
2.1.1 Ein erstes User Language Programm
2.1.2 Variablen, Arithmetik und Funktionen
2.1.3 Vektoren und Kontrollstrukturen
2.2 Konventionen
2.3 Datentypen und Definitionen
2.4 Ausdrücke
2.5 Kontrollstrukturen
2.6 Preprozessor-Anweisungen
2.7 Syntaxdefinition
3 Programmiersystem
4 BAE User Language-Programme
A Konventionen und Definitionen
B Index-Variablen-Typen
C Systemfunktionen
BAE Update-Historie
BAE Nächste Version Freigabemitteilungen Vorabinfo
BAE V8.0 Freigabemitteilungen
BAE V7.8 Freigabemitteilungen
BAE V7.6 Freigabemitteilungen
BAE V7.4 Freigabemitteilungen
BAE V7.2 Freigabemitteilungen
BAE V7.0 Freigabemitteilungen
BAE V6.8 Freigabemitteilungen
BAE V6.6 Freigabemitteilungen
BAE V6.4 Freigabemitteilungen
BAE V6.2 Freigabemitteilungen
BAE V6.0 Freigabemitteilungen
BAE V5.4 Freigabemitteilungen
BAE V5.0 Freigabemitteilungen
BAE V4.6 Freigabemitteilungen
BAE V4.4 Freigabemitteilungen
BAE V4.2 Freigabemitteilungen
BAE V4.0 Freigabemitteilungen
BAE V3.4 Freigabemitteilungen
BAE Support
BAE Contrib
BAE Entwickler und Dienstleister
Elektronikentwicklung
Sport
Firmenprofil
Impressum
Bartels :: Bartels AutoEngineer :: BAE Dokumentation :: User Language Programmierhandbuch :: Sprachbeschreibung :: Einführung in die User Language Programmierung
Bartels User Language - Programmierhandbuch

2.1 Einführung in die User Language Programmierung

Bartels AutoEngineer® Dokumentation

An dieser Stelle sollen anhand kleiner Programmbeispiele die wichtigsten Sprachelemente der User Language kurz vorgestellt werden, ohne zunächst Wert auf Vollständigkeit zu legen bzw. auf Details oder gar Ausnahmeregelungen einzugehen. Ziel dabei ist, möglichst schnell die Vorgehensweise bei der User Language Programmierung aufzuzeigen.

 

2.1.1 Ein erstes User Language Programm

Als erstes soll ein Programm erstellt werden, welches lediglich eine Meldung ausgibt und dann auf eine Eingabe wartet, um den Programmlauf abzubrechen. Dies ist im Übrigen bereits ein Programmkonstrukt, das innerhalb des Bartels AutoEngineer relativ häufig benötigt wird. Wie Sie bereits aus der Einleitung wissen, muss ein User Language-Programm mindestens aus der main-Funktion bestehen. Was innerhalb der main-Funktion benötigt wird, ist eine Anweisung, die die gewünschte Meldung ausgibt, sowie eine Anweisung, die eine Benutzerabfrage aktiviert. Beide Anweisungen werden durch den Aufruf entsprechender User Language Systemfunktionen (printf und askstr) realisiert. Diese Systemfunktionen sind dem Compiler bekannt, und in den Interpreter eingebunden, d.h. der Programmierer muss lediglich wissen, wie diese Funktionen aufzurufen sind, und was sie tun (diese Information kann dem Anhang C dieses Handbuchs entnommen werden). Erstellen Sie nun mit Ihrem Texteditor folgendes User Language-Programm und speichern Sie dieses unter dem Dateinamen ulprog.ulc ab (an der File-Extension .ulc erkennt der Compiler, dass es sich um ein User Language Programm handelt):

main()
{
      printf("User Language Program");
      askstr("Press ENTER to continue ",1);
}

Wie Sie sehen, besteht das Programm lediglich aus der Definition der Funktion main. Innerhalb der runden Klammern nach dem Funktionsnamen stehen normalerweise die formalen Parameter der Funktion. Um den Funktionsnamen von anderen Variablennamen zu unterscheiden, sind diese Klammern auch anzugeben, wenn, wie in obigem Beispiel, keine Parameter existieren. Innerhalb der geschweiften Klammern befindet sich der Rumpf der Funktion, d.h. die Anweisungen, die die Funktion ausführen soll. Jede Anweisung wird durch ein Semikolon (;) abgeschlossen. Die erste Anweisung innerhalb der Funktion main ist der Aufruf der Funktion printf, was an der nachfolgenden runden Klammer zu erkennen ist. Als Argument bzw. Parameter wird an printf (in doppelten Anführungszeichen) eine konstante Zeichenkette übergeben, die das Programm bei fehlerfreier Übersetzung und Ausführung am Bildschirm ausgibt. Die zweite Anweisung ist ein Aufruf der Funktion askstr. Diese Funktion gibt in der Eingabe- bzw. Mitteilungszeile des Bartels AutoEngineer ihr erstes Argument in Form eines Prompts aus und wartet auf die Eingabe einer Zeichenkette durch den Anwender. Der zweite Parameter zu askstr gibt dabei die maximal zulässige Länge der einzugebenden Zeichenkette an. Der Aufruf von askstr ist zugleich die letzte Anweisung des Programms, d.h. nach der Bearbeitung des askstr-Aufrufs wird das Programm beendet. Wenn das Programm fertig codiert und unter ulprog.ulc abgespeichert ist, kann es mit folgendem Aufruf des User Language Compilers übersetzt werden:

ulc ulprog

Falls keine Fehler auftreten, gibt der Compiler die folgende Meldung auf dem Bildschirm aus:

==============================
BARTELS USER LANGUAGE COMPILER
==============================

Quellcodedatei "ulprog.ulc" wird kompiliert...
Programm 'ulprog' erfolgreich generiert.
Quellcodedatei "ulprog.ulc" erfolgreich kompiliert.

Keine Fehler, keine Warnungen.
User Language Compiler-Lauf erfolgreich beendet.

Der Compiler hat das Programm übersetzt und unter dem Namen ulprog in der Datei ulcprog.vdb im Bartels AutoEngineer Programmverzeichnis abgespeichert. Jetzt kann das Programm durch den User Language Interpreter ausgeführt werden. Hierzu ist z.B. der Schaltplaneditor des Bartels AutoEngineer aufzurufen und die Funktion Anwenderfunktion im Menü Datei zu aktivieren. Auf die Abfrage nach dem Namen des auszuführenden Programms ist anschließend ulprog einzugeben:

DateiLinke Maustaste (LMB)
AnwenderfunktionLinke Maustaste (LMB)
Programmname ?ulprog Return-/Eingabetaste (CR)

Der Grafikarbeitsbereich des AutoEngineer wird in den Textmodus geschaltet und es wird die Meldung User Language Program angezeigt. Anschließend wird im Eingabefenster der Prompt Press ENTER to continue angezeigt. Betätigt der Anwender daraufhin die Return-Taste, dann wird das User Language-Programm beendet und der Grafikarbeitsbereich wieder in den Grafikmodus zurückgeschaltet.

 

2.1.2 Variablen, Arithmetik und Funktionen

Anhand des nächsten Beispiels sollen eine ganze Reihe weiterer spezifischer Eigenschaften der User Language veranschaulicht werden. Das folgende Programm überprüft einige durch ihren Mittelpunkt und ihren Radius definierte Kreise daraufhin, ob sie sich überlappen (Bohrdatentest?!), und gibt entsprechende Meldungen aus:

// Circle Test Program

double tol=0.254*5;           // Tolerance

struct pos {                  // Position descriptor
      double x;               // X coordinate
      double y;               // Y coordinate
      };

struct circle {               // Circle descriptor
      double rad;             // Circle radius
      struct pos c;           // Circle position
      };

// Main program
main()
{
      // Define three circles
      struct circle c1 = {  4.5, { 19.4, 28.3} };
      struct circle c2 = { 17.0, { 37.6, 9.71} };
      struct circle c3 = { 1.5E01, { 25, 0.2e2} };
      // Perform circle test
      printf("Circle 1 - 2 overlap : %d\n",circletest(c1,c2));
      printf("Circle 1 - 3 overlap : %d\n",circletest(c1,c3));
      printf("Circle 2 - 3 overlap : %d\n",circletest(c2,c3));
      // Prompt for continue
      askstr("Press ENTER to continue ",1);
}

int circletest(c1,c2)
// Circle test function
// Returns: nonzero if overlapping or zero else
struct circle c1,c2           /* Test circles 1 and 2 */;
{
      double d                /* Distance value */;
      // Get circle center point distances
      d=distance(c1.c,c2.c);
      // Error tolerant check distance against radius sum
      return(d<=(c1.rad+c2.rad+tol));
}

double distance(p1,p2)
// Get distance between two points
// Returns: distance length value
struct pos p1                 /* Point 1 */;
struct pos p2                 /* Point 2 */;
{
      double xd=p2.x-p1.x     /* X distance */;
      double yd=p2.y-p1.y     /* Y distance */;
      // Calculate and return distance
      return(sqrt(xd*xd+yd*yd));
}

Obiger Quelltext enthält eine Reihe von Kommentaren, die durch /* und */ eingeklammert sind; diese Kommentare dürfen sich über mehrere Zeilen erstrecken, aber sie dürfen nicht verschachtelt werden. Ein anderer Typ von Kommentar beginnt mit // und erstreckt sich jeweils bis zum Zeilenende. Sie sollten sich angewöhnen, Ihre Programme mit derartiger Inline-Dokumentation zu versehen, damit der Programmcode gut verständlich bleibt und somit - auch durch dritte - leichter gepflegt bzw. weiterentwickelt werden kann.

Das Programm enthält weiterhin eine Reihe von Variablendefinitionen. Variablen müssen grundsätzlich vor ihrer Verwendung definiert werden. Dabei wird sowohl der Datentyp als auch der Variablenname festgelegt. Unterschieden wird zwischen globalen Variablen, lokalen Variablen und Funktionsparametern. Der Geltungsbereich globaler Variablen erstreckt sich über das gesamte Programm. Lokale Variablen sind nur innerhalb der Funktion, in der sie definiert wurden, gültig. Funktionsparameter dienen dazu, Werte an Funktionen zu übergeben. In obigem Beispiel wird als einzige globale Variable tol mit dem Datentyp double definiert. Beispiele für lokale Variablen sind die double-Variablen xd und yd in der Funktion distance. Funktionsparameter sind z.B. c1 und c2 in der Funktion circletest. Diese sind von dem speziell definierten zusammengesetzten struct-Datentyp circle. Initialisierungen globaler und lokaler Variablen lassen sich bereits bei deren Deklaration durchführen. Beispiele hierfür sind die globale Variable tol sowie die lokalen Variablen xd und yd der Funktion distance. Auch zusammengesetzte Datentypen lassen sich initialisieren, wie die Beispiele für die lokalen struct-Variablen c1, c2 und c3 der Funktion main zeigen. Bei der Variablendeklaration besteht darüber hinaus die Möglichkeit, gleich eine ganze Liste von Variablennamen anzugeben (siehe Parameterdeklaration für c1 und c2 in der Funktion circletest).

Die Berechnung von Werten erfolgt über Ausdrücke, wobei das Gleichheitszeichen (=) als Zuweisungsoperator fungiert.

Bei der Definition von Funktionen ist ebenfalls ein Datentyp zu spezifizieren. In obigem Beispiel ist die Funktion distance vom Typ double, die Funktion circletest vom Typ int. Wird die Datentypspezifikation - wie bei der Funktion main - weggelassen, dann wird deren Typ automatisch auf int gesetzt. Ein spezieller Datentyp für Funktionen ist void. Jede Funktion außer den void-Funktionen liefert einen zum Funktionsdatentyp kompatiblen Rückgabewert. Die Übergabe des Rückgabewerts geschieht mit der return-Funktion, welche gleichzeitig die Funktionsausführung beendet.

 

2.1.3 Vektoren und Kontrollstrukturen

An dieser Stelle sei abschließend ein Beispiel für die Verwendung von Vektoren und Kontrollstrukturen aufgeführt. Das nachfolgende Programm wandelt eine ganze Liste von Integerwerten in Strings um und gibt diese aus:

// Integer list
int intary[]={ 0,17,-12013,629,0770,0xFF,-16*4+12 };

// Main program
main()
{
      int i                   /* Loop control variable */;
      // Set last integer value
      intary[10]=(-1);
      // Loop through integer list
      for (i=0;i<=10;i++)
              // Print integer and integer string
              printf("%8d : \"%s\"\n",intary[i],inttostr(intary[i]));
      // Prompt for continue
      askstr("Press ENTER to continue ",1);
}

string inttostr(int intval)
// Convert integer value to a string
// Returns: resulting string
{
      string resstr=""        /* Result string */;
      int n=intval,i=0        /* Integer value, loop counter */;
      char sign               /* Sign character */;
      // Test for negative integer value
      if (n==0)
              // Return zero integer string
              return("0");
      else if (n>0)
              // Set sign to plus character
              sign='+';
      else {
              // Make integer value positive
              n=-n;
              // Set sign to minus character
              sign='-';
              }
      // Build result string
      do {    // Get and append next character
              resstr[i++]=n%10+'0';
              } while ((n/=10)!=0);
      // Append zeros
      while (i++<15)
              resstr+='0';
      // Append sign character
      resstr+=sign;
      // Reverse string
      strreverse(resstr);
      // Return string result
      return(resstr);
}

In obigem Programm wird ein Vektor aus Integerwerten (globale int-Variable intary) deklariert und dabei auch bereits (teilweise) initialisiert. Wie leicht zu erkennen ist, definiert das eckige Klammernpaar nach dem Variablennamen intary einen eindimensionalen int-Vektor. Mehrdimensionale Vektoren sind durch entsprechendes Anfügen weiterer eckiger Klammernpaare (intary[][]...[]) zu deklarieren. Zu beachten ist dabei, dass die Angabe einer Feldlänge entfällt. Dies resultiert aus der Fähigkeit der User Language, Vektoren dynamisch zu verwalten, d.h. sowohl dem Compiler als auch dem Interpreter genügt die Information über die Dimension des Vektors. Allerdings erfolgen doch einige Prüfungen, die den Zugriff auf nicht existente Vektorelemente (und damit eine Speicherzugriffsverletzung) unterbinden. So erkennt der Compiler z.B., wenn versucht wird, über einen konstanten, negativen (also ungültigen) Index auf ein Vektorelement zuzugreifen. Ebenso prüft der Interpreter Vektorindizes, die außerhalb des aktuell belegten Vektorfeldbereiches liegen. Beachten Sie hierbei, dass der Index mit dem Wert 0 auf das erste Element eines Vektors verweist.

Eine spezielle Form eines Vektors stellt der Datentyp string dar. User Language erlaubt die direkte Zuweisung von Vektoren kompatiblen Datentyps und gleicher Dimension. Dies wurde bei der Initialisierung der lokalen Variable resstr in der Funktion inttostr ebenso wie bei der Definition dieser Funktion als string und beim Setzen entsprechender Rückgabewerte in den return-Aufrufen ausgenutzt. Zudem lässt sich der Additionsoperator direkt auf string-Datentypen anwenden; das Resultat entspricht dabei einem durch Aneinanderfügen der beiden Additionsoperatoren erzeugten string.

Obiges Programmbeispiel enthält einige Kontrollstrukturen. So wird in der Funktion main über eine for-Schleife die Vektorvariable intary abgearbeitet. In der Funktion inttostr werden eine while- und eine do-while-Schleife verwendet, um die string-Variable resstr zu manipulieren. Des Weiteren enthält die Funktion inttostr eine if-Kontrollstruktur, die in Abhängigkeit vom Wert der lokalen Variablen n jeweils in einen entsprechenden Programmblock verzweigt.

Bartels :: Bartels AutoEngineer :: BAE Dokumentation :: User Language Programmierhandbuch :: Sprachbeschreibung :: Einführung in die User Language Programmierung

Einführung in die User Language Programmierung
© 1985-2017 Oliver Bartels F+E • Aktualisiert: 26. January 2007, 17:23 [UTC]

© 1985-2017 Oliver Bartels F+E Bartels Startseite Kontakt und Impressum

Webentwicklung Baumeister Mediasoft Engineering

Einführung in die User Language Programmierung - Deutsche Version Introducing User Language Programming - English Version