Преглед на файлове

Merge pull request #3532 from mhilbrunner/vnen-gdscript-grammar

Add GDScript grammar by vnen


Co-authored-by: George Marques <[email protected]>
Max Hilbrunner преди 5 години
родител
ревизия
f92e9e9d14
променени са 3 файла, в които са добавени 155 реда и са изтрити 0 реда
  1. 152 0
      development/file_formats/gdscript_grammar.rst
  2. 1 0
      development/file_formats/index.rst
  3. 2 0
      getting_started/scripting/gdscript/gdscript_basics.rst

+ 152 - 0
development/file_formats/gdscript_grammar.rst

@@ -0,0 +1,152 @@
+.. _doc_gdscript_grammar:
+
+GDScript grammar
+================
+
+This is the formal grammar of GDScript written in `EBNF <https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form>`_,
+for reference purposes.
+
+.. note:: This grammar is descriptive only, derived from the reference
+          documentation and current implementation. The GDScript parser is
+          **not** generated from a grammar definition. Inconsistencies here
+          likely mean an error in this grammar, not a bug in GDScript.
+
+.. code-block:: ebnf
+
+    (* GDScript EBNF grammar.
+       Uppercase words are terminals generated by the tokenizer.
+       INDENT/DEDENT are not generated by the tokenizer yet, but they are added
+       here for reading convenience.
+       Naturally, this only cover syntax. Semantics can't be inferred from this
+       description.
+    *)
+
+    program = [ inheritance NEWLINE ] [ className ] { topLevelDecl } ;
+
+    inheritance = "extends" ( IDENTIFIER | STRING ) { "." IDENTIFIER } ;
+    className = "class_name" IDENTIFIER [ "," STRING ] NEWLINE ;
+
+    topLevelDecl
+        = classVarDecl
+        | constDecl
+        | signalDecl
+        | enumDecl
+        | methodDecl
+        | constructorDecl
+        | innerClass
+        | "tool"
+        ;
+
+    classVarDecl = [ "onready" ] [ export ] "var" IDENTIFIER [ ":" typeHint ]
+        [ "=" expression ] [ setget ] NEWLINE ;
+    setget = "setget" [ IDENTIFIER ] [ "," IDENTIFIER] ;
+    export = "export" [ "(" [ BUILTINTYPE | IDENTIFIER { "," literal } ] ")" ] ;
+    typeHint = BUILTINTYPE | IDENTIFIER ;
+
+    constDecl = "const" IDENTIFIER [ ":" typeHint ] "=" expression NEWLINE ;
+
+    signalDecl = "signal" IDENTIFIER [ signalParList ] NEWLINE ;
+    signalParList = "(" [ IDENTIFIER { "," IDENTIFIER } ] ")" ;
+
+    enumDecl = "enum" [ IDENTIFIER ] "{" [ IDENTIFIER [ "=" INTEGER ]
+        { "," IDENTIFIER [ "=" INTEGER ] } [ "," ] ] "}" NEWLINE ;
+
+    methodDecl = [ rpc ] [ "static" ] "func" IDENTIFIER "(" [ parList ] ")"
+        [ "->" typeHint] ":" stmtOrSuite ;
+    parList = parameter { "," parameter } ;
+    parameter = [ "var" ] IDENTIFIER [ ":" typeHint ] [ "=" expression ] ;
+    rpc = "remote" | "master" | "puppet"
+        | "remotesync" | "mastersync"  | "puppetsync";
+
+    constructorDecl = "func" IDENTIFIER "(" [ parList ] ")"
+        [ "." "(" [ argList ] ")" ] ":" stmtOrSuite ;
+    argList = expression { "," expression } ;
+
+    innerClass = "class" IDENTIFIER [ inheritance ] ":" NEWLINE
+        INDENT [ inheritance NEWLINE ] topLevelDecl { topLevelDecl } DEDENT ;
+
+    stmtOrSuite = stmt | NEWLINE INDENT suite DEDENT ;
+    suite = stmt { stmt };
+
+    stmt
+        = varDeclStmt
+        | ifStmt
+        | forStmt
+        | whileStmt
+        | matchStmt
+        | flowStmt
+        | assignmentStmt
+        | exprStmt
+        | assertStmt
+        | yieldStmt
+        | preloadStmt
+        | "breakpoint" stmtEnd
+        | "pass" stmtEnd
+        ;
+    stmtEnd = NEWLINE | ";" ;
+
+    ifStmt = "if" expression ":" stmtOrSuite { "elif" expression ":" stmtOrSuite }
+        [ "else" ":" stmtOrSuite ] ;
+    whileStmt = "while" expression ":" stmtOrSuite;
+    forStmt = "for" IDENTIFIER "in" expression ":" stmtOrSuite ;
+
+    matchStmt = "match" expression ":" NEWLINE INDENT matchBlock DEDENT;
+    matchBlock = patternList ":" stmtOrSuite { patternList ":" stmtOrSuite };
+    patternList = pattern { "," pattern } ;
+    (* Note: you can't have a binding in a pattern list, but to not complicate the
+    grammar more it won't be restricted syntactically *)
+    pattern = literal | BUILTINTYPE | CONSTANT | "_" | bindingPattern
+        | arrayPattern | dictPattern ;
+    bindingPattern = "var" IDENTIFIER ;
+    arrayPattern = "[" [ pattern { "," pattern } [ ".." ] ] "]" ;
+    dictPattern = "{" [ keyValuePattern ] { "," keyValuePattern } [ ".." ] "}" ;
+    keyValuePattern = STRING [ ":" pattern ] ;
+
+    flowStmt
+        = "continue" stmtEnd
+        | "break" stmtEnd
+        | "return" [ expression ] stmtEnd
+        ;
+
+    assignmentStmt = subscription "=" expression stmtEnd;
+    varDeclStmt = "var" IDENTIFIER [ "=" expression ] stmtEnd;
+
+    assertStmt = "assert" "(" expression [ "," STRING ] ")" stmtEnd ;
+    yieldStmt = "yield" "(" [ expression "," expression ] ")" ;
+    preloadStmt = "preload" "(" CONSTANT ")" ;
+
+    (* This expression grammar encodes precedence. Items later in the list have
+    higher precedence than the ones before. *)
+    exprStmt = expression stmtEnd ;
+    expression = cast [ "[" expression "]" ] ;
+    cast = ternaryExpr [ "as" typeHint ];
+    ternaryExpr = logicOr [ "if" logicOr "else" logicOr ] ;
+    logicOr = logicAnd { ( "or" | "||" ) logicAnd } ;
+    logicAnd = logicNot { ( "and" | "&&" ) logicNot };
+    logicNot = ( "!" | "not" ) logicNot | in;
+    in = comparison { "in" comparison };
+    comparison = bitOr { ( "<" | ">" | "<=" | ">=" | "==" | "!=" ) bitOr } ;
+    bitOr = bitXor { "|" bitXor } ;
+    bitXor = bitAnd { "^" bitAnd } ;
+    bitAnd = bitShift { "&" bitShift } ;
+    bitShift = minus { ( "<<" | ">>" ) minus } ;
+    minus = plus { "-" plus } ;
+    plus = factor { "+" factor } ;
+    factor = sign { ( "*" | "/" | "%" ) sign } ;
+    sign = ( "-" | "+" ) sign | bitNot ;
+    bitNot = "~" bitNot | is ;
+    is = call [ "is" ( IDENTIFIER | BUILTINTYPE ) ] ;
+    call = attribute [ "(" [ argList ] ")" ];
+    attribute = subscription { "." IDENTIFIER } ;
+    subscription = primary [ "[" expression "]" ] ;
+    primary = "true" | "false" | "null" | "self" | literal | arrayDecl
+        | dictDecl | "(" expression ")" ;
+
+    literal = STRING | NUMBER | IDENTIFIER | BUILTINTYPE
+        | "PI" | "TAU" | "NAN" | "INF" ;
+    arrayDecl = "[" [ expression { "," expression } "," ] "]" ;
+    dictDecl = "{" [ keyValue { "," keyValue } "," ] "}" ;
+    keyValue
+        = expression ":" expression
+        | IDENTIFIER "=" expression
+        ;

+ 1 - 0
development/file_formats/index.rst

@@ -5,4 +5,5 @@ Godot file formats
    :maxdepth: 1
    :name: toc-devel-file-formats
 
+   gdscript_grammar.rst
    tscn.rst

+ 2 - 0
getting_started/scripting/gdscript/gdscript_basics.rst

@@ -271,6 +271,8 @@ The following is the list of supported operators and their precedence.
 +---------------------------------------------------------------+-----------------------------------------+
 | ``if x else``                                                 | Ternary if/else                         |
 +---------------------------------------------------------------+-----------------------------------------+
+| ``as``                                                        | Type casting                            |
++---------------------------------------------------------------+-----------------------------------------+
 | ``=`` ``+=`` ``-=`` ``*=`` ``/=`` ``%=`` ``&=`` ``|=``        | Assignment (lowest priority)            |
 +---------------------------------------------------------------+-----------------------------------------+