BlitzBasic Syntax

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

Vertex

Betreff: BlitzBasic Syntax

BeitragMi, Jul 21, 2010 18:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey,

lese gerade "Visionäre der Programmierung" (Interviews mit den Autoren von BASIC, Java, UML, C# usw.) und das hat mich mal wieder beflügelt mich mit BlitzBasic auseinander zu setzen.

Die Idee von diesem Thread ist, die Syntax von BlitzBasic nieder zu schreiben
Arrow Als Dokumentation
Arrow Als Referenz für Editoren-Entwickler
Arrow Als Referenz für Compiler-Entwickler

Wie ich finde, ist BlitzBasic eine hervorragende Lehrsprache. Das Problem ist bloß, dass BlitzBasic kommerziell vertrieben wird, weshalb es für Schulen und Unis nicht geeignet ist. Für die Unis im Bereich der theoretischen Informatik, die sich auch mit Sprachen und Compilerbau beschäftigt, fehlt eine Syntaxbeschriebung von BB ebenfalls. Wir haben bspw. mit Pascal angefangen zu programmieren und haben dann in der theoretischen Informatik EBNF anhand von Pascal besprochen. Gleiches würde ich mir mit BB wünschen.

Ein bischen Theorie zu Sprachen angewandt auf BB, damit man die richtigen Begriffe bei den Diskussionen verwenden kann:
Arrow Ein Alphabet A ist eine Menge von Zeichen. Bei BB sind es alle exrweiterten ASCII Zeichen von Chr$(0) bis Chr$(255)
Arrow Mit A* bezeichnet man die Menge aller Wörter über A. In der Informatik spielt dabei keine Rolle, welche Zeichen das Wort beinhaltet. Beispiele für Wörter: "Print", "; A Comment", "Return A + B". Auch ein Leerzeichen ist demzufolge Bestandteil eines Wortes. Wörter in BB würde man als Programme bezeichnen.
Arrow Jede Teilmenge L von A*, d. h. jede Menge von Wörtern über A, heißt Sprache über A.
Sprachen können endlich viele oder unendlich viele Wörter enthalten. Endliche Sprachen lassen sich durch Aufzählen ihrer Wörter beschreiben. Die Sprache BB kann jedoch unendlich viele Wörter enthalten: "Print 1", "Print 1 : Print 2", "Print 1 : Print 2 : Print 3", ... sind alles Wörter und von denen gibt es unendlich viele in BB.
Um eine unendliche Sprache wie BB beschreiben zu können, benötigt man eine endliche Beschreibung. Das ist nur möglich, wenn die Sprache nach gewissen Regeln aufgebaut ist. Die Menge dieser Regeln wird als Syntax der Sprache bezeichnet; sie ist eine endliche Beschreibung der Sprache.

Definition Syntax: Die Syntax einer Programmiersprache ist die Gesamtheit der Regeln, die angeben, was ein Programm ist.

Definition Semantik: Die Semantik einer Programmiersprache ist die Gesamtheit der Regeln, die angeben, was ein Programm tut
[Hans Werner Lang: Algorithmen in Java]

Man unterscheidet bei der Semantik zwischen statischer und operationaler Semantik. Zwei typische Regeln für ersteres ist, dass Funktionen deklariert sein müssen, bevor man sie auffruft und der Typ auf der linken Seite einer Zuweisung der selbe sein muss wie der Typ auf der rechten Seite (bspw. x = 10 + 5: links int und rechts int). Zweiteres ist die eigentliche Semantik, die vorgibt, wie ein Sprachkonstrukt sich verhält. Beispielsweise dass erst der Else-Block ausgeführt wird, wenn der ausgewertete Ausdruck der If-Anweisung und aller ElseIf-Blöcke false ergibt.

Folgendes Dokument fasst ausschließlich die Syntaxregeln von BB zusammen:
Code: [AUSKLAPPEN]
-- Autor: Oliver Skawronek
-- Version: 1.02

-- Änderungen:
-- - Vertex 1.02:
--   - SIMPLE_TYPED_IDENTIFIER ::= IDENTIFIER (SIMPLE_PREFIX)?
--     wurde geändert in IDENTIFIER (SIMPLE_TYPE_PREFIX)?
--   - NULL_LITERAL := 'Null'
--     wurde geändert in NULL_LITERAL ::= 'Null'
-- - Noobody 1.01:
--   - HEX_LITERAL ::= '$' ('0'..'9' | 'A'..'B' | 'a'..'b')+
--     wurde geändert in '$' ('0'..'9' | 'A'..'F' | 'a'..'f')+
--   - SingleLineIfStatement das ('End If' | 'EndIf')
--     wurde geändert in ('End If' | 'EndIf')?

-- Parser
Main ::= (MainSegment)*

Block ::= (BlockSegment)*

MainSegment ::= BlockSegment
   | DataDirective
   | ConstantsDeclaration
   | GlobalArraysDeclaration
   | TypeDeclaration
   | FunctionDelcaration


BlockSegment ::= IncludeDirective
   | GlobalvariablesDeclaration
   | LocalVariablesDeclaration
   | LabelDeclaration
   | Statement

Statement ::= RestoreStatement
   | ReadStatement
   | GotoStatement
   | GosubStatement
   | IfStatement
   | SelectStatement
   | ReturnStatement
   | ExitStatement
   | WhileStatement
   | RepeatStatement
   | ForStatement
   | ForEachStatement
   | AssignmentStatement
   | CallStatement
   | InsertStatement
   | DeleteStatement
   | DeleteEachStatement

-- Direktiven
IncludeDirective ::= 'Include' STRING_LITERAL

DataDirective ::= 'Data' Expression (',' Expression)*

-- Konstanten
ConstantsDeclaration ::= 'Const' ConstantDeclaration (',' ConstantDeclaration)*

ConstantDeclaration ::= SIMPLE_TYPED_IDENTIFIER '=' Expression

-- Variablen und Arrays
GlobalvariablesDeclaration ::= 'Global' VariableDeclaration (',' VariableDeclaration)*

LocalVariablesDeclaration ::= 'Local' VariableDeclaration (',' VariableDeclaration)*

VariableDeclaration ::= LocalArrayDeclaration
   | TYPED_IDENTIFIER '=' Expression

LocalArrayDeclaration ::= IDENTIFIER '[' Expression ']'

GlobalArraysDeclaration ::= 'Dim' GlobalArrayDeclaration (',' GlobalArrayDeclaration)*

GlobalArrayDeclaration  ::= TYPED_IDENTIFIER '(' Expression (',' Expression)* ')'

-- Blitz-Bezeichner
BlitzIdentifier ::= BlitzIdentifierSegment ('\' BlitzIdentifierSegment)*

BlitzIdentifierSegment ::= TYPED_IDENTIFIER (GlobalArrayAccess | LocalArrayAccess)?

GlobalArrayAccess ::= '(' Expression (',' Expression)* ')'

LocalArrayAccess ::= '[' Expression ']'

-- Sprungmarke
LabelDeclaration ::= '.' IDENTIFIER

-- Type
TypeDeclaration ::= 'Type' IDENTIFIER (FieldDeclaration)* 'End Type'

FieldDeclaration ::= 'Field' TYPED_IDENTIFIER

-- Funktion
FunctionDelcaration ::= 'Function' TYPED_IDENTIFIER '(' (Parameter (',' Parameter)*)? ')'
   (Statement)*
   'End Function'

Parameter ::= SIMPLE_TYPED_IDENTIFIER ('=' Expression)?
   | TYPED_IDENTIFIER

-- Data
RestoreStatement ::= 'Restore' (IDENTIFIER)?

ReadStatement ::= 'Read' BlitzIdentifier

-- Goto- und Gosub-Anweisungen
GotoStatement ::= 'Goto' IDENTIFIER

GosubStatement ::= 'Gosub' IDENTIFIER

-- Bedingte Anweisung
IfStatement ::= BlockIfStatement
   | SingleLineIfStatement

BlockIfStatement ::= 'If' Expression ('Then')? NEW_LINE
   (ElseIfBlock)*
   (ElseBlock)?
   ('End If' | 'EndIf')

SingleLineIfStatement ::= 'If' Expression ('Then')?
   (ElseIfBlock)*
   (ElseBlock)?
   ('End If' | 'EndIf')?

ElseIfBlock ::= ('ElseIf' | 'Else If') Expression ('Then')? Block

ElseBlock ::= ('Else') Block

-- Mehrseitige Auswahl
SelectStatement ::= 'Select' Expression
   (CaseBlock)*
   (DefaultBlock)?
   'End Select'

CaseBlock ::= 'Case' Expression (',' Expression)* Block

DefaultBlock ::= 'Default' Block

-- Return-Anweisung
ReturnStatement ::= 'Return' (Expression)?

-- Funktionsaufruf
CallStatement ::= IDENTIFIER ('(' (Expression (',' Expression)*)? ')')?

-- Schleifen
ExitStatement ::= 'Exit'

WhileStatement ::= 'While' Expression Block 'Wend'

RepeatStatement ::= 'Repeat' Block 'Until' Expression

ForStatement ::= 'For' AssignmentStatement 'To' Expression (StepExpression)? Block 'Next'

StepExpression ::= 'Step' Expression

ForEachStatement ::= 'For' BlitzIdentifier '=' 'Each' IDENTIFIER Block 'Next'

-- Zuweisung
AssignmentStatement ::= BlitzIdentifier '=' (Expression | ListExpression)

-- Listenbefehle
InsertStatement ::= 'Insert' (BlitzIdentifier | '(' BlitzIdentifier ')') (BeforeExpression | AfterExpression)

DeleteStatement ::= 'Delete' ListExpression

DeleteEachStatement ::= 'Delete' 'Each' IDENTIFIER

-- Listenausdruck
ListExpression ::= BlitzIdentifier
   | BeforeExpression
   | AfterExpression
   | FirstExpression
   | LastExpression

BeforeExpression ::= 'Before' (ListExpression | '(' ListExpression ')')

AfterExpression ::= 'After' (ListExpression | '(' ListExpression ')')

FirstExpression ::= 'First' IDENTIFIER

LastExpression ::= 'Last' IDENTIFIER

-- Ausdruck
Expression ::= ('Not')? BitExpression

BitExpression ::= RelationExpression (('And' | 'Or' | 'Xor') RelationExpression)*

RelationExpression ::= AddExpression (('=' | '<>' | '><' | '<' | '<=' | '=<' | '>' | '>=' | '=>') AddExpression)*

AddExpression ::= ShiftExpression (('+' | '-') ShiftExpression)*

ShiftExpression ::= Term (('Shl' | 'Shr' |'Sar') Term)*

Term ::= Power (('*' | '/' | 'Mod') Power)*

Power ::= Unary ('^' Unary)*

Unary ::= ('~')? Factor ('~' Factor)*

Factor ::= INTEGER_LITERAL
   | FLOAT_LITERAL
   | STRING_LITERAL
   | NULL_LITERAL
   | '(' Expression ')'
   | TypeInstance
   | TypeCast
   | FunctionCall
   | BlitzIdentifier

TypeInstance ::= 'New' IDENTIFIER

TypeCast ::= 'Int' '(' Expression ')'
   | 'Float' '(' Expression ')'
   | 'Str' '(' Expression ')'

FunctionCall ::= IDENTIFIER '(' (Expression (',' Expression)*)? ')'

-- Lexer
COMMENT ::= ';' (~('\n' | '\r'))* NEW_LINE

IDENTIFIER ::= ('A'..'Z' | 'a'..'z') ('A'..'Z' | 'a'..'z' | '0'..'9' | '_')*

SIMPLE_TYPED_IDENTIFIER ::= IDENTIFIER (SIMPLE_PREFIX)?

TYPED_IDENTIFIER ::= IDENTIFIER (TYPE_PREFIX)?

TYPE_PREFIX ::= SIMPLE_TYPE_PREFIX | '.' IDENTIFIER

SIMPLE_TYPE_PREFIX ::= '%' | '#' | '$'

NULL_LITERAL ::= 'Null'

INTEGER_LITERAL ::= DECIMAL_LITERAL
   | HEX_LITERAL
   | BIN_LITERAL

DECIMAL_LITERAL ::= ('0'..'9')+

HEX_LITERAL ::= '$' ('0'..'9' | 'A'..'F' | 'a'..'f')+

BIN_LITERAL ::= '%' ('0' | '1')+

FLOAT_LITERAL ::= ('0'..'9')* '.' ('0'..'9')+

STRING_LITERAL ::= ('\"') (~('\"' | '\n' | '\r'))* ('\"')

NEW_LINE ::= '\n' | '\r' ('\n')?

WHITESPACE ::= '\t'..'\n' | ' ' | ' : '


Sie wurden aus meiner Erfahrung mit BB erstellt und teilweise mit dem BB-Compiler immer wieder überprüft. Mein Anliegen wäre es, dass ihr nach Beispielen sucht, wo diese Syntax versagt. Das heißt der BB-Compiler akzeptiert die Eingabe/den Quelltext und die hier angegebene Syntax nicht.

Hinweis zu WHITESPACE: Whitespaces sind hier Chr$(9) .. Chr$(13) das Leerzeichen und der Doppelpunkt.
Was ist eurer Meinung nach die Aufgabe des Doppelpunkts? Doppelpunkt=New Line oder Trenner von Anweisungen? Akuell würde die Syntax folgendes Wort nicht akzeptieren: "If True Then Print 123:Else Print 456" der BB-Compiler schon. Definiere ich allerdings WHITESPACE ::= '\t'..'\n' | ' ' | " : " so, dann würde auch "Print(:123:Smile" akzeptiert werden, was der BB-Compiler nicht akzeptiert.

Ein Beispiel zum Anwenden der Syntax:
BlitzBasic: [AUSKLAPPEN]
Type TPerson
Field Name$
End Type

Local Person.TPerson = New TPerson
Person\Name$ = "Max"

For P.TPerson = Each TPerson
Print P\Name$
Next
WaitKey


Das Beispiel würde folgenden Parse-Tree erzeugen:
Code: [AUSKLAPPEN]
Main {
  // Type TPerson .. End Type
  MainSegment->TypeDeclaration {
    'Type' IDENTIFIER := 'TPerson'
    // Field Name$
    FieldDelcaration {
      'Field' TYPED_IDENTFIER := 'Name$'
    }
    'End Type'
  }

  // Local Person.TPerson = New TPerson
  MainSegment->BlockSegment->LocalVariablesDeclaration {
    'Local'
    VariableDeclaration {
      TYPED_IDENTIFIER := 'Person.TPerson' '='
      Expression->BitExpression->RelationExpression->AddExpression
        ->ShiftExpression->Term->Power->Unary->Factor->TypeInstance {
        'New' IDENTIFIER := 'TPerson'
      }
    }
  }

  // Person\Name$ = "Max"
  MainSegment->BlockSegment->Statement->AssignmentStatement {
    BlitzIdentifier {
      BlitzIdentifierSegment {
        TYPED_IDENTIFIER := 'Person'
      }
      '\'
      BlitzIdentifierSegment {
        TYPED_IDENTIFIER := 'Name$'
      }
    }
    '='
    Expression->BitExpression->RelationExpression->AddExpression
      ->ShiftExpression->Term->Power->Unary->Factor {
      STRING_LITERAL = '"Max"'
    }
  }

  // For P = Each TPerson .. Next
  MainSegment->BlockSegment->Statement->ForEachStatement {
    BlitzIdentifier {
      TYPED_IDENTIFIER := 'P'
    }
    '=' 'Each' IDENTIFIER := 'TPerson'
    Block {
      // Print P\Name$
      BlockSegement->CallStatement {
        IDENTIFIER := 'Print'
        Expression->BitExpression->RelationExpression->AddExpression
          ->ShiftExpression->Term->Power->Unary->Factor {
          BlitzIdentifier {
            BlitzIdentifierSegment {
              TYPED_IDENTIFIER := 'P'
            }
            '\'
            BlitzIdentifierSegment {
              TYPED_IDENTIFIER := 'Name$'
            }
          }
        }
      }
    }
    'Next'
  }

  // WaitKey
  MainSegment->BlockSegement->CallStatement {
    IDENTIFIER := 'Waitkey'
  }
}


Ciao Olli
  • Zuletzt bearbeitet von Vertex am Do, Jul 22, 2010 10:53, insgesamt 5-mal bearbeitet

Noobody

BeitragMi, Jul 21, 2010 19:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Soweit ich mir erinnere, gehen die Hexziffern von 1-F und nicht von 1-B Wink

Ansonsten fallen mir beim überfliegen hie und da auch noch andere Ungereimtheiten auf (zum Beispiel ist beim einzeiligen If das EndIf optional). Vor allem stellt sich mir aber die Frage, wofür man so etwas braucht - du sagst zwar, dass für die Uni so etwas nützlich wäre, aber BB ist nun wirklich keine Sprache mit schöner Syntax und daher auch nicht wirklich sinnvoll, wenn man sie in theoretischer Informatik betrachtet. Und für Compilerbauer? Ich weiss ja nicht, aber wenn man ein wenig mit BB gearbeitet hat, nützt einem das Gedächtnis fast mehr als ein verwirrendes Stück EBNF (nichts gegen deinen Schreibstil, aber theoretisches Zeug wie die (E)BNF wird bei komplexeren Beispielen als 'ABBABBABBABB' schlichtweg unleserlich).
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Vertex

BeitragMi, Jul 21, 2010 20:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke, habe ich geändert.

Also EBNF (das hier ist EBNF und nicht BNF) ist nicht nur eine Beschreibungssprache für Akademiker, sondern sie wird als Referenz für bekannte Programmiersprachen genutzt. Siehe Java (Kapitel 18 auf Seite 585), C# (Annex A. Grammar, Seite 443) oder Python um nur drei zu nennen.

Heutzutage gibt es gute Tools zum Entwickeln von Sprachen: ANTLR oder Xtext. Mit letzterem erstellt man eine Grammatik in EBNF und Xtext generiert daraus einen vollfunktionsfähigen Eclipse-Editor mit Syntax-Highlighting, Code-Completion, Quick-Assist, Outline-View, Problems-View usw.

Das ist aber hier nicht primär das Ziel des Topics diese Tools zu nutzen, sondern nur eine Syntax-Beschreibung von BB zu erstellen.

Ciao Olli

Edit: Die obige Syntax lässt sich noch nicht ohne weiteres als ANTLR-Grammatik umsetzen, da einige Regeln noch mehrdeutig sind. Aber ich habe mal eine vereinfachte Variante erstellt und den Parse-Tree für ein simples Beispiel generiert:
BlitzBasic: [AUSKLAPPEN]
Dim MyArrayA(10), MyArrayB(10)
.MyLabel

user posted image

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group