Converting the grammar of lucid to an EBNF understood by https://github.com/GuntherRademacher/rr we can have a nice navigable railroad diagram (see bellow with instructions at the top).
I also just added lucid to https://mingodad.github.io/parsertl-playground/playground/ an Yacc/Lex compatible online interpreter/editor (select Lucid-lang parser (partially working) from Examples then click Parse to see a parse tree for the content of Input source).
Notice that I have replaced the right recursion in rules by left recursion !!!
//
// EBNF to be viewd at
// (IPV6) https://www.bottlecaps.de/rr/ui
// (IPV4) https://rr.red-dove.com/ui
//
// Copy and paste this at one of the urls shown above in the 'Edit Grammar' tab
// then click the 'View Diagram' tab.
//
start_on ::= prog //to make easy navigate
ty::=
TINT single_poly
| TINT
| TBOOL
| QID
| AUTO
| cid
| cid poly
| cid ty_poly
| EVENT
| VOID
| GROUP
| MEMOP poly
| LBRACE record_def RBRACE
| ty LBRACKET size RBRACKET
| BITSTRING
tys::=
ty
| tys COMMA ty
cid::=
ID
| cid DOT ID
size::=
NUM
| ID
| QID
| AUTO
| size PLUS size
| LPAREN RPAREN
| LPAREN sizes RPAREN
sizes::=
size
| sizes COMMA size
polys::=
size
| polys COMMA size
poly::=
LESS polys MORE
single_poly::=
LESS size MORE
ty_or_empty_tuple::=
ty
| LPAREN RPAREN
ty_polys::=
ty_or_empty_tuple
| ty_polys COMMA ty_or_empty_tuple
ty_poly::=
LSHIFT ty_polys RSHIFT
paren_args::=
LPAREN RPAREN
| LPAREN args RPAREN
binop::=
exp PLUS exp
| exp SUB exp
| exp SATPLUS exp
| exp SATSUB exp
| exp LESS exp
| exp MORE exp
| exp LEQ exp
| exp GEQ exp
| exp AND exp
| exp OR exp
| exp EQ exp
| exp NEQ exp
| exp BITXOR exp
| exp BITAND exp
| exp PIPE exp
| exp CONCAT exp
| exp LSHIFT exp
| exp RSHIFT exp
| exp PATAND exp
| exp LESS UNORDERED MORE paren_args
pattern::=
cid
| NUM
| BITPAT
| cid paramsdef
| WILDCARD
patterns::=
pattern
| patterns COMMA pattern
exp::=
BITPAT
| WILDCARD
| cid
| NUMWITDH
| NUM
| TRUE
| FALSE
| cid paren_args
| binop
| NOT exp
| SUB exp
| BITNOT exp
| HASH single_poly LPAREN args RPAREN
| PATCAST LPAREN exp RPAREN
| LPAREN TINT single_poly RPAREN exp
| exp PROJ ID
| exp LBRACKET size COLON size RBRACKET
| LBRACE record_entries RBRACE
| LBRACE exp WITH record_entries RBRACE
| exp LBRACKET size RBRACKET
| LBRACKET exp FOR ID LESS size RBRACKET
| LBRACKET exps RBRACKET
| SIZECAST LPAREN size RPAREN
| SIZECAST single_poly LPAREN size RPAREN
| FLOOD exp
| LBRACE args RBRACE
| TABLE_CREATE LESS ty MORE LPAREN exp COMMA exp COMMA exp RPAREN
| TABLE_MATCH LPAREN exp COMMA exp COMMA exp RPAREN
| paren_exp
paren_exp::=
LPAREN args RPAREN
| LPAREN RPAREN
exps::=
exp
| exps SEMI exp
record_entry::=
ID ASSIGN exp
record_entries::=
record_entry
| record_entry SEMI
| record_entry SEMI record_entries
args::=
exp
| args COMMA exp
opt_args::=
LPAREN args RPAREN
| LPAREN RPAREN
paramsdef::=
LPAREN RPAREN
| LPAREN params RPAREN
event_sort::=
EVENT
| PACKET EVENT
speclist::=
cid LESS cid
| cid LEQ cid
| speclist cid LESS
| speclist cid LEQ
constr::=
speclist
| END cid
constrs::=
constr
| constrs SEMI constr
constr_list::=
LBRACKET RBRACKET
| LBRACKET constrs RBRACKET
interface_spec::=
FUN ty ID paramsdef SEMI
| FUN ty ID paramsdef constr_list SEMI
| CONSTR ty ID paramsdef SEMI
| ty ID SEMI
| EVENT ID paramsdef SEMI
| EVENT ID paramsdef constr_list SEMI
| SIZE ID SEMI
| MODULE ID COLON LBRACE interface RBRACE
| GLOBAL TYPE tyname_def ASSIGN ty
| GLOBAL TYPE tyname_def SEMI
| TYPE tyname_def ASSIGN ty
| TYPE tyname_def SEMI
interface::=
interface_spec
| interface_spec interface
event_decl::=
event_sort ID paramsdef
| event_sort ID paramsdef constr_list
| event_sort ID ANNOT paramsdef
| event_sort ID ANNOT paramsdef constr_list
handle_sort::=
HANDLE
| CONTROL HANDLE
| EGRESS HANDLE
tyname_def::=
ID
| ID poly
ty_args::=
LPAREN tys RPAREN
| LPAREN RPAREN
| ty
dt_table::=
ID ASSIGN LBRACE KEY_TYPE ty_args ARG_TYPE ty_args RET_TYPE ty RBRACE
lexp::=
cid
| lexp PROJ ID
parser_action::=
SKIP LPAREN ty COMMA exp RPAREN SEMI
| ty ID ASSIGN READ LPAREN exp RPAREN SEMI
| ty ID ASSIGN exp SEMI
| lexp ASSIGN exp SEMI
parser_branch::=
PIPE pattern ARROW LBRACE parser_block RBRACE
parser_branches::=
parser_branch
| parser_branches parser_branch
parser_step::=
GENERATE exp SEMI
| cid paren_args SEMI
| MATCH exp WITH parser_branches
| DROP SEMI
parser_block::=
parser_step
| parser_action parser_block
decl::=
CONST ty ID ASSIGN exp SEMI
| EXTERN ty ID SEMI
| EXTERN ID paramsdef SEMI
| SYMBOLIC ty ID SEMI
| event_decl SEMI
| event_decl LBRACE statement RBRACE
| handle_sort ID paramsdef LBRACE statement RBRACE
| FUN ty ID paramsdef LBRACE statement RBRACE
| FUN ty ID paramsdef constr_list LBRACE statement RBRACE
| MAIN decl
| ACTION_CONSTR ID paramsdef ASSIGN LBRACE RETURN ACTION ty ID paramsdef LBRACE statement RBRACE SEMI RBRACE SEMI
| ACTION ty ID paramsdef paramsdef LBRACE statement RBRACE
| MEMOP ID paramsdef LBRACE statement RBRACE
| SYMBOLIC SIZE ID SEMI
| SIZE ID ASSIGN size SEMI
| MODULE ID LBRACE decls RBRACE
| MODULE ID COLON LBRACE interface RBRACE LBRACE decls RBRACE
| MODULE ID ASSIGN cid IF exp ELSE cid SEMI
| TYPE tyname_def ASSIGN ty
| CONSTR ty ID paramsdef ASSIGN exp SEMI
| GLOBAL ty ID ASSIGN exp SEMI
| TABLE_TYPE dt_table
| PARSER ID paramsdef LBRACE parser_block RBRACE
decls::=
decl
| decls decl
param::=
ty ID
params::=
param
| params COMMA param
record_def::=
param SEMI
| record_def param SEMI
statement::=
statement0
| statement statement0
statement0::=
matched
| unmatched
| statement1
matched::=
IF LPAREN exp RPAREN LBRACE statement RBRACE ELSE LBRACE statement RBRACE
unmatched::=
IF LPAREN exp RPAREN LBRACE statement RBRACE ELSE unmatched
| IF LPAREN exp RPAREN LBRACE statement RBRACE
branch::=
PIPE patterns ARROW LBRACE statement RBRACE
branches::=
branch
| branches branch
table_entry::=
opt_args ARROW ID opt_args
| LBRACKET NUM RBRACKET opt_args ARROW ID opt_args
table_entries::=
table_entry
| table_entries SEMI table_entry
multiargs::=
exp COMMA args
statement1::=
SKIP SEMI
| ty ID ASSIGN exp SEMI
| NOINLINE ty ID ASSIGN exp SEMI
| ID ASSIGN exp SEMI
| NOINLINE ID ASSIGN exp SEMI
| RETURN SEMI
| RETURN exp SEMI
| GENERATE exp SEMI
| SGENERATE LPAREN exp COMMA exp RPAREN SEMI
| MGENERATE LPAREN exp COMMA exp RPAREN SEMI
| PGENERATE LPAREN exp COMMA exp RPAREN SEMI
| cid LESS UNORDERED MORE paren_args SEMI
| cid paren_args SEMI
| MATCH exp WITH branches
| MATCH multiargs WITH branches
| PRINTF LPAREN STRING RPAREN SEMI
| PRINTF LPAREN STRING COMMA args RPAREN SEMI
| FOR LPAREN ID LESS size RPAREN LBRACE statement RBRACE
| TABLE_MULTI_INSTALL LPAREN exp COMMA LBRACE table_entries RBRACE RPAREN SEMI
| TABLE_INSTALL LPAREN exp COMMA LBRACE table_entries RBRACE RPAREN SEMI
includes::=
/*%empty*/
| INCLUDE STRING
| includes INCLUDE STRING
prog::=
includes decls
| decls
//Tokens
INCLUDE ::= "include"
FALSE ::= "false"
TRUE ::= "true"
IF ::= "if"
ELSE ::= "else"
TINT ::= "int"
TBOOL ::= "bool"
EVENT ::= "event"
GENERATE ::= "generate"
SGENERATE ::= "generate_switch"
MGENERATE ::= "generate_ports"
PGENERATE ::= "generate_port"
PRINTF ::= "printf"
HANDLE ::= "handle"
FUN ::= "fun"
MEMOP ::= "memop"
MEMOP ::= "memop"
RETURN ::= "return"
SIZE ::= "size"
GLOBAL ::= "global"
UNORDERED ::= "unordered"
CONST ::= "const"
EXTERN ::= "extern"
VOID ::= "void"
HASH ::= "hash"
AUTO ::= "auto"
GROUP ::= "group"
CONTROL ::= "control"
EGRESS ::= "@egress"
ANNOT ::= "@" [0-9]+
MAIN ::= "@main"
PACKET ::= "packet"
MATCH ::= "match"
WITH ::= "with"
TYPE ::= "type"
NOINLINE ::= "noinline"
TABLE_TYPE ::= "table_type"
KEY_TYPE ::= "key_type:"
ARG_TYPE ::= "arg_type:"
RET_TYPE ::= "ret_type:"
ACTION_CONSTR ::= "action_constr"
ACTION ::= "action"
TABLE_CREATE ::= "table_create"
TABLE_MATCH ::= "table_match"
TABLE_INSTALL ::= "table_install"
TABLE_MULTI_INSTALL ::= "table_multi_install"
PARSER ::= "parser"
READ ::= "read"
SKIP ::= "skip"
DROP ::= "drop"
BITSTRING ::= "bitstring"
CONSTR ::= "constructor"
CONSTR ::= "constr"
MODULE ::= "module"
END ::= "end"
FOR ::= "for"
SIZECAST ::= "size_to_int"
SYMBOLIC ::= "symbolic"
FLOOD ::= "flood"
PATCAST ::= "int_to_pat"
PROJ ::= "#"
SATPLUS ::= "|+|"
PLUS ::= "+"
SATSUB ::= "|-|"
SUB ::= "-"
NOT ::= "!"
AND ::= "&&"
OR ::= "||"
BITAND ::= "&"
EQ ::= "=="
NEQ ::= "!="
LSHIFT ::= "<<"
RSHIFT ::= ">>"
LEQ ::= "<="
GEQ ::= ">="
LESS ::= "<"
MORE ::= ">"
BITXOR ::= "^^"
CONCAT ::= "^"
BITNOT ::= "~"
SEMI ::= ";"
COLON ::= ":"
LPAREN ::= "("
RPAREN ::= ")"
ASSIGN ::= "="
LBRACE ::= "{"
RBRACE ::= "}"
LBRACKET ::= "["
RBRACKET ::= "]"
COMMA ::= ","
DOT ::= "."
PIPE ::= "|"
ARROW ::= "->"
PATAND ::= "&&&"
WILDCARD ::= "_"
ID ::= [A-Za-z_][A-Za-z0-9_]*
QID ::= ID ('.' ID)+
Converting the grammar of
lucidto anEBNFunderstood by https://github.com/GuntherRademacher/rr we can have a nice navigable railroad diagram (see bellow with instructions at the top).I also just added
lucidto https://mingodad.github.io/parsertl-playground/playground/ anYacc/Lexcompatible online interpreter/editor (selectLucid-lang parser (partially working)fromExamplesthen clickParseto see a parse tree for the content ofInput source).Notice that I have replaced the right recursion in rules by left recursion !!!