Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge in renpy grammar specification branch #413

Merged
merged 7 commits into from
Jul 11, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update grammars
  • Loading branch information
duckdoom4 committed Jul 11, 2024
commit 3aef821c94849b8f01baf2078c5e6a90b9c5ba22
12 changes: 12 additions & 0 deletions grammars/python.grammar.bnf → grammars/python.grammar.ebnf
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
PYTHON_CONTROL_FLOW_KEYWORD = "if" | "else" | "elif" | "while" | "for"
|"return" | "continue" | "yield" | "break" | "pass"
| "try" | "finally";

PYTHON_KEYWORD = "True" | "False" | "None"
| PYTHON_CONTROL_FLOW_KEYWORD
| "raise" | "except"
| "as" | "with" | "from" | "in" | "is"
| "and" | "not" | "or" | "del"
| "global" | "nonlocal" | "async" | "await"
| "def" | "class" | "lambda" | "import" | "assert";

# PEG grammar for Python


File renamed without changes.
235 changes: 129 additions & 106 deletions grammars/renpy.grammar.bnf → grammars/renpy.grammar.ebnf
Original file line number Diff line number Diff line change
@@ -1,25 +1,141 @@
NEWLINE = "\n";
LETTER = "A" | ... | "Z" | "a" | ... | "z" | ? any Unicode letter in the range U+00A0 to U+FFFD ?;
KEYWORD = "as" | "at" | "behind" | "call" | "expression" | "hide" | "if" | "in" | "image" | "init" | "jump" | "menu" | "onlayer" | "python" | "return" | "scene" | "show" | "with" | "while" | "zorder";
CHARACTER = /./;
(* Recommended extension for EBNF syntax highlighting: https://marketplace.visualstudio.com/items?itemName=omkov.vscode-ebnf *)

(*===Common Expressions===*)
(*
POSIX character classes defined using unicode categories
For POSIX see: https://www.regular-expressions.info/posixbrackets.html
For unicode categories see: https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt
For category breakdown see: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
*)
UPPER = "\p{Uppercase_Letter}";
LOWER = "\p{Lowercase_Letter}";
ALPHA = "\p{Letter}" | "\p{Letter_Number}";
LETTER = "\p{Letter}";
DIGIT = "\p{Digit}";
HEX_DIGIT = "\p{Hex_Digit}";
ALNUM = ALPHA | DIGIT;
WORD_CHAR = ALNUM | "\p{Connector_Punctuation}";
NEWLINE = "\n" | "\r";
CHARACTER = "\p{Any}";

IDENTIFIER = "\p{XID_Start}", { "\p{XID_Continue}" }; (* Based on Python specification. See: https://docs.python.org/3/reference/lexical_analysis.html#identifiers *)
RENPY_KEYWORD = "as" | "at" | "behind" | "call" | "expression" | "hide" | "if" | "in" | "image" | "init" | "jump" | "menu" | "onlayer" | "python" | "return" | "scene" | "show" | "with" | "while" | "zorder";
OPERATOR = "<>" | "<<" | "<=" | "<" | ">>" | ">=" | ">" | "!=" | "==" | "|" | "^" | "&" | "+" | "-" | "**" | "*" | "//" | "/" | "%" | "~";

DIGIT = "0" | "1" | ... | "9";
HEX_DIGIT = DIGIT | "A" | ... | "F" | "a" | ... | "f";
(*===Renpy Expressions===*)
AS_EXPRESSION = "as", NAME;
AT_EXPRESSION = "at", SIMPLE_EXPRESSION_LIST;
ONLAYER_EXPRESSION = "onlayer", NAME;
ZORDER_EXPRESSION = "zorder", SIMPLE_EXPRESSION;
BEHIND_EXPRESSION = "behind", NAME, {",", NAME};
IF_EXPRESSION = "if", PYTHON_EXPRESSION;
EXPRESSION_CLAUSE = "expression", SIMPLE_EXPRESSION;
FROM_EXPRESSION = "from", LABEL_NAME;
WITH_EXPRESSION = "with", SIMPLE_EXPRESSION;

(*---Literals---*)
HASH = HEX_DIGIT, { HEX_DIGIT };
INTEGER = [ "+" | "-" ], DIGIT, { DIGIT };
FLOAT = [ "+" | "-" ], ( DIGIT, { DIGIT }, [ ".", { DIGIT } ] | ".", DIGIT, { DIGIT } ), [ ( "e" | "E" ), [ "+" | "-" ], DIGIT, { DIGIT } ];

ALNUM = { LETTER | DIGIT }
(*---Entities---*)
NAME = IDENTIFIER - KEYWORD;

(* image specifier *)
IMAGE_NAME_COMPONENT_NO_DASH = WORD_CHAR - "-", { WORD_CHAR - "-" };
IMAGE_NAME_COMPONENT = WORD_CHAR, { WORD_CHAR };
IMAGE_NAME = IMAGE_NAME_COMPONENT, { IMAGE_NAME_COMPONENT };
IMAGE_NAME_NO_DASH = IMAGE_NAME_COMPONENT_NO_DASH, { IMAGE_NAME_COMPONENT_NO_DASH };

IMAGE_SPECIFIER_CLAUSE = AS_EXPRESSION | AT_EXPRESSION | ONLAYER_EXPRESSION | ZORDER_EXPRESSION | BEHIND_EXPRESSION;
IMAGE_SPECIFIER = [ EXPRESSION_CLAUSE | IMAGE_NAME ], { IMAGE_SPECIFIER_CLAUSE };


(*===Renpy Statements===*)

SUB_BLOCK = ":", NEWLINE, BLOCK;
ATL_SUB_BLOCK = ":", NEWLINE, ATL_BLOCK;

(* if *)
IF_CLAUSE = IF_EXPRESSION, SUB_BLOCK;
ELIF_CLAUSE = "elif", PYTHON_EXPRESSION, SUB_BLOCK;
ELSE_CLAUSE = "else", SUB_BLOCK;
IF_STATEMENT = IF_CLAUSE, { ELIF_CLAUSE }, [ ELSE_CLAUSE ];

(* while *)
WHILE = "while", PYTHON_EXPRESSION, SUB_BLOCK;

(* pass *)
PASS = "pass", NEWLINE;

(* return *)
RETURN = "return", [ PYTHON_EXPRESSION ], NEWLINE;

(* jump *)
JUMP = "jump", ( EXPRESSION_CLAUSE | LABEL_NAME ), NEWLINE;

(* call *)
CALL = "call", ( EXPRESSION_CLAUSE, [ "pass" ] | LABEL_NAME ), [ ARGUMENTS ], [ FROM_EXPRESSION ], NEWLINE;

(* with *)
WITH = WITH_EXPRESSION, NEWLINE;

(* say *)
SAY_WHO = SIMPLE_EXPRESSION;
SAY_WHAT = TRIPLE_STRING | STRING;
SAY_ATTRIBUTES = "-", {IMAGE_NAME_COMPONENT};
SAY_TEMPORARY_ATTRIBUTES = "@", SAY_ATTRIBUTES;
SAY = [SAY_WHO], [SAY_ATTRIBUTES], [SAY_TEMPORARY_ATTRIBUTES], SAY_WHAT;

(* menu *)
MENU = "menu", [ LABEL_NAME ], [ ARGUMENTS ], MENU_BLOCK;

(* menu block *)
MENUITEM_SET = "set", PYTHON_EXPRESSION, NEWLINE;
MENUITEM_CAPTION = SAY;
MENUITEM_CHOICE = STRING, [ ARGUMENTS ], [ IF_EXPRESSION ], SUB_BLOCK;
MENUITEM_BLOCK_STATEMENT = MENUITEM_SET | WITH | MENUITEM_CAPTION | MENUITEM_CHOICE;
MENU_BLOCK = MENUITEM_BLOCK_STATEMENT, { MENUITEM_BLOCK_STATEMENT };

(* scene *)
SCENE = "scene", [ ONLAYER_EXPRESSION ], [ IMAGE_SPECIFIER, [ WITH ] ], (ATL_SUB_BLOCK | NEWLINE);

(* show *)
SHOW = "show", IMAGE_SPECIFIER, [ WITH ], (ATL_SUB_BLOCK | NEWLINE);
SHOW_LAYER = "show", "layer", NAME, [ AT_EXPRESSION ], (ATL_SUB_BLOCK | NEWLINE);

(* hide *)
HIDE = "hide", IMAGE_SPECIFIER, [ WITH ], NEWLINE;

(* camera *)
CAMERA = "camera", [ NAME | "master" ], [ AT_EXPRESSION ], (ATL_SUB_BLOCK | NEWLINE);

(* image *)
IMAGE = "image", IMAGE_NAME_NO_DASH, (ATL_SUB_BLOCK | "=", PYTHON_EXPRESSION, NEWLINE);












(* GENERATED *)




UNICODE_ESCAPE = "u", HEX_DIGIT, HEX_DIGIT, HEX_DIGIT, HEX_DIGIT;
ESCAPE_SEQUENCE = "\\", ( CHARACTER | UNICODE_ESCAPE );
WORD = ( LETTER | "_" ), ( ALNUM | "_" );
NAME = WORD - KEYWORD;


DOTTED_NAME = NAME, { ".", NAME };
LABEL_NAME = NAME | ( ".", NAME );
IMAGE_NAME_COMPONENT_NO_DASH = ( ALNUM | "_" ), { ALNUM | "_" };
IMAGE_NAME_COMPONENT = ( ALNUM | "-" | "_" ), { ALNUM | "-" | "_" };
LABEL_NAME = ["."], NAME, [ ".", NAME ];


STRING = [ "r" ], ( SINGLE_QUOTED_STRING | DOUBLE_QUOTED_STRING );
SINGLE_QUOTED_STRING = "'", { CHARACTER - "'" | ESCAPE_SEQUENCE }, "'";
@@ -123,97 +239,4 @@ STATEMENT = JUMP | CALL | RETURN | SHOW | HIDE | SCENE | WITH | MENU_ITEM | CAPT

BLOCK = STATEMENT, { STATEMENT };

PROGRAM = BLOCK;






# Renpy Expressions
# Literals

# image specifier
IMAGE_NAME = IMAGE_NAME_COMPONENT, { IMAGE_NAME_COMPONENT };
IMAGE_NAME_NO_DASH = IMAGE_NAME_COMPONENT_NO_DASH, { IMAGE_NAME_COMPONENT_NO_DASH };

AS_EXPRESSION = "as", NAME;
AT_EXPRESSION = "at", SIMPLE_EXPRESSION_LIST;
ONLAYER_EXPRESSION = "onlayer", NAME;
ZORDER_EXPRESSION = "zorder", SIMPLE_EXPRESSION;
BEHIND_EXPRESSION = "behind", NAME, {",", NAME};
IMAGE_SPECIFIER_CLAUSE = AS_EXPRESSION | AT_EXPRESSION | ONLAYER_EXPRESSION | ZORDER_EXPRESSION | BEHIND_EXPRESSION
IMAGE_SPECIFIER = [EXPRESSION | IMAGE_NAME], { IMAGE_SPECIFIER_CLAUSE };


# Renpy Statements

SUB_BLOCK = ":", NEWLINE, BLOCK;
ATL_SUB_BLOCK = ":", NEWLINE, ATL_BLOCK;

# if
IF_EXPRESSION = "if", PYTHON_EXPRESSION;
IF_CLAUSE = IF_EXPRESSION, SUB_BLOCK;
ELIF_CLAUSE = "elif", PYTHON_EXPRESSION, SUB_BLOCK;
ELSE_CLAUSE = "else", SUB_BLOCK;
IF_STATEMENT = IF_CLAUSE, { ELIF_CLAUSE }, [ ELSE_CLAUSE ];

# while
WHILE = "while", PYTHON_EXPRESSION, SUB_BLOCK;

# pass
PASS = "pass", NEWLINE;

# return
RETURN = "return", [ PYTHON_EXPRESSION ], NEWLINE;

# jump
JUMP = "jump", ( EXPRESSION_CLAUSE | LABEL_NAME ), NEWLINE;

# call
CALL = "call", ( EXPRESSION_CLAUSE, [ "pass" ] | LABEL_NAME ), [ ARGUMENTS ], [ FROM_EXPRESSION ], NEWLINE;

# from
FROM_EXPRESSION = "from", LABEL_NAME;

# with
WITH_EXPRESSION = "with", SIMPLE_EXPRESSION;
WITH = WITH_EXPRESSION, NEWLINE;

# expression
EXPRESSION_CLAUSE = "expression", SIMPLE_EXPRESSION

# say
SAY_WHO = SIMPLE_EXPRESSION;
SAY_WHAT = TRIPLE_STRING | STRING;
SAY_ATTRIBUTES = "-", {IMAGE_NAME_COMPONENT};
SAY_TEMPORARY_ATTRIBUTES = "@", ATTRIBUTES;
SAY = [SAY_WHO], [SAY_ATTRIBUTES], [SAY_TEMPORARY_ATTRIBUTES], SAY_WHAT;

# menu
MENU = "menu", [ LABEL_NAME ], [ ARGUMENTS ], MENU_BLOCK;

# menu block
MENUITEM_SET = "set", PYTHON_EXPRESSION, NEWLINE;
MENUITEM_CAPTION = SAY;
MENUITEM_CHOICE = STRING, [ ARGUMENTS ], [ IF_EXPRESSION ], SUB_BLOCK;
MENUITEM_BLOCK_STATEMENT = MENUITEM_SET | WITH | MENUITEM_CAPTION | MENUITEM_CHOICE;
MENU_BLOCK = MENUITEM_BLOCK_STATEMENT, { MENUITEM_BLOCK_STATEMENT };


# scene
SCENE = "scene", [ ONLAYER_EXPRESSION ], [ IMAGE_SPECIFIER, [ WITH ] ], (ATL_SUB_BLOCK | NEWLINE);

# show
SHOW = "show", IMAGE_SPECIFIER, [ WITH ], (ATL_SUB_BLOCK | NEWLINE);
SHOW_LAYER = "show", "layer", NAME, [ AT_EXPRESSION ], (ATL_SUB_BLOCK | NEWLINE);

# hide
HIDE = "hide", IMAGE_SPECIFIER, [ WITH ], NEWLINE;

# camera
CAMERA = "camera", [ NAME | "master" ], [ AT_EXPRESSION ], (ATL_SUB_BLOCK | NEWLINE);

# image
IMAGE = "image", IMAGE_NAME_NO_DASH, (ATL_SUB_BLOCK | "=", PYTHON_EXPRESSION, NEWLINE);

PROGRAM = BLOCK;
File renamed without changes.