Binden binaere Operatoren zu schwach?



  • Gibt vermutlich Gründe, aus denen das Sinn macht. Sei froh dass wir nicht bei Pascal sind, da binden die Dinger so bekloppt, dass man quasi immer Klammern muss 😉
    Sollte man hier so oder so machen, gerade bei den bit-Operatoren weiß ja doch niemand so genau, wie stark/schwach die binden -> Lesbarkeit erfordert schon Klammern.



  • Kellerautomat schrieb:

    Ich bastle gerade an einer eigenen Programmiersprache und habe ueber Operator-Prioritaeten nachgedacht.

    Machs wie in C, das kennen die Leute wenigstens, auch wenn es teilweise keinen Sinn zu machen scheint. BTW, gibts bei dir einen Potenzoperator? Die sind besonders lustig ...



  • Nein, es gibt derzeit keinen Potenzoperator. Die Begruendung "Machs so, wie Leute das kennen" hat fuer mich keinen Wert. Meine Sprache soll dem Benutzer moeglichst viel Tipparbeit und Verkrampfungen auf der Tastatur ersparen. Da ist mir ziemlich egal, was andere Programmierer (inkl. mir) gewohnt sind. 😉

    Z.B. habe ich die bedeutung von &&/& und ||/| vertauscht, weil man die logischen Operatoren viel oefters braucht. Scopes werden anstatt {} durch [] markiert, weil das auf meiner englischen Tastatur kein Shift braucht. Semikolone sind grundsaetzlich unnoetig, \n ist auch ein gueltiger Terminator. if, while und for brauchen keine (). Statt [] verwende ich fuer Arrays @.

    Das mag alles nur nach Kleinigkeiten klingen, aber in Summe betrachtet kommt da schon was zusammen. 😉



  • Ja, eine Sprache mit der keiner arbeiten will kommt da zusammen 🤡 Das ist wie ein von QWERTY abweichendes Tastaturlayout. Vielleicht ergonomischer, aber irgendwie sinnlos.

    MfG SideWinder



  • Ach was, so schlimm sieht das gar nicht aus. Herrlich sinnloses Codebeispiel:

    # comment
    
    int@ f = { 2, 4, 6 }
    
    main(string@ args) => void
    [
    	foo f = new foo
    	f.qux f.baz
    ]
    
    type foo
    [
    	alias bar = foo
    
    	baz() => int
    	[
    		<-- ::f
    		return 0
    	]
    
    	qux(int x) => void
    	[
    		if x % 42 == 0
    			<-- true
    
    		for int i = 0; i < 2; ++i
    			<-- i
    
    		if .b
    		[
    			<-- x
    			--> .b ? .i : x
    			.b = x -> bool
    		]
    
    		else <-- "huehuehue"
    	]
    
    	bool b, c
    	int i
    ]
    


  • Ich geh mal davon aus, du machst das nur als Lexer/Parser-Übung 😋
    Ansonsten sieht deine Sprache nämlich genau wie jede andere C-basierte Sprache aus, dürfte keine zusätzlichen interessanten Features haben und verwendet zur allgemeinen Verwirrung andere Symbole als gewohnt 🙄

    Also bitte nicht produktiv einsetzen *g*

    BTW: "=> void" spart jetzt aber nicht gerade Schreibarbeit.

    MfG SideWinder



  • Kellerautomat schrieb:

    Kommt das nur mir falsch vor?

    Nope. Das sollte jedem komisch vorkommen 😉

    Der Grund warum es so ist wie es ist, ist folgender:

    In C gabs ursprünglich && und || garnicht - da hat man & und | verwendet. Deshalb musste ein if(a<b | b<c) korrekt funktionieren. Etwas später kamen dann aber && und || dazu, um short circuit zu erlauben. Aus Kompatibilitätsgründen hat man aber die Precedence von | und & nicht mehr angefasst.



  • SideWinder schrieb:

    Ich geh mal davon aus, du machst das nur als Lexer/Parser-Übung 😋

    Jop. Allerdings habe ich auch vor, das ganze lauffaehig zu bekommen. Der Lexer ist beretis fertig. Ich verpasse nur gerade der Grammatik den letzten Schliff, danach kommt der Parser. 🤡

    SideWinder schrieb:

    Ansonsten sieht deine Sprache nämlich genau wie jede andere C-basierte Sprache aus

    Die Aehnlichkeit ist durchaus vorhanden, ja. Aber warum auch nicht, hat sich schliesslich bewaehrt.

    SideWinder schrieb:

    dürfte keine zusätzlichen interessanten Features haben

    Dem muss ich widersprechen. Mag sein, dass ich damit keine grossen Innovationen bringen, oder gar neue Programmierparadigmen. Aber ich versuche Dinge, die mir in C++ besonders auf den Keks gehen, loszuwerden. Eins davon ist das staendige kennzeichnen von globalen Variablen und Membern. Auf globals greift man bei mir mit :: zu, auf Member mit . 🤡

    SideWinder schrieb:

    und verwendet zur allgemeinen Verwirrung andere Symbole als gewohnt 🙄

    Ich wuerde sagen, das ist Gewoehnungssache. 😉

    SideWinder schrieb:

    BTW: "=> void" spart jetzt aber nicht gerade Schreibarbeit.

    Ich nenne es "trailing return types done right". 😃



  • Ah, als Übung natürlich sehr interessant. Wie hast du Lexer/Parser geschrieben? Verwendest du flex/bison oder baust du alles von Hand?

    Übersetzerbau war eine meiner Lieblings-LVAs im Bachelorstudium. Allerdings mussten wir die attributierte Grammatik mit "ox", einem undokumentierten Uralt-Tool erledigen, pfui.

    Lustigster Teil bleibt dann aber imho die Code-Optimierung, auch wenn man da gnadenlos jedem anderen Compiler unterlegen ist und man besser nur ein Language-Frontend für gcc bastelt.

    MfG SideWinder



  • Kellerautomat schrieb:

    Ich wuerde sagen, das ist Gewoehnungssache. 😉

    Warum verwendet man denn andere Zeichen für Dinge, die man von überall her kennt und nichtmal eine andere Bedeutung haben?



  • Cyres schrieb:

    Kellerautomat schrieb:

    Ich wuerde sagen, das ist Gewoehnungssache. 😉

    Warum verwendet man denn andere Zeichen für Dinge, die man von überall her kennt und nichtmal eine andere Bedeutung haben?

    Hat er doch schon weiter oben beantwortet.

    MfG SideWinder



  • Alles von Hand gebaut mit der C++-Standardlib only. 🙂



  • SideWinder schrieb:

    Lustigster Teil bleibt dann aber imho die Code-Optimierung, auch wenn man da gnadenlos jedem anderen Compiler unterlegen ist und man besser nur ein Language-Frontend für gcc bastelt.

    Wenn das so nah an C++ ist, wie das hier klingt, kann er auch "einfach" nach C++ übersetzen. Je nachdem, wie nah seine Sprache ist, geht das relativ einfach.

    mir ist allerdings nicht klar, was die "-->" und "<--" machen sollen.



  • otze schrieb:

    mir ist allerdings nicht klar, was die "-->" und "<--" machen sollen.

    Eingabe und Ausgabe 🤡



  • Shade Of Mine schrieb:

    In C gabs ursprünglich && und || garnicht - da hat man & und | verwendet.

    Quelle dafür:
    http://www.lysator.liu.se/c/dmr-on-or.html



  • Falls es jemanden interessiert: Ich habe gerade die Grammatik fertiggestellt. Zur Info: a % b bedeutet "beliebig viele Vorkommen von a, getrennt durch b".

    module                    =  definition*
    
    definition                = type-definition | function-definition | variable-definition | alias-definition | terminator
    type-definition           = 'type' identifier '[' (function-definition | variable-definition | alias-definition | terminator)* ']'
    function-definition       = identifier [':' parameter % ','] '=>' type compound-statement
    variable-definition       = type identifier '=' expression terminator
    alias-definition          = 'alias' identifier = type terminator
    
    identifier                =  {a-zA-Z_}{a-zA-Z_0-9} && !built-in-type
    parameter                 =  type identifier
    type                      =  type-name [type-modifier]
    type-name                 =  built-in-type | identifier ['.' identifier]
    built-in-type             =  void | bool | char | int | float
    type-modifier             = '@'
    
    terminator                = '\n' | ';'
    
    statement                 = selection-statement | iteration-statement | jump-statement | io-statement | definition-statement | expression-statement | compound-statement
    selection-statement       = if-statement
    if-statement              = 'if' expression terminator statement ['else' statement]
    iteration-statement       = for-statement | while-statement
    for-statement             = 'for' variable-definition | terminator expression-statement [expression] terminator statement
    while-statement           = 'while' expression terminator statement
    expression-statement      = [expression] terminator
    jump-statement            = break-statement | continue-statement | return-statement
    break-statement           = 'break' terminator
    continue-statement        = 'continue' terminator
    return-statement          = 'return' expression terminator
    io-statement              = input-statement | output-statement
    input-statement           = '-->' expression terminator
    output-statement          = '<--' expression terminator
    definition-statement      = variable-definition | alias-definition
    compound-statement        = '[' statement* ']'
    
    expression                = comma-expression          ['$' expression]
    comma-expression          = assignment-expression     [',' expression]
    assignment-expression     = cast-expression           [assignment-operator assignment-expression]
    cast-expression           = conditional-expression    ['->' type]
    conditional-expression    = logical-or-expression     ['?' expression ':' assignment-expression]
    logical-or-expression     = logical-xor-expression    ['|' logical-or-expression]
    logical-xor-expression    = logical-and-expression    ['^' logical-xor-expression]
    logical-and-expression    = equality-expression       ['&' logical-and-expression]
    equality-expression       = relational-expression     ['==' | '!=' equality-expression]
    relational-expression     = bitwise-or-expression     ['<' | '>' | '<=' | '>=' relational-expression]
    bitwise-or-expression     = bitwise-xor-expression    ['||' bitwise-or-expression]
    bitwise-xor-expression    = bitwise-and-expression    ['^^' bitwise-xor-expression]
    bitwise-and-expression    = shift-expression          ['&&' bitwise-and-expression]
    shift-expression          = additive-expression       ['<<' | '>>' shift-expression]
    additive-expression       = multiplicative-expression ['+' | '-' additive-expression]
    multiplicative-expression = infix-function-call       ['*' | '/' | '%' multiplicative-expression]
    infix-function-call       = prefix-expression         [':' accessor ':' prefix-expression]
    prefix-expression         = prefix-operator*          postfix-expression
    postfix-expression        = primary-expression        [postfix-operator-sequence]
    primary-expression        = '(' expression ')' | literal | accessor | 'this' | function-call | new-expression
    function-call             = accessor primary-expression*
    new-expression            = 'new' type
    
    accessor                  = global-accessor | member-accessor | object-accessor
    global-accessor           = '::' object-accessor
    member-accessor           = '.' object-accessor
    object-accessor           = identifier [member-accessor]
    
    prefix-operator           = '+' | '-' | '++' | '--' | '!' | '~'
    postfix-operator-sequence = ['@' primary-expression] postfix-operator*
    postfix-operator          = '++' | '--'
    assignment-operator       = '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '|=' | '^=' | '&&=' | '||=' | '^^='
    
    literal                   = bool-literal | int-literal | float-literal | char-literal | string-literal | array-literal
    bool-literal              = 'true' | 'false'
    int-literal               = digit+
    float-literal             = digit+ '.' digit+
    char-literal              = '\'' character '\''
    string-literal            = '"' character* '"'
    array-literal             = '{' expression % ',' '}'
    

    Ist ganz schoen viel geworden. 😃



  • hast du die Grammatik auf irgendwelche Eigenschaften getuned? also LL(k), LR(k)...



  • Nope. Ich weiss zwar, dass es verschiedene Kategorien von Grammatiken gibt, die verschwieden schwer zu parsen sind, aber so aufs erste fange ich auch mit den Wikipedia-Artikeln darueber wenig an. So genau habe ich mich mit dem Thema nicht auseinandergesetzt. Aber der Parser ist in meinem Kopf schon im Prinzip fertig. 🤡


Anmelden zum Antworten