mdegirolami / sing

BSD 3-Clause "New" or "Revised" License
3 stars 0 forks source link

Grammar railroad diagram #3

Open mingodad opened 2 years ago

mingodad commented 2 years ago

Using a parser generator to produce an EBNF understood by https://www.bottlecaps.de/rr/ui and following the code flow in https://github.com/mdegirolami/sing/blob/master/compiler/src/Parser.cpp, we can have a nice railroad diagram (https://en.wikipedia.org/wiki/Syntax_diagram) .

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".

//
// EBNF generated by CocoR parser generator to be viewed with https://www.bottlecaps.de/rr/ui
//

//
// productions
//

Sing ::=  ParseNamespace? ParseDependency* ParseDeclaration* EOF
ParseNamespace ::=  TOKEN_NAMESPACE TOKEN_NAME ( TOKEN_DOT TOKEN_NAME )* TOKEN_SEMICOLON
ParseDependency ::=  TOKEN_REQUIRES TOKEN_LITERAL_STRING ( TOKEN_COMMA TOKEN_NAME )? TOKEN_SEMICOLON
ParseDeclaration ::=  TOKEN_PUBLIC? ( ParseType | ParseVar | ParseConst | ParseFunctionDeclaration | ParseEnum | ParseInterface | ParseClass )
ParseType ::=  TOKEN_TYPE TOKEN_NAME ParseTypeSpecification TOKEN_SEMICOLON
ParseVar ::=  TOKEN_VAR TOKEN_NAME ( TOKEN_ASSIGN ParseIniter )? TOKEN_SEMICOLON
ParseConst ::=  TOKEN_LET TOKEN_NAME ParseTypeSpecification? TOKEN_ASSIGN ParseIniter TOKEN_SEMICOLON
ParseFunctionDeclaration ::=  TOKEN_FUNC TOKEN_NAME ( TOKEN_DOT TOKEN_NAME )? ParseFunctionType ( TOKEN_SEMICOLON | ParseBlock )
ParseEnum ::=  TOKEN_ENUM TOKEN_NAME TOKEN_CURLY_OPEN ParseEnumElement ( TOKEN_COMMA ParseEnumElement )* TOKEN_CURLY_CLOSE
ParseInterface ::=  TOKEN_INTERFACE TOKEN_NAME ( TOKEN_COLON ParseNamedType ( TOKEN_COMMA ParseNamedType )* )? TOKEN_CURLY_OPEN ( TOKEN_FUNC TOKEN_MUT? ParseFunctionType TOKEN_SEMICOLON )* TOKEN_NAME TOKEN_CURLY_CLOSE
ParseClass ::=  TOKEN_CLASS TOKEN_NAME ( TOKEN_COLON ParseNamedType ( TOKEN_BY TOKEN_NAME )? ( TOKEN_COMMA ParseNamedType ( TOKEN_BY TOKEN_NAME )? )* )?
ParseTypeSpecification ::=  ( TOKEN_INT8 | TOKEN_INT16 | TOKEN_INT32 | TOKEN_INT64 | TOKEN_UINT8 | TOKEN_UINT16 | TOKEN_UINT32 | TOKEN_UINT64 | TOKEN_FLOAT32 | TOKEN_FLOAT64 | TOKEN_COMPLEX64 | TOKEN_COMPLEX128 | TOKEN_STRING | TOKEN_BOOL | TOKEN_VOID ) | ParseNamedType | TOKEN_MAP TOKEN_ROUND_OPEN ParseTypeSpecification TOKEN_ROUND_CLOSE ParseTypeSpecification | ParseIndices | ( TOKEN_CONST | TOKEN_WEAK )? TOKEN_MPY ParseTypeSpecification | ParseFunctionType
ParseIniter ::=  ( TOKEN_CURLY_OPEN ParseIniter ( TOKEN_COMMA ParseIniter )* TOKEN_CURLY_CLOSE )? ParseExpression
ParseFunctionType ::=  TOKEN_PURE? ParseArgsDef ParseTypeSpecification
ParseBlock ::=  TOKEN_CURLY_OPEN ParseStatement* TOKEN_CURLY_CLOSE
ParseStatement ::=  ParseVar | ParseConst | ParseBlock | ParseWhile | ParseIf | ParseFor | ParseSwitch | ParseTypeSwitch | ( TOKEN_BREAK | TOKEN_CONTINUE ) TOKEN_SEMICOLON | TOKEN_RETURN ( TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE )? TOKEN_SEMICOLON | ( TOKEN_INC | TOKEN_DEC ) ParsePrefixExpression TOKEN_SEMICOLON | TOKEN_SWAP TOKEN_ROUND_OPEN ParsePrefixExpression TOKEN_COMMA ParsePrefixExpression TOKEN_ROUND_CLOSE TOKEN_SEMICOLON | ParseLeftTermStatement
ParseWhile ::=  TOKEN_WHILE TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock
ParseIf ::=  TOKEN_IF TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock ( TOKEN_ELSE ( ParseIf | ParseBlock ) )?
ParseFor ::=  TOKEN_FOR TOKEN_ROUND_OPEN TOKEN_NAME ( TOKEN_COMMA TOKEN_NAME )* TOKEN_IN ParseExpression ( TOKEN_COLON ParseExpression ( TOKEN_STEP ParseExpression )? )? TOKEN_ROUND_CLOSE ParseBlock
ParseSwitch ::=  TOKEN_SWITCH TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE TOKEN_CURLY_OPEN ParseSwitchCase* ( TOKEN_DEFAULT TOKEN_COLON ParseStatement )? TOKEN_CURLY_CLOSE
ParseTypeSwitch ::=  TOKEN_TYPESWITCH TOKEN_ROUND_OPEN TOKEN_NAME TOKEN_ASSIGN ParseExpression TOKEN_ROUND_CLOSE TOKEN_CURLY_OPEN ParseTypeSwitchCase* TOKEN_CURLY_CLOSE
ParseExpression ::=  ParsePrefixExpression ( GetBinopPriority ParsePrefixExpression )*
ParsePrefixExpression ::=  TOKEN_MINUS | TOKEN_PLUS | TOKEN_AND | TOKEN_NOT | TOKEN_LOGICAL_NOT | TOKEN_MPY | ParsePostfixExpression
ParseLeftTermStatement ::=  ParsePrefixExpression ( ( TOKEN_ASSIGN | TOKEN_UPD_PLUS | TOKEN_UPD_MINUS | TOKEN_UPD_MPY | TOKEN_UPD_DIVIDE | TOKEN_UPD_XOR | TOKEN_UPD_MOD | TOKEN_UPD_SHR | TOKEN_UPD_SHL | TOKEN_UPD_AND | TOKEN_UPD_OR ) ParseExpression | ( TOKEN_INC | TOKEN_DEC ) ) TOKEN_SEMICOLON
ParseSwitchCase ::=  ParseCase ParseCase* ParseStatement
ParseCase ::=  TOKEN_CASE ParseExpression TOKEN_COLON
ParseTypeSwitchCase ::=  ParseTypeCase ParseTypeCase* ParseStatement
ParseTypeCase ::=  TOKEN_CASE ParseTypeSpecification TOKEN_COLON
ParseEnumElement ::=  TOKEN_NAME ( TOKEN_ASSIGN ParseExpression )?
ParseNamedType ::=  TOKEN_NAME
ParseIndices ::=  ParseOneIndice ParseOneIndice*
ParseOneIndice ::=  TOKEN_SQUARE_OPEN ( ParseOneIndixeExpr ( TOKEN_COMMA ParseOneIndixeExpr )* )? TOKEN_SQUARE_CLOSE ParseTypeSpecification
ParseOneIndixeExpr ::=  TOKEN_MPY | ParseExpression
ParseArgsDef ::=  TOKEN_ROUND_OPEN ( TOKEN_ETC | ParseSingleArgDef ( TOKEN_COMMA ParseSingleArgDef )* )? TOKEN_ROUND_CLOSE
ParseSingleArgDef ::=  ( TOKEN_IN | TOKEN_OUT | TOKEN_IO )? TOKEN_NAME ParseTypeSpecification ( TOKEN_ASSIGN ParseIniter )?
GetBinopPriority ::=  TOKEN_POWER | TOKEN_MPY | TOKEN_DIVIDE | TOKEN_MOD | TOKEN_SHR | TOKEN_SHL | TOKEN_AND | TOKEN_PLUS | TOKEN_MINUS | TOKEN_OR | TOKEN_XOR | TOKEN_ANGLE_OPEN_LT | TOKEN_ANGLE_CLOSE_GT | TOKEN_GTE | TOKEN_LTE | TOKEN_DIFFERENT | TOKEN_EQUAL | TOKEN_LOGICAL_AND | TOKEN_LOGICAL_OR
ParsePostfixExpression ::=  ParseExpressionTerm ( ParseRangesOrIndices | TOKEN_DOT | ParseArguments )
ParseExpressionTerm ::=  TOKEN_NULL | TOKEN_FALSE | TOKEN_TRUE | TOKEN_LITERAL_STRING | TOKEN_LITERAL_UINT | TOKEN_LITERAL_FLOAT | TOKEN_LITERAL_IMG | TOKEN_SIZEOF TOKEN_ROUND_OPEN ( ParsePrefixExpression | ParseTypeSpecification ) TOKEN_ROUND_CLOSE | ( TOKEN_INT8 | TOKEN_INT16 | TOKEN_INT32 | TOKEN_INT64 | TOKEN_UINT8 | TOKEN_UINT16 | TOKEN_UINT32 | TOKEN_UINT64 | TOKEN_FLOAT32 | TOKEN_FLOAT64 | TOKEN_COMPLEX64 | TOKEN_COMPLEX128 | TOKEN_STRING | TOKEN_BOOL ) TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE | TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE | TOKEN_NAME | TOKEN_THIS | ( TOKEN_MIN | TOKEN_MAX ) TOKEN_ROUND_OPEN ParseExpression TOKEN_COMMA ParseExpression TOKEN_ROUND_CLOSE
ParseRangesOrIndices ::=  TOKEN_SQUARE_OPEN
ParseArguments ::=  TOKEN_ROUND_OPEN
TOKEN_LITERAL_IMG ::= "??()??"

//
// tokens
//

TOKEN_NULL ::= "null"
TOKEN_TRUE ::= "true"
TOKEN_FALSE ::= "false"
TOKEN_VOID ::= "void"
TOKEN_MUT ::= "mut"
TOKEN_REQUIRES ::= "requires"
TOKEN_NAMESPACE ::= "namespace"
TOKEN_VAR ::= "var"
TOKEN_CONST ::= "const"
TOKEN_TYPE ::= "type"
TOKEN_MAP ::= "map"
TOKEN_WEAK ::= "weak"
TOKEN_INT8 ::= "i8"
TOKEN_INT16 ::= "i16"
TOKEN_INT32 ::= "i32"
TOKEN_INT64 ::= "i64"
TOKEN_UINT8 ::= "u8"
TOKEN_UINT16 ::= "u16"
TOKEN_UINT32 ::= "u32"
TOKEN_UINT64 ::= "u64"
TOKEN_FLOAT32 ::= "f32"
TOKEN_FLOAT64 ::= "f64"
TOKEN_COMPLEX64 ::= "c64"
TOKEN_COMPLEX128 ::= "c128"
TOKEN_LET ::= "let"
TOKEN_STRING ::= "string"
TOKEN_BOOL ::= "bool"
TOKEN_FUNC ::= "fn"
TOKEN_PURE ::= "pure"
TOKEN_IN ::= "in"
TOKEN_OUT ::= "out"
TOKEN_IO ::= "io"
TOKEN_DOUBLEDOT ::= ".."
TOKEN_ETC ::= "..."
TOKEN_IF ::= "if"
TOKEN_ELSE ::= "else"
TOKEN_WHILE ::= "while"
TOKEN_FOR ::= "for"
TOKEN_RETURN ::= "return"
TOKEN_BREAK ::= "break"
TOKEN_CONTINUE ::= "continue"
TOKEN_SIZEOF ::= "sizeof"
TOKEN_XOR ::= "^"
TOKEN_CASE ::= "case"
TOKEN_TYPESWITCH ::= "typeswitch"
TOKEN_SWITCH ::= "switch"
TOKEN_DEFAULT ::= "default"
TOKEN_PUBLIC ::= "public"
TOKEN_PRIVATE ::= "private"
TOKEN_ENUM ::= "enum"
TOKEN_CLASS ::= "class"
TOKEN_THIS ::= "this"
TOKEN_INTERFACE ::= "interface"
TOKEN_BY ::= "by"
TOKEN_STEP ::= "step"
TOKEN_MIN ::= "min"
TOKEN_MAX ::= "max"
TOKEN_SWAP ::= "swap"
TOKEN_ROUND_OPEN ::= "("
TOKEN_ROUND_CLOSE ::= ")"
TOKEN_SQUARE_OPEN ::= "["
TOKEN_SQUARE_CLOSE ::= "]"
TOKEN_CURLY_OPEN ::= "{"
TOKEN_CURLY_CLOSE ::= "}"
TOKEN_ANGLE_OPEN_LT ::= "<"
TOKEN_ANGLE_CLOSE_GT ::= ">"
TOKEN_COMMA ::= ","
TOKEN_ASSIGN ::= "="
TOKEN_INC ::= "++"
TOKEN_DEC ::= "--"
TOKEN_DOT ::= "."
TOKEN_PLUS ::= "+"
TOKEN_MINUS ::= "-"
TOKEN_MPY ::= "*"
TOKEN_DIVIDE ::= "/"
TOKEN_POWER ::= "**"
TOKEN_MOD ::= "%"
TOKEN_SHR ::= ">>"
TOKEN_SHL ::= "<<"
TOKEN_NOT ::= "~"
TOKEN_AND ::= "&"
TOKEN_OR ::= "|"
TOKEN_GTE ::= ">="
TOKEN_LTE ::= "<="
TOKEN_DIFFERENT ::= "!="
TOKEN_EQUAL ::= "=="
TOKEN_LOGICAL_NOT ::= "!"
TOKEN_LOGICAL_AND ::= "&&"
TOKEN_LOGICAL_OR ::= "||"
TOKEN_COLON ::= ":"
TOKEN_SEMICOLON ::= ";"
TOKEN_UPD_PLUS ::= "+="
TOKEN_UPD_MINUS ::= "-="
TOKEN_UPD_MPY ::= "*="
TOKEN_UPD_DIVIDE ::= "/="
TOKEN_UPD_XOR ::= "^="
TOKEN_UPD_MOD ::= "%="
TOKEN_UPD_SHR ::= ">>="
TOKEN_UPD_SHL ::= "<<="
TOKEN_UPD_AND ::= "&="
TOKEN_UPD_OR ::= "|="

Parser so far on variant of https://github.com/mingodad/CocoR-CPP:

/* ANSI C 89 grammar as specified in http://flash-gordon.me.uk/ansi.c.txt

    Processing the C grammar requires LL(1) conflict resolvers, some of which
    need to check whether an identifier is a type name (see IsTypeName() below).
    So the grammar assumes that there is a symbol table, from where you can
    look up an identifier and find out whether it is a type name.

    The language in the semantic actions here is C#, but it can easily be
    translated to any other language.
*/

$namespace=Sing

#ifdef __SQUILU__
#include "Scanner.nut"
typedef SymTab SymTab;
#else
#include "Scanner.h"
#endif

COMPILER Sing

CHARACTERS
    letter     = 'A'..'Z' + 'a'..'z' + '_'.
    oct        = '0'..'7'.
    digit      = '0'..'9'.
    nzdigit    = '1'..'9'.
    hex        = digit + 'a'..'f' + 'A'..'F'.
    notQuote   = ANY - '"' - "\r\n".
    notApo     = ANY - '\'' - "\r\n".

    tab        = '\t'.
    cr         = '\r'.
    lf         = '\n'.
    newLine    = cr + lf.
    notNewLine = ANY - newLine .
    ws         = " " + tab + '\u000b' + '\u000c'.

TOKENS
    TOKEN_NAME    = letter {letter | digit}.

    TOKEN_LITERAL_FLOAT = ( '.' digit {digit} [('e'|'E')  ['+'|'-'] digit {digit}]
                         | digit {digit} '.' {digit} [('e'|'E')  ['+'|'-'] digit {digit}]
                         | digit {digit} ('e'|'E')  ['+'|'-'] digit {digit}
                         )
                         ['f'|'l'|'F'|'L'].

    TOKEN_LITERAL_UINT   = ( nzdigit {digit}
                         | '0' {oct}
                         | ("0x"|"0X") hex {hex}
                         )
                         {'u'|'U'|'l'|'L'}.

    TOKEN_LITERAL_STRING   = '"' {notQuote} '"'.        // no check for valid escape sequences

    charcon  = '\'' notApo {notApo} '\''. // no check for valid escape sequences

    // tokens defined in order to get their names for LL(1) conflict resolvers
    //{\([^,]+\),\s*\("[^"]+"\).+
    TOKEN_NULL = "null" .
    TOKEN_TRUE = "true" .
    TOKEN_FALSE = "false" .
    TOKEN_VOID = "void" .

    TOKEN_MUT = "mut" .
    TOKEN_REQUIRES = "requires" .
    TOKEN_NAMESPACE = "namespace" .
    TOKEN_VAR = "var" .
    TOKEN_CONST = "const" .
    TOKEN_TYPE = "type" .
    TOKEN_MAP = "map" .
    TOKEN_WEAK = "weak" .
    TOKEN_INT8 = "i8" .
    TOKEN_INT16 = "i16" .
    TOKEN_INT32 = "i32" .
    TOKEN_INT64 = "i64" .
    TOKEN_UINT8 = "u8" .
    TOKEN_UINT16 = "u16" .
    TOKEN_UINT32 = "u32" .
    TOKEN_UINT64 = "u64" .
    TOKEN_FLOAT32 = "f32" .
    TOKEN_FLOAT64 = "f64" .
    TOKEN_COMPLEX64 = "c64" .
    TOKEN_COMPLEX128 = "c128" .
    TOKEN_LET = "let" .
    TOKEN_STRING = "string" .
    TOKEN_BOOL = "bool" .

    TOKEN_FUNC = "fn" .
    TOKEN_PURE = "pure" .
    TOKEN_IN = "in" .
    TOKEN_OUT = "out" .
    TOKEN_IO = "io" .
    TOKEN_DOUBLEDOT  = ".." .
    TOKEN_ETC = "..." .
    TOKEN_IF = "if" .
    TOKEN_ELSE = "else" .
    TOKEN_WHILE = "while" .
    TOKEN_FOR = "for" .
    TOKEN_RETURN = "return" .
    TOKEN_BREAK = "break" .
    TOKEN_CONTINUE = "continue" .

    TOKEN_SIZEOF = "sizeof" .
    TOKEN_XOR = "^" .
    TOKEN_CASE = "case" .
    TOKEN_TYPESWITCH = "typeswitch" .
    TOKEN_SWITCH = "switch" .
    TOKEN_DEFAULT = "default" .

    TOKEN_PUBLIC = "public" .
    TOKEN_PRIVATE = "private" .
    TOKEN_ENUM = "enum" .
    TOKEN_CLASS = "class" .
    TOKEN_THIS = "this" .
    TOKEN_INTERFACE = "interface" .
    TOKEN_BY = "by" .
    TOKEN_STEP = "step" .
    TOKEN_MIN = "min" .
    TOKEN_MAX = "max" .
    TOKEN_SWAP = "swap" .

    TOKEN_ROUND_OPEN = "(" .
    TOKEN_ROUND_CLOSE = ")" .
    TOKEN_SQUARE_OPEN = "[" .
    TOKEN_SQUARE_CLOSE = "]" .
    TOKEN_CURLY_OPEN = "{" .
    TOKEN_CURLY_CLOSE = "}" .
    TOKEN_ANGLE_OPEN_LT = "<" .
    TOKEN_ANGLE_CLOSE_GT = ">" .

    TOKEN_COMMA = "," .
    TOKEN_ASSIGN = "=" .
    TOKEN_INC = "++" .
    TOKEN_DEC = "--" .
    TOKEN_DOT = "." .
    TOKEN_PLUS = "+" .
    TOKEN_MINUS = "-" .
    TOKEN_MPY = "*" .
    TOKEN_DIVIDE = "/" .
    TOKEN_POWER = "**" .
    TOKEN_MOD = "%" .
    TOKEN_SHR = ">>" .
    TOKEN_SHL = "<<" .
    TOKEN_NOT = "~" .
    TOKEN_AND = "&" .
    TOKEN_OR = "|" .
    TOKEN_GTE = ">=" .
    TOKEN_LTE = "<=" .
    TOKEN_DIFFERENT = "!=" .
    TOKEN_EQUAL = "==" .
    TOKEN_LOGICAL_NOT = "!" .
    TOKEN_LOGICAL_AND = "&&" .
    TOKEN_LOGICAL_OR = "||" .
    TOKEN_COLON = ":" .
    TOKEN_SEMICOLON = ";" .

    TOKEN_UPD_PLUS = "+=" .
    TOKEN_UPD_MINUS = "-=" .
    TOKEN_UPD_MPY = "*=" .
    TOKEN_UPD_DIVIDE = "/=" .
    TOKEN_UPD_XOR = "^=" .
    TOKEN_UPD_MOD = "%=" .
    TOKEN_UPD_SHR = ">>=" .
    TOKEN_UPD_SHL = "<<=" .
    TOKEN_UPD_AND = "&=" .
    TOKEN_UPD_OR = "|=" .

PRAGMAS
    //---- preprocessor commands (not handled here)
    ppDefine  = '#' {ws} "define" {notNewLine} newLine.
    ppUndef   = '#' {ws} "undef" {notNewLine} newLine.
    ppIf      = '#' {ws} "if" {notNewLine} newLine.
    ppElif    = '#' {ws} "elif" {notNewLine} newLine.
    ppElse    = '#' {ws} "else" {notNewLine} newLine.
    ppEndif   = '#' {ws} "endif" {notNewLine} newLine.
    ppInclude = '#' {ws} "include" {notNewLine} newLine.
    ppLine = '#' {ws} digit {digit} {notNewLine} newLine.

COMMENTS FROM "/*" TO "*/"
COMMENTS FROM "//" TO lf

IGNORE tab + cr + lf

PRODUCTIONS

//---------- Compilation Unit ----------
Sing =
    [ParseNamespace] {ParseDependency} {ParseDeclaration} EOF
    .

ParseNamespace =
    TOKEN_NAMESPACE TOKEN_NAME {TOKEN_DOT TOKEN_NAME} TOKEN_SEMICOLON
    .

ParseDependency =
    TOKEN_REQUIRES TOKEN_LITERAL_STRING [TOKEN_COMMA TOKEN_NAME] TOKEN_SEMICOLON
    .

ParseDeclaration =
    [TOKEN_PUBLIC] (
        ParseType
        | ParseVar
        | ParseConst
        | ParseFunctionDeclaration
        | ParseEnum
        | ParseInterface
        | ParseClass
    )
    .

ParseType =
    TOKEN_TYPE TOKEN_NAME ParseTypeSpecification TOKEN_SEMICOLON
    .

ParseVar =
    TOKEN_VAR TOKEN_NAME [TOKEN_ASSIGN ParseIniter] TOKEN_SEMICOLON
    .

ParseConst =
    TOKEN_LET TOKEN_NAME [ParseTypeSpecification] TOKEN_ASSIGN ParseIniter TOKEN_SEMICOLON
    .

ParseFunctionDeclaration =
    TOKEN_FUNC TOKEN_NAME [TOKEN_DOT TOKEN_NAME] ParseFunctionType (TOKEN_SEMICOLON | ParseBlock)
    .

ParseBlock =
    TOKEN_CURLY_OPEN {ParseStatement} TOKEN_CURLY_CLOSE
    .

ParseStatement =
    ParseVar
    | ParseConst
    | ParseBlock
    | ParseWhile
    | ParseIf
    | ParseFor
    | ParseSwitch
    | ParseTypeSwitch
    | (TOKEN_BREAK | TOKEN_CONTINUE) TOKEN_SEMICOLON
    | TOKEN_RETURN [TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE] TOKEN_SEMICOLON
    | (TOKEN_INC | TOKEN_DEC) ParsePrefixExpression TOKEN_SEMICOLON
    | TOKEN_SWAP TOKEN_ROUND_OPEN ParsePrefixExpression TOKEN_COMMA ParsePrefixExpression TOKEN_ROUND_CLOSE TOKEN_SEMICOLON
    | ParseLeftTermStatement
    .

ParseWhile =
    TOKEN_WHILE TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock
    .

ParseIf =
    TOKEN_IF TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock [TOKEN_ELSE (ParseIf | ParseBlock)]
    .

ParseFor =
    TOKEN_FOR TOKEN_ROUND_OPEN TOKEN_NAME {TOKEN_COMMA TOKEN_NAME}
        TOKEN_IN ParseExpression [TOKEN_COLON ParseExpression [TOKEN_STEP ParseExpression]] TOKEN_ROUND_CLOSE
        ParseBlock
    .

ParseSwitch =
    TOKEN_SWITCH TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE
        TOKEN_CURLY_OPEN {ParseSwitchCase} [TOKEN_DEFAULT TOKEN_COLON ParseStatement] TOKEN_CURLY_CLOSE
    .

ParseSwitchCase =
    ParseCase {ParseCase} ParseStatement
    .

ParseCase =
    TOKEN_CASE ParseExpression TOKEN_COLON
    .

ParseTypeSwitch =
    TOKEN_TYPESWITCH TOKEN_ROUND_OPEN TOKEN_NAME TOKEN_ASSIGN ParseExpression TOKEN_ROUND_CLOSE
        TOKEN_CURLY_OPEN {ParseTypeSwitchCase} TOKEN_CURLY_CLOSE
    .

ParseTypeSwitchCase =
    ParseTypeCase {ParseTypeCase} ParseStatement
    .

ParseTypeCase =
    TOKEN_CASE ParseTypeSpecification TOKEN_COLON
    .

ParseLeftTermStatement =
    ParsePrefixExpression (
        (
            TOKEN_ASSIGN
            | TOKEN_UPD_PLUS
            | TOKEN_UPD_MINUS
            | TOKEN_UPD_MPY
            | TOKEN_UPD_DIVIDE
            | TOKEN_UPD_XOR
            | TOKEN_UPD_MOD
            | TOKEN_UPD_SHR
            | TOKEN_UPD_SHL
            | TOKEN_UPD_AND
            | TOKEN_UPD_OR
        ) ParseExpression
        | (TOKEN_INC | TOKEN_DEC)

    ) TOKEN_SEMICOLON
    .

ParseEnum =
    TOKEN_ENUM TOKEN_NAME TOKEN_CURLY_OPEN ParseEnumElement {TOKEN_COMMA ParseEnumElement} TOKEN_CURLY_CLOSE
    .

ParseEnumElement =
    TOKEN_NAME [TOKEN_ASSIGN ParseExpression]
    .

ParseInterface =
    TOKEN_INTERFACE TOKEN_NAME [TOKEN_COLON ParseNamedType {TOKEN_COMMA ParseNamedType}]
        TOKEN_CURLY_OPEN {TOKEN_FUNC [TOKEN_MUT] ParseFunctionType TOKEN_SEMICOLON} TOKEN_NAME TOKEN_CURLY_CLOSE
    .

ParseClass =
    TOKEN_CLASS TOKEN_NAME [TOKEN_COLON ParseNamedType [TOKEN_BY TOKEN_NAME] {TOKEN_COMMA ParseNamedType [TOKEN_BY TOKEN_NAME]}]
    .

ParseTypeSpecification =
    (
        TOKEN_INT8
        | TOKEN_INT16
        | TOKEN_INT32
        | TOKEN_INT64
        | TOKEN_UINT8
        | TOKEN_UINT16
        | TOKEN_UINT32
        | TOKEN_UINT64
        | TOKEN_FLOAT32
        | TOKEN_FLOAT64
        | TOKEN_COMPLEX64
        | TOKEN_COMPLEX128
        | TOKEN_STRING
        | TOKEN_BOOL
        | TOKEN_VOID
    )
    | ParseNamedType
    | TOKEN_MAP TOKEN_ROUND_OPEN ParseTypeSpecification TOKEN_ROUND_CLOSE ParseTypeSpecification
    | ParseIndices
    | [ TOKEN_CONST | TOKEN_WEAK ] TOKEN_MPY ParseTypeSpecification
    | ParseFunctionType
    .

ParseNamedType =
    TOKEN_NAME
    .

ParseIndices =
    ParseOneIndice {ParseOneIndice}
    .

ParseOneIndice =
    TOKEN_SQUARE_OPEN [ParseOneIndixeExpr {TOKEN_COMMA ParseOneIndixeExpr} ] TOKEN_SQUARE_CLOSE ParseTypeSpecification
    .

ParseOneIndixeExpr =
    /*IF()*/ TOKEN_MPY
    | ParseExpression
    .

ParseFunctionType =
    [TOKEN_PURE] ParseArgsDef ParseTypeSpecification
    .

ParseArgsDef =
    TOKEN_ROUND_OPEN [TOKEN_ETC | ParseSingleArgDef {TOKEN_COMMA ParseSingleArgDef}] TOKEN_ROUND_CLOSE
    .

ParseSingleArgDef =
    [ TOKEN_IN | TOKEN_OUT | TOKEN_IO ] TOKEN_NAME ParseTypeSpecification [TOKEN_ASSIGN ParseIniter]
    .

ParseIniter =
    [TOKEN_CURLY_OPEN ParseIniter {TOKEN_COMMA ParseIniter} TOKEN_CURLY_CLOSE] ParseExpression
    .

ParseExpression =
    ParsePrefixExpression {GetBinopPriority ParsePrefixExpression}
    .

GetBinopPriority =
    TOKEN_POWER // 0

    | TOKEN_MPY
    | TOKEN_DIVIDE
    | TOKEN_MOD
    | TOKEN_SHR
    | TOKEN_SHL
    | TOKEN_AND // 1

    | TOKEN_PLUS
    | TOKEN_MINUS
    | TOKEN_OR
    | TOKEN_XOR // 2

    | TOKEN_ANGLE_OPEN_LT
    | TOKEN_ANGLE_CLOSE_GT
    | TOKEN_GTE
    | TOKEN_LTE
    | TOKEN_DIFFERENT
    | TOKEN_EQUAL // 3

    | TOKEN_LOGICAL_AND // 4

    | TOKEN_LOGICAL_OR // 5

    // 10
    .

ParsePrefixExpression =
    TOKEN_MINUS
    | TOKEN_PLUS
    | TOKEN_AND
    | TOKEN_NOT
    | TOKEN_LOGICAL_NOT
    | TOKEN_MPY
    | ParsePostfixExpression
    .

ParsePostfixExpression =
    ParseExpressionTerm (
        ParseRangesOrIndices
        | TOKEN_DOT
        | ParseArguments
    )
    .

ParseRangesOrIndices =
    TOKEN_SQUARE_OPEN
    .

ParseArguments =
    TOKEN_ROUND_OPEN
    .

ParseExpressionTerm =
    TOKEN_NULL
    | TOKEN_FALSE
    | TOKEN_TRUE
    | TOKEN_LITERAL_STRING
    | TOKEN_LITERAL_UINT
    | TOKEN_LITERAL_FLOAT
    | TOKEN_LITERAL_IMG
    | TOKEN_SIZEOF TOKEN_ROUND_OPEN (ParsePrefixExpression | ParseTypeSpecification) TOKEN_ROUND_CLOSE
    | (
        TOKEN_INT8
        | TOKEN_INT16
        | TOKEN_INT32
        | TOKEN_INT64
        | TOKEN_UINT8
        | TOKEN_UINT16
        | TOKEN_UINT32
        | TOKEN_UINT64
        | TOKEN_FLOAT32
        | TOKEN_FLOAT64
        | TOKEN_COMPLEX64
        | TOKEN_COMPLEX128
        | TOKEN_STRING
        | TOKEN_BOOL
        ) TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE
    | TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE
    | TOKEN_NAME
    | TOKEN_THIS
    | (
        TOKEN_MIN
        | TOKEN_MAX
        ) TOKEN_ROUND_OPEN ParseExpression TOKEN_COMMA ParseExpression TOKEN_ROUND_CLOSE
    .

END Sing.
mdegirolami commented 2 years ago

Nice tool indeed. I didn't take the time to check if all the EBNF is right but I will for sure add railroad diagrams to the documentation when I have time to revise it.

Regards

Maurizio

https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=icon Virus-free. www.avast.com https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=link <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Mon, Apr 4, 2022 at 10:22 PM Domingo Alvarez Duarte < @.***> wrote:

Using a parser generator to produce an EBNF understood by https://www.bottlecaps.de/rr/ui and following the code flow in https://github.com/mdegirolami/sing/blob/master/compiler/src/Parser.cpp, we can have a nice railroad diagram ( https://en.wikipedia.org/wiki/Syntax_diagram) .

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".

// // EBNF generated by CocoR parser generator to be viewed with https://www.bottlecaps.de/rr/ui //

// // productions //

Sing ::= ParseNamespace? ParseDependency ParseDeclaration EOF ParseNamespace ::= TOKEN_NAMESPACE TOKEN_NAME ( TOKEN_DOT TOKEN_NAME ) TOKEN_SEMICOLON ParseDependency ::= TOKEN_REQUIRES TOKEN_LITERAL_STRING ( TOKEN_COMMA TOKEN_NAME )? TOKEN_SEMICOLON ParseDeclaration ::= TOKEN_PUBLIC? ( ParseType | ParseVar | ParseConst | ParseFunctionDeclaration | ParseEnum | ParseInterface | ParseClass ) ParseType ::= TOKEN_TYPE TOKEN_NAME ParseTypeSpecification TOKEN_SEMICOLON ParseVar ::= TOKEN_VAR TOKEN_NAME ( TOKEN_ASSIGN ParseIniter )? TOKEN_SEMICOLON ParseConst ::= TOKEN_LET TOKEN_NAME ParseTypeSpecification? TOKEN_ASSIGN ParseIniter TOKEN_SEMICOLON ParseFunctionDeclaration ::= TOKEN_FUNC TOKEN_NAME ( TOKEN_DOT TOKEN_NAME )? ParseFunctionType ( TOKEN_SEMICOLON | ParseBlock ) ParseEnum ::= TOKEN_ENUM TOKEN_NAME TOKEN_CURLY_OPEN ParseEnumElement ( TOKEN_COMMA ParseEnumElement ) TOKEN_CURLY_CLOSE ParseInterface ::= TOKEN_INTERFACE TOKEN_NAME ( TOKEN_COLON ParseNamedType ( TOKEN_COMMA ParseNamedType ) )? TOKEN_CURLY_OPEN ( TOKEN_FUNC TOKEN_MUT? ParseFunctionType TOKEN_SEMICOLON ) TOKEN_NAME TOKEN_CURLY_CLOSE ParseClass ::= TOKEN_CLASS TOKEN_NAME ( TOKEN_COLON ParseNamedType ( TOKEN_BY TOKEN_NAME )? ( TOKEN_COMMA ParseNamedType ( TOKEN_BY TOKEN_NAME )? ) )? ParseTypeSpecification ::= ( TOKEN_INT8 | TOKEN_INT16 | TOKEN_INT32 | TOKEN_INT64 | TOKEN_UINT8 | TOKEN_UINT16 | TOKEN_UINT32 | TOKEN_UINT64 | TOKEN_FLOAT32 | TOKEN_FLOAT64 | TOKEN_COMPLEX64 | TOKEN_COMPLEX128 | TOKEN_STRING | TOKEN_BOOL | TOKEN_VOID ) | ParseNamedType | TOKEN_MAP TOKEN_ROUND_OPEN ParseTypeSpecification TOKEN_ROUND_CLOSE ParseTypeSpecification | ParseIndices | ( TOKEN_CONST | TOKEN_WEAK )? TOKEN_MPY ParseTypeSpecification | ParseFunctionType ParseIniter ::= ( TOKEN_CURLY_OPEN ParseIniter ( TOKEN_COMMA ParseIniter ) TOKEN_CURLY_CLOSE )? ParseExpression ParseFunctionType ::= TOKEN_PURE? ParseArgsDef ParseTypeSpecification ParseBlock ::= TOKEN_CURLY_OPEN ParseStatement TOKEN_CURLY_CLOSE ParseStatement ::= ParseVar | ParseConst | ParseBlock | ParseWhile | ParseIf | ParseFor | ParseSwitch | ParseTypeSwitch | ( TOKEN_BREAK | TOKEN_CONTINUE ) TOKEN_SEMICOLON | TOKEN_RETURN ( TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE )? TOKEN_SEMICOLON | ( TOKEN_INC | TOKEN_DEC ) ParsePrefixExpression TOKEN_SEMICOLON | TOKEN_SWAP TOKEN_ROUND_OPEN ParsePrefixExpression TOKEN_COMMA ParsePrefixExpression TOKEN_ROUND_CLOSE TOKEN_SEMICOLON | ParseLeftTermStatement ParseWhile ::= TOKEN_WHILE TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock ParseIf ::= TOKEN_IF TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock ( TOKEN_ELSE ( ParseIf | ParseBlock ) )? ParseFor ::= TOKEN_FOR TOKEN_ROUND_OPEN TOKEN_NAME ( TOKEN_COMMA TOKEN_NAME ) TOKEN_IN ParseExpression ( TOKEN_COLON ParseExpression ( TOKEN_STEP ParseExpression )? )? TOKEN_ROUND_CLOSE ParseBlock ParseSwitch ::= TOKEN_SWITCH TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE TOKEN_CURLY_OPEN ParseSwitchCase ( TOKEN_DEFAULT TOKEN_COLON ParseStatement )? TOKEN_CURLY_CLOSE ParseTypeSwitch ::= TOKEN_TYPESWITCH TOKEN_ROUND_OPEN TOKEN_NAME TOKEN_ASSIGN ParseExpression TOKEN_ROUND_CLOSE TOKEN_CURLY_OPEN TOKEN_CURLY_CLOSE ParseExpression ::= ParsePrefixExpression ParsePrefixExpression ::= TOKEN_MINUS | TOKEN_PLUS | TOKEN_AND | TOKEN_NOT | TOKEN_LOGICAL_NOT | TOKEN_MPY | ParsePostfixExpression ParseLeftTermStatement ::= ParsePrefixExpression ( ( TOKEN_ASSIGN | TOKEN_UPD_PLUS | TOKEN_UPD_MINUS | TOKEN_UPD_MPY | TOKEN_UPD_DIVIDE | TOKEN_UPD_XOR | TOKEN_UPD_MOD | TOKEN_UPD_SHR | TOKEN_UPD_SHL | TOKEN_UPD_AND | TOKEN_UPD_OR ) ParseExpression | ( TOKEN_INC | TOKEN_DEC ) ) TOKEN_SEMICOLON ParseSwitchCase ::= ParseCase ParseCase ParseStatement ParseCase ::= TOKEN_CASE ParseExpression TOKEN_COLON ParseTypeSwitchCase ::= ParseTypeCase ParseTypeCase ParseStatement ParseTypeCase ::= TOKEN_CASE ParseTypeSpecification TOKEN_COLON ParseEnumElement ::= TOKEN_NAME ( TOKEN_ASSIGN ParseExpression )? ParseNamedType ::= TOKEN_NAME ParseIndices ::= ParseOneIndice ParseOneIndice ParseOneIndice ::= TOKEN_SQUARE_OPEN ( ParseOneIndixeExpr ( TOKEN_COMMA ParseOneIndixeExpr ) )? TOKEN_SQUARE_CLOSE ParseTypeSpecification ParseOneIndixeExpr ::= ParseExpression | TOKEN_MPY ParseArgsDef ::= TOKEN_ROUND_OPEN ( TOKEN_ETC | ParseSingleArgDef ( TOKEN_COMMA ParseSingleArgDef ) )? TOKEN_ROUND_CLOSE ParseSingleArgDef ::= ( TOKEN_IN | TOKEN_OUT | TOKEN_IO )? TOKEN_NAME ParseTypeSpecification ( TOKEN_ASSIGN ParseIniter )? ParsePostfixExpression ::= ParseRangesOrIndices | TOKEN_DOT | ParseArguments ParseRangesOrIndices ::= TOKEN_SQUARE_OPEN ParseArguments ::= TOKEN_ROUND_OPEN

// // tokens //

TOKEN_NULL ::= "null" TOKEN_TRUE ::= "true" TOKEN_FALSE ::= "false" TOKEN_VOID ::= "void" TOKEN_MUT ::= "mut" TOKEN_REQUIRES ::= "requires" TOKEN_NAMESPACE ::= "namespace" TOKEN_VAR ::= "var" TOKEN_CONST ::= "const" TOKEN_TYPE ::= "type" TOKEN_MAP ::= "map" TOKEN_WEAK ::= "weak" TOKEN_INT8 ::= "i8" TOKEN_INT16 ::= "i16" TOKEN_INT32 ::= "i32" TOKEN_INT64 ::= "i64" TOKEN_UINT8 ::= "u8" TOKEN_UINT16 ::= "u16" TOKEN_UINT32 ::= "u32" TOKEN_UINT64 ::= "u64" TOKEN_FLOAT32 ::= "f32" TOKEN_FLOAT64 ::= "f64" TOKEN_COMPLEX64 ::= "c64" TOKEN_COMPLEX128 ::= "c128" TOKEN_LET ::= "let" TOKEN_STRING ::= "string" TOKEN_BOOL ::= "bool" TOKEN_FUNC ::= "fn" TOKEN_PURE ::= "pure" TOKEN_IN ::= "in" TOKEN_OUT ::= "out" TOKEN_IO ::= "io" TOKEN_DOUBLEDOT ::= ".." TOKEN_ETC ::= "..." TOKEN_IF ::= "if" TOKEN_ELSE ::= "else" TOKEN_WHILE ::= "while" TOKEN_FOR ::= "for" TOKEN_RETURN ::= "return" TOKEN_BREAK ::= "break" TOKEN_CONTINUE ::= "continue" TOKEN_SIZEOF ::= "sizeof" TOKEN_XOR ::= "^" TOKEN_CASE ::= "case" TOKEN_TYPESWITCH ::= "typeswitch" TOKEN_SWITCH ::= "switch" TOKEN_DEFAULT ::= "default" TOKEN_PUBLIC ::= "public" TOKEN_PRIVATE ::= "private" TOKEN_ENUM ::= "enum" TOKEN_CLASS ::= "class" TOKEN_THIS ::= "this" TOKEN_INTERFACE ::= "interface" TOKEN_BY ::= "by" TOKEN_STEP ::= "step" TOKEN_MIN ::= "min" TOKEN_MAX ::= "max" TOKEN_SWAP ::= "swap" TOKEN_ROUND_OPEN ::= "(" TOKEN_ROUND_CLOSE ::= ")" TOKEN_SQUARE_OPEN ::= "[" TOKEN_SQUARE_CLOSE ::= "]" TOKEN_CURLY_OPEN ::= "{" TOKEN_CURLY_CLOSE ::= "}" TOKEN_ANGLE_OPEN_LT ::= "<" TOKEN_ANGLE_CLOSE_GT ::= ">" TOKEN_COMMA ::= "," TOKEN_ASSIGN ::= "=" TOKEN_INC ::= "++" TOKEN_DEC ::= "--" TOKEN_DOT ::= "." TOKEN_PLUS ::= "+" TOKEN_MINUS ::= "-" TOKEN_MPY ::= "" TOKEN_DIVIDE ::= "/" TOKEN_MOD ::= "%" TOKEN_SHR ::= ">>" TOKEN_SHL ::= "<<" TOKEN_NOT ::= "~" TOKEN_AND ::= "&" TOKEN_OR ::= "|" TOKEN_GTE ::= ">=" TOKEN_LTE ::= "<=" TOKEN_DIFFERENT ::= "!=" TOKEN_EQUAL ::= "==" TOKEN_LOGICAL_NOT ::= "!" TOKEN_LOGICAL_AND ::= "&&" TOKEN_LOGICAL_OR ::= "||" TOKEN_COLON ::= ":" TOKEN_SEMICOLON ::= ";" TOKEN_UPD_PLUS ::= "+=" TOKEN_UPD_MINUS ::= "-=" TOKEN_UPD_MPY ::= "=" TOKEN_UPD_DIVIDE ::= "/=" TOKEN_UPD_XOR ::= "^=" TOKEN_UPD_MOD ::= "%=" TOKEN_UPD_SHR ::= ">>=" TOKEN_UPD_SHL ::= "<<=" TOKEN_UPD_AND ::= "&=" TOKEN_UPD_OR ::= "|="

Parser so far on variant of https://github.com/mingodad/CocoR-CPP:

/* ANSI C 89 grammar as specified in http://flash-gordon.me.uk/ansi.c.txt

Processing the C grammar requires LL(1) conflict resolvers, some of which need to check whether an identifier is a type name (see IsTypeName() below). So the grammar assumes that there is a symbol table, from where you can look up an identifier and find out whether it is a type name.

The language in the semantic actions here is C#, but it can easily be translated to any other language. */

$namespace=Sing

ifdef SQUILU

include "Scanner.nut"

typedef SymTab SymTab;

else

include "Scanner.h"

endif

COMPILER Sing

CHARACTERS letter = 'A'..'Z' + 'a'..'z' + '_'. oct = '0'..'7'. digit = '0'..'9'. nzdigit = '1'..'9'. hex = digit + 'a'..'f' + 'A'..'F'. notQuote = ANY - '"' - "\r\n". notApo = ANY - '\'' - "\r\n".

tab = '\t'. cr = '\r'. lf = '\n'. newLine = cr + lf. notNewLine = ANY - newLine . ws = " " + tab + '\u000b' + '\u000c'.

TOKENS TOKEN_NAME = letter {letter | digit}.

floatcon = ( '.' digit {digit} [('e'|'E') ['+'|'-'] digit {digit}] | digit {digit} '.' {digit} [('e'|'E') ['+'|'-'] digit {digit}] | digit {digit} ('e'|'E') ['+'|'-'] digit {digit} ) ['f'|'l'|'F'|'L'].

intcon = ( nzdigit {digit} | '0' {oct} | ("0x"|"0X") hex {hex} ) {'u'|'U'|'l'|'L'}.

TOKEN_LITERAL_STRING = '"' {notQuote} '"'. // no check for valid escape sequences

charcon = '\'' notApo {notApo} '\''. // no check for valid escape sequences

// tokens defined in order to get their names for LL(1) conflict resolvers //{([^,]+),\s*("[^"]+").+ TOKEN_NULL = "null" . TOKEN_TRUE = "true" . TOKEN_FALSE = "false" . TOKEN_VOID = "void" .

TOKEN_MUT = "mut" . TOKEN_REQUIRES = "requires" . TOKEN_NAMESPACE = "namespace" . TOKEN_VAR = "var" . TOKEN_CONST = "const" . TOKEN_TYPE = "type" . TOKEN_MAP = "map" . TOKEN_WEAK = "weak" . TOKEN_INT8 = "i8" . TOKEN_INT16 = "i16" . TOKEN_INT32 = "i32" . TOKEN_INT64 = "i64" . TOKEN_UINT8 = "u8" . TOKEN_UINT16 = "u16" . TOKEN_UINT32 = "u32" . TOKEN_UINT64 = "u64" . TOKEN_FLOAT32 = "f32" . TOKEN_FLOAT64 = "f64" . TOKEN_COMPLEX64 = "c64" . TOKEN_COMPLEX128 = "c128" . TOKEN_LET = "let" . TOKEN_STRING = "string" . TOKEN_BOOL = "bool" .

TOKEN_FUNC = "fn" . TOKEN_PURE = "pure" . TOKEN_IN = "in" . TOKEN_OUT = "out" . TOKEN_IO = "io" . TOKEN_DOUBLEDOT = ".." . TOKEN_ETC = "..." . TOKEN_IF = "if" . TOKEN_ELSE = "else" . TOKEN_WHILE = "while" . TOKEN_FOR = "for" . TOKEN_RETURN = "return" . TOKEN_BREAK = "break" . TOKEN_CONTINUE = "continue" .

TOKEN_SIZEOF = "sizeof" . TOKEN_XOR = "^" . TOKEN_CASE = "case" . TOKEN_TYPESWITCH = "typeswitch" . TOKEN_SWITCH = "switch" . TOKEN_DEFAULT = "default" .

TOKEN_PUBLIC = "public" . TOKEN_PRIVATE = "private" . TOKEN_ENUM = "enum" . TOKEN_CLASS = "class" . TOKEN_THIS = "this" . TOKEN_INTERFACE = "interface" . TOKEN_BY = "by" . TOKEN_STEP = "step" . TOKEN_MIN = "min" . TOKEN_MAX = "max" . TOKEN_SWAP = "swap" .

TOKEN_ROUND_OPEN = "(" . TOKEN_ROUND_CLOSE = ")" . TOKEN_SQUARE_OPEN = "[" . TOKEN_SQUARE_CLOSE = "]" . TOKEN_CURLY_OPEN = "{" . TOKEN_CURLY_CLOSE = "}" . TOKEN_ANGLE_OPEN_LT = "<" . TOKEN_ANGLE_CLOSE_GT = ">" .

TOKEN_COMMA = "," . TOKEN_ASSIGN = "=" . TOKEN_INC = "++" . TOKEN_DEC = "--" . TOKEN_DOT = "." . TOKEN_PLUS = "+" . TOKEN_MINUS = "-" . TOKEN_MPY = "*" . TOKEN_DIVIDE = "/" . //TOKEN_POWER = "**" . TOKEN_MOD = "%" . TOKEN_SHR = ">>" . TOKEN_SHL = "<<" . TOKEN_NOT = "~" . TOKEN_AND = "&" . TOKEN_OR = "|" . TOKEN_GTE = ">=" . TOKEN_LTE = "<=" . TOKEN_DIFFERENT = "!=" . TOKEN_EQUAL = "==" . TOKEN_LOGICAL_NOT = "!" . TOKEN_LOGICAL_AND = "&&" . TOKEN_LOGICAL_OR = "||" . TOKEN_COLON = ":" . TOKEN_SEMICOLON = ";" .

TOKEN_UPD_PLUS = "+=" . TOKEN_UPD_MINUS = "-=" . TOKEN_UPD_MPY = "*=" . TOKEN_UPD_DIVIDE = "/=" . TOKEN_UPD_XOR = "^=" . TOKEN_UPD_MOD = "%=" . TOKEN_UPD_SHR = ">>=" . TOKEN_UPD_SHL = "<<=" . TOKEN_UPD_AND = "&=" . TOKEN_UPD_OR = "|=" .

PRAGMAS //---- preprocessor commands (not handled here) ppDefine = '#' {ws} "define" {notNewLine} newLine. ppUndef = '#' {ws} "undef" {notNewLine} newLine. ppIf = '#' {ws} "if" {notNewLine} newLine. ppElif = '#' {ws} "elif" {notNewLine} newLine. ppElse = '#' {ws} "else" {notNewLine} newLine. ppEndif = '#' {ws} "endif" {notNewLine} newLine. ppInclude = '#' {ws} "include" {notNewLine} newLine. ppLine = '#' {ws} digit {digit} {notNewLine} newLine.

COMMENTS FROM "/" TO "/" COMMENTS FROM "//" TO lf

IGNORE tab + cr + lf

PRODUCTIONS

//---------- Compilation Unit ---------- Sing = [ParseNamespace] {ParseDependency} {ParseDeclaration} EOF .

ParseNamespace = TOKEN_NAMESPACE TOKEN_NAME {TOKEN_DOT TOKEN_NAME} TOKEN_SEMICOLON .

ParseDependency = TOKEN_REQUIRES TOKEN_LITERAL_STRING [TOKEN_COMMA TOKEN_NAME] TOKEN_SEMICOLON .

ParseDeclaration = [TOKEN_PUBLIC] ( ParseType | ParseVar | ParseConst | ParseFunctionDeclaration | ParseEnum | ParseInterface | ParseClass ) .

ParseType = TOKEN_TYPE TOKEN_NAME ParseTypeSpecification TOKEN_SEMICOLON .

ParseVar = TOKEN_VAR TOKEN_NAME [TOKEN_ASSIGN ParseIniter] TOKEN_SEMICOLON .

ParseConst = TOKEN_LET TOKEN_NAME [ParseTypeSpecification] TOKEN_ASSIGN ParseIniter TOKEN_SEMICOLON .

ParseFunctionDeclaration = TOKEN_FUNC TOKEN_NAME [TOKEN_DOT TOKEN_NAME] ParseFunctionType (TOKEN_SEMICOLON | ParseBlock) .

ParseBlock = TOKEN_CURLY_OPEN {ParseStatement} TOKEN_CURLY_CLOSE .

ParseStatement = ParseVar | ParseConst | ParseBlock | ParseWhile | ParseIf | ParseFor | ParseSwitch | ParseTypeSwitch | (TOKEN_BREAK | TOKEN_CONTINUE) TOKEN_SEMICOLON | TOKEN_RETURN [TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE] TOKEN_SEMICOLON | (TOKEN_INC | TOKEN_DEC) ParsePrefixExpression TOKEN_SEMICOLON | TOKEN_SWAP TOKEN_ROUND_OPEN ParsePrefixExpression TOKEN_COMMA ParsePrefixExpression TOKEN_ROUND_CLOSE TOKEN_SEMICOLON | ParseLeftTermStatement .

ParseWhile = TOKEN_WHILE TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock .

ParseIf = TOKEN_IF TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE ParseBlock [TOKEN_ELSE (ParseIf | ParseBlock)] .

ParseFor = TOKEN_FOR TOKEN_ROUND_OPEN TOKEN_NAME {TOKEN_COMMA TOKEN_NAME} TOKEN_IN ParseExpression [TOKEN_COLON ParseExpression [TOKEN_STEP ParseExpression]] TOKEN_ROUND_CLOSE ParseBlock .

ParseSwitch = TOKEN_SWITCH TOKEN_ROUND_OPEN ParseExpression TOKEN_ROUND_CLOSE TOKEN_CURLY_OPEN {ParseSwitchCase} [TOKEN_DEFAULT TOKEN_COLON ParseStatement] TOKEN_CURLY_CLOSE .

ParseSwitchCase = ParseCase {ParseCase} ParseStatement .

ParseCase = TOKEN_CASE ParseExpression TOKEN_COLON .

ParseTypeSwitch = TOKEN_TYPESWITCH TOKEN_ROUND_OPEN TOKEN_NAME TOKEN_ASSIGN ParseExpression TOKEN_ROUND_CLOSE TOKEN_CURLY_OPEN TOKEN_CURLY_CLOSE .

ParseTypeSwitchCase = ParseTypeCase {ParseTypeCase} ParseStatement .

ParseTypeCase = TOKEN_CASE ParseTypeSpecification TOKEN_COLON .

ParseLeftTermStatement = ParsePrefixExpression ( ( TOKEN_ASSIGN | TOKEN_UPD_PLUS | TOKEN_UPD_MINUS | TOKEN_UPD_MPY | TOKEN_UPD_DIVIDE | TOKEN_UPD_XOR | TOKEN_UPD_MOD | TOKEN_UPD_SHR | TOKEN_UPD_SHL | TOKEN_UPD_AND | TOKEN_UPD_OR ) ParseExpression | (TOKEN_INC | TOKEN_DEC)

) TOKEN_SEMICOLON .

ParseEnum = TOKEN_ENUM TOKEN_NAME TOKEN_CURLY_OPEN ParseEnumElement {TOKEN_COMMA ParseEnumElement} TOKEN_CURLY_CLOSE .

ParseEnumElement = TOKEN_NAME [TOKEN_ASSIGN ParseExpression] .

ParseInterface = TOKEN_INTERFACE TOKEN_NAME [TOKEN_COLON ParseNamedType {TOKEN_COMMA ParseNamedType}] TOKEN_CURLY_OPEN {TOKEN_FUNC [TOKEN_MUT] ParseFunctionType TOKEN_SEMICOLON} TOKEN_NAME TOKEN_CURLY_CLOSE .

ParseClass = TOKEN_CLASS TOKEN_NAME [TOKEN_COLON ParseNamedType [TOKEN_BY TOKEN_NAME] {TOKEN_COMMA ParseNamedType [TOKEN_BY TOKEN_NAME]}] .

ParseTypeSpecification = ( TOKEN_INT8 | TOKEN_INT16 | TOKEN_INT32 | TOKEN_INT64 | TOKEN_UINT8 | TOKEN_UINT16 | TOKEN_UINT32 | TOKEN_UINT64 | TOKEN_FLOAT32 | TOKEN_FLOAT64 | TOKEN_COMPLEX64 | TOKEN_COMPLEX128 | TOKEN_STRING | TOKEN_BOOL | TOKEN_VOID ) | ParseNamedType | TOKEN_MAP TOKEN_ROUND_OPEN ParseTypeSpecification TOKEN_ROUND_CLOSE ParseTypeSpecification | ParseIndices | [ TOKEN_CONST | TOKEN_WEAK ] TOKEN_MPY ParseTypeSpecification | ParseFunctionType .

ParseNamedType = TOKEN_NAME .

ParseIndices = ParseOneIndice {ParseOneIndice} .

ParseOneIndice = TOKEN_SQUARE_OPEN [ParseOneIndixeExpr {TOKEN_COMMA ParseOneIndixeExpr} ] TOKEN_SQUARE_CLOSE ParseTypeSpecification .

ParseOneIndixeExpr = ParseExpression | TOKEN_MPY .

ParseFunctionType = [TOKEN_PURE] ParseArgsDef ParseTypeSpecification .

ParseArgsDef = TOKEN_ROUND_OPEN [TOKEN_ETC | ParseSingleArgDef {TOKEN_COMMA ParseSingleArgDef}] TOKEN_ROUND_CLOSE .

ParseSingleArgDef = [ TOKEN_IN | TOKEN_OUT | TOKEN_IO ] TOKEN_NAME ParseTypeSpecification [TOKEN_ASSIGN ParseIniter] .

ParseIniter = [TOKEN_CURLY_OPEN ParseIniter {TOKEN_COMMA ParseIniter} TOKEN_CURLY_CLOSE] ParseExpression .

ParseExpression = ParsePrefixExpression .

ParsePrefixExpression = TOKEN_MINUS | TOKEN_PLUS | TOKEN_AND | TOKEN_NOT | TOKEN_LOGICAL_NOT | TOKEN_MPY | ParsePostfixExpression .

ParsePostfixExpression = ParseRangesOrIndices | TOKEN_DOT | ParseArguments .

ParseRangesOrIndices = TOKEN_SQUARE_OPEN .

ParseArguments = TOKEN_ROUND_OPEN .

END Sing.

— Reply to this email directly, view it on GitHub https://github.com/mdegirolami/sing/issues/3, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEWY54PILHZOQHBK5GNO2LDVDNFO7ANCNFSM5SQUUFPQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=icon Virus-free. www.avast.com https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=link <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>