siy / CafeBabe

Attempt to design ideal language for me
MIT License
3 stars 0 forks source link

Grammar railroad diagram #1

Open mingodad opened 2 years ago

mingodad commented 2 years ago

After a small temp change in InterpolatedStringLiteral from CafeBabe.peg and using peg from https://github.com/mingodad/peg that has an extension to output an EBNF understood by https://www.bottlecaps.de/rr/ui (that still needed some small manual fixes) we can have a nice railroad diagram (https://en.wikipedia.org/wiki/Syntax_diagram) for documenting/understand the grammar.

Copy and paste the EBNF shown bellow at https://www.bottlecaps.de/rr/ui on the tab Edit Grammar then click on the tab View Diagram.

Program ::= ( Use* Constant* Type* Extension* Function* Unsafe* Test* eof )
Use ::= ( 'use' QualifiedName ImportList? Semicolon )
Constant ::= ( Public? 'const' ( 'val' | TypeName ) Name '=' Expression Semicolon )
Type ::= ( AnnotationRef* Public? 'type' TypeName '=' TypeDecl )
Extension ::= ( Public? 'extend' TypeName ApiRefs? ClassBlock )
Function ::= ( AnnotationRef* Public? Method )
Unsafe ::= ( 'unsafe' BlockStart Constant* Type* Extension* Function* Test* BlockEnd )
Test ::= ( 'test' BlockStart Constant* Type* Extension* Function* Unsafe* BlockEnd )
eof ::= _NOT_  .
QualifiedName ::= ( _NOT_  'F"' [_$@a-zA-Z] [_$.a-zA-Z0-9]* )
ImportList ::= ( BlockStart NameWithAlias ( Comma NameWithAlias )* BlockEnd )
Semicolon ::= ';'
Public ::= 'pub'
TypeName ::= ( Name TypeArguments? BitAnd? ArrayDecl* )
Name ::= ( _NOT_  'F"' [_$@a-zA-Z] [_$a-zA-Z0-9]* )
Expression ::= ( IfExpression | SelectExpression | MatchExpression | TernaryExpression | Expr )
AnnotationRef ::= ( '@' Name ( LP ExpressionList? RP )? )
TypeDecl ::= ( ApiDecl | AnnotationDecl | TypeAliasDecl | CompoundTypeDecl | TupleDecl | ClassDecl )
ApiRefs ::= ( Colon TypeNameList )
ClassBlock ::= ( BlockStart Constant* Constructor* Destructor? ( StaticMethodImpl | Function | MethodImpl )* NamedClassDecl* BlockEnd )
Method ::= ( MethodSignature MethodBody )
BlockStart ::= '{'
BlockEnd ::= '}'
ApiDecl ::= ( 'api' CommonApiBody )
AnnotationDecl ::= ( 'annotation' TypedArgDecl AnnotationBody )
TypeAliasDecl ::= ( ArgumentType Semicolon )
CompoundTypeDecl ::= ( ( AndType | OrType )? ( Semicolon | CommonApiDecl ) )
TupleDecl ::= ( LP TypeName? ( Comma TypeName )* OptionalEllipsis? RP Semicolon )
ClassDecl ::= ( 'class' ClassDataDecl? ApiRefs? ( ClassBlock | Semicolon ) )
NameWithAlias ::= ( Name ( 'as' Name )? )
Comma ::= ','
LP ::= '('
ExpressionList ::= ( Expression ( Comma Expression )* )
RP ::= ')'
OptionalEllipsis ::= ( Comma Ellipsis )
CommonApiBody ::= ( BlockStart Constant* ( ( MethodSignature Semicolon ) | StaticMethodImpl | DefaultMethodImpl )* NamedClassDecl* BlockEnd )
ArgumentType ::= ( UnitDecl | ArrowDecl )
TypedArgDecl ::= ( LP TypedArgList? RP )
AnnotationBody ::= ( BlockStart Statement* BlockEnd )
Statement ::= ( BlockStatement | ( ExpressionStatement Semicolon ) )
AndType ::= ( TypeName ( Comma TypeName )+ )
OrType ::= ( TypeName ( BitOr TypeName )+ )
CommonApiDecl ::= ( ApiRefs? CommonApiBody )
BitOr ::= '|'
Ellipsis ::= '...'
Colon ::= ':'
TypeNameList ::= ( TypeName ( Comma TypeName )* )
MethodSignature ::= ( TypeVarsDecl? ( UnTypedFunction | TypedFunction ) )
StaticMethodImpl ::= ( Public? 'static' Method )
DefaultMethodImpl ::= ( 'default' Method )
NamedClassDecl ::= ( Public? 'class' TypeName ClassBody )
TypeVarsDecl ::= ( '<' LimitedTypeName ( Comma LimitedTypeName )* '>' )
UnTypedFunction ::= ( 'fn' Name OptionalNameList )
TypedFunction ::= ( TypeName Name TypedArgDecl )
OptionalNameList ::= ( LP NameList? RP )
NameList ::= ( Name ( Comma Name )* )
ClassDataDecl ::= ( LP ClassFields? RP )
ClassBody ::= ( TypedArgDecl? ApiRefs? ClassBlock )
TypedArgList ::= ( TypedArgument ( Comma TypedArgument )* OptionalEllipsis? )
ClassFields ::= ( ClassField ( Comma ClassField )* OptionalEllipsis? )
ClassField ::= ( Mutable? TypedArgument )
Mutable ::= 'var'
TypedArgument ::= ( ArgumentType Name )
Constructor ::= ( Public? Name TypedArgDecl MethodBody )
Destructor ::= ( Public? '~' Name LP RP MethodBody )
MethodImpl ::= ( 'impl' Name OptionalNameList MethodBody )
MethodBody ::= ( MethodExpression | MethodBlockBody )
MethodExpression ::= ( '=' Expression Semicolon )
MethodBlockBody ::= ( BlockStart Statement* BlockEnd )
BlockStatement ::= ( ForStatement | IfExpression | SelectExpression | MatchExpression | MethodBlockBody )
ExpressionStatement ::= ( FlowControlStatement | VariableDeclaration | Assignment | IterableStatement | ValueStatement )
ForStatement ::= ( 'for' ForSetup MethodBlockBody )
IfExpression ::= ( 'if' BooleanExpression MethodBlockBody ( 'else' MethodBlockBody )? )
SelectExpression ::= ( 'select' NestedExpr SelectBody )
MatchExpression ::= ( 'match' NestedExpr MatchBody )
FlowControlStatement ::= ( ReturnExpr | Break | Continue )
VariableDeclaration ::= ( VarTitle Assignment )
Assignment ::= AssignmentExpr
IterableStatement ::= ( Iterable Invoke* )
ValueStatement ::= Value
ReturnExpr ::= ( Return Expression? )
Break ::= 'break'
Continue ::= 'continue'
Return ::= 'return'
VarTitle ::= ( 'val' | 'var' | TypeName )
AssignmentExpr ::= ( RegularAssignment | ParallelAssignment )
Value ::= ( ValueConstruction Invoke* PostfixOps? )
Iterable ::= ( Comprehension | OpenRange )
Invoke ::= ( CallParameters | MethodCall | Index )
RegularAssignment ::= ( QualifiedName AssignOps Expression )
ParallelAssignment ::= ( RequiredNameList '=' ( TupleConstruction | Expression ) )
AssignOps ::= ( '+=' | '-=' | '^=' | '|=' | '&=' | '=' )
RequiredNameList ::= ( LP NameList RP )
TupleConstruction ::= ( LP ValueReference? Expression? ( Comma Expression )* OptionalEllipsis? RP )
ValueReference ::= ( QualifiedName Invoke* BitOr )
ForSetup ::= ( LP VarTitle Name Colon Expression RP )
CallParameters ::= ( TypeArguments? ( NamedCallParameters | AnonymousCallParameters ) )
MethodCall ::= ( '.' QualifiedName Invoke? )
Index ::= ( LSqB Expression RSqB )
TypeArguments ::= ( '<' TypeNameList OptionalEllipsis? '>' )
BitAnd ::= '&'
ArrayDecl ::= ( LSqB RSqB )
LSqB ::= '['
RSqB ::= ']'
LimitedTypeName ::= ( Name ( Colon TypeName ( '+' | '-' )? )? )
UnitDecl ::= ( '(' ')' Arrow ( TypeName Arrow )* Ellipsis? TypeName )
ArrowDecl ::= ( TypeName ( Arrow ( TypeName Arrow )* Ellipsis? TypeName )? )
Arrow ::= '->'
TernaryExpression ::= ( NestedExpr '?' Expression Colon Expression )
Expr ::= ( Or ( LogicalOr Or )* )
BooleanExpression ::= ( LP Expression RP )
NestedExpr ::= ( LP Expression RP )
SelectBody ::= ( BlockStart SelectCase* Default? BlockEnd )
SelectCase ::= ( 'case' CaseExpr Arrow Expression Semicolon )
Default ::= ( 'default' Arrow Expression Semicolon )
MatchBody ::= ( BlockStart MatchCase* Default? BlockEnd )
MatchCase ::= ( TypeConstructor Arrow Expression Semicolon )
CaseExpr ::= ( NumLiteral | StringLiteral | ObjConstruction )
TypeConstructor ::= ( TypeName | TypeArguments )
NumLiteral ::= ( ( HexNumLiteral | OctNumLiteral | BinNumLiteral | FloatNumLiteral | DecNumLiteral ) NumSuffix? )
StringLiteral ::= ( InterpolatedStringLiteral | StringSegment+ )
ObjConstruction ::= ( TypeName? ObjConstructionBody )
Or ::= ( And ( LogicalAnd And )* )
LogicalOr ::= '||'
And ::= ( BitwiseOr ( BitOr BitwiseOr )* )
LogicalAnd ::= '&&'
BitwiseOr ::= ( BitwiseXor ( BitXor BitwiseXor )* )
BitwiseXor ::= ( BitwiseAnd ( BitAnd BitwiseAnd )* )
BitXor ::= '^'
BitwiseAnd ::= ( Equality ( EqualityOps Equality )? )
Equality ::= ( Compare ( Comparison | TypeCheck )? )
EqualityOps ::= ( '==' | '!=' )
Compare ::= ( Shift ( ShiftOps Shift )* )
Comparison ::= ( CompareOps Compare )
TypeCheck ::= ( 'isA' TypeConstructor )
CompareOps ::= ( '<=' | '>=' | '<' | '>' )
Shift ::= ( Sum ( SumOps Sum )* )
ShiftOps ::= ( '<<' | '>>' | '>>>' )
Sum ::= ( Product ( MulOps Product )* )
SumOps ::= ( '+' | '-' )
Product ::= ( ( Cast | UnaryOps )* ( MethodReference | Value | NestedExpr | Ellipsis ) )
MulOps ::= ( '*' | '/' | '%' )
Cast ::= ( LP TypeName RP )
UnaryOps ::= ( '-' | '+' | '--' | '++' | '!' | '~' )
MethodReference ::= ( QualifiedName? DoubleColon Name )
DoubleColon ::= '::'
ValueConstruction ::= ( ObjConstruction | ArrayConstruction | Lambda | TupleConstruction | QualifiedName | Iterable | LiteralValue )
PostfixOps ::= ( '--' | '++' )
ArrayConstruction ::= ( LSqB ArrayElements? RSqB )
Lambda ::= ( ( SingleParamLambda | MultiparamLambda ) Ellipsis? ( Expression | MethodBlockBody ) )
LiteralValue ::= ( NumLiteral | CharLiteral | StringLiteral )
CharLiteral ::= ( ['] ( "\\'" | ( _NOT_  ['] . ) ) ['] )
SingleParamLambda ::= ( Name Arrow )+
MultiparamLambda ::= ( TypeName? CallParameters Arrow )
NamedCallParameters ::= ( LP NamedAssignmentList RP )
AnonymousCallParameters ::= ( LP ( ExpressionList OptionalEllipsis? )? RP )
NamedAssignmentList ::= ( NamedAssignment ( Comma NamedAssignment )* )
ObjConstructionBody ::= ( BlockStart ValueReference? NamedAssignmentList BlockEnd )
NamedAssignment ::= ( Name '=' Expression )
ArrayElements ::= ( ExpressionList Comma? )
Comprehension ::= ( LSqB NamedRange ( ( Comma | BitOr ) NamedRange )* ComprPipeline RSqB )
OpenRange ::= ( NumLiteral '..' NumLiteral? )
NamedRange ::= ( Name Colon OpenRange )
ComprPipeline ::= ( Arrow Expression ( BitOr Expression )* )
HexNumLiteral ::= ( '0x' [0-9a-fA-F] [0-9a-fA-F_]* )
OctNumLiteral ::= ( '0o' [0-7] [0-7_]* )
BinNumLiteral ::= ( '0b' [01] [01_]* )
FloatNumLiteral ::= ( DecSegment '.' DecSegment ( ( 'e' | 'E' ) ( '+' | '-' )? DecSegment )? )
DecNumLiteral ::= DecSegment
NumSuffix ::= ( 'i8' | 'u8' | 'i16' | 'u16' | 'i32' | 'u32' | 'i64' | 'u64' | 'f16' | 'f32' | 'f64' )
DecSegment ::= ( [0-9] [0-9_]* )
InterpolatedStringLiteral ::= ( 'F"' ( '\\"' | ( _NOT_  '"' . ) )* '"' )
StringSegment ::= ( '"' ( '\\"' | ( _NOT_  '"' . ) )* '"' )
whitespace ::= ( [ \t\r\n]* Comment? )
Comment ::= ( '//' ( _NOT_  end . )* end )
end ::= ( eol | eof )
eol ::= ( '\r\n' | '\n' | '\r' )

//Added tokens for EBNF
_NOT_ ::= '!'
_AND_ ::= '&'
mingodad commented 2 years ago

I'm also looking at nez and found that you seem to have the most update version of it but decided to abandon it. Can you tell me why ? Have you discovered a flaw on it ?

I'm just starting looking at it and I'm curious to know why it doesn't went further and widespread, because it main idea is a nice one Open Grammar Language.

mingodad commented 2 years ago

I did some fixes for the EBNF generation on https://github.com/mingodad/peg and noticed that this rule could be simplified and my direct translation to EBNF is shown properly this way.

CharLiteral <- [\'] <('\'' / ![\'] .)> [\']

To:

CharLiteral <- ['] <('\'' / !['] .)> [']