use logos::{Lexer, Logos};
#[derive(Logos, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[allow(non_camel_case_types)]
#[repr(u16)]
pub enum SyntaxKind {
#[regex(r"[ \t\r\n]+")]
WHITESPACE,
#[regex(r"//[^\r\n]*", allow_greedy = true)]
LINE_COMMENT,
#[regex(r"/\*([^*]|\*+[^*/])*\*+/")]
BLOCK_COMMENT,
#[regex(r"`(define|include|line|undef)", directive_line, priority = 20)]
DIRECTIVE,
#[regex(r"`(ifdef|ifndef|elsif|endif|else|if)", directive_line, priority = 20)]
COND_DIRECTIVE,
#[regex(r"[0-9][0-9_]*")]
INT_NUMBER,
#[regex(r"0[xX][0-9a-fA-F][0-9a-fA-F_]*")]
HEX_NUMBER,
#[regex(r"[0-9]+'([bB][01][01_]*|[dD][0-9][0-9_]*|[hH][0-9a-fA-F][0-9a-fA-F_]*)")]
VLOG_NUMBER,
#[regex(r#""([^"\\]|\\["\\])*""#)]
STRING_LITERAL,
#[regex(r"\\?[a-zA-Z_][a-zA-Z0-9_]*")]
IDENT,
#[regex(r"`[a-zA-Z_][a-zA-Z0-9_]*")]
MACRO_REF,
#[token("boolean")]
BOOLEAN_KW,
#[token("bit")]
BIT_KW,
#[token("longint")]
LONGINT_KW,
#[token("unsigned")]
UNSIGNED_KW,
#[token("string")]
STRING_KW,
#[token("accesstype")]
ACCESSTYPE_KW,
#[token("addressingtype")]
ADDRESSINGTYPE_KW,
#[token("onreadtype")]
ONREADTYPE_KW,
#[token("onwritetype")]
ONWRITETYPE_KW,
#[token("alias")]
ALIAS_KW,
#[token("external")]
EXTERNAL_KW,
#[token("internal")]
INTERNAL_KW,
#[token("addrmap")]
ADDRMAP_KW,
#[token("regfile")]
REGFILE_KW,
#[token("reg")]
REG_KW,
#[token("field")]
FIELD_KW,
#[token("mem")]
MEM_KW,
#[token("signal")]
SIGNAL_KW,
#[token("true")]
TRUE_KW,
#[token("false")]
FALSE_KW,
#[token("na")]
NA_KW,
#[token("rw")]
RW_KW,
#[token("wr")]
WR_KW,
#[token("r", priority = 3)]
R_KW,
#[token("w", priority = 3)]
W_KW,
#[token("rw1")]
RW1_KW,
#[token("w1")]
W1_KW,
#[token("rclr")]
RCLR_KW,
#[token("rset")]
RSET_KW,
#[token("ruser")]
RUSER_KW,
#[token("woset")]
WOSET_KW,
#[token("woclr")]
WOCLR_KW,
#[token("wot")]
WOT_KW,
#[token("wzs")]
WZS_KW,
#[token("wzc")]
WZC_KW,
#[token("wzt")]
WZT_KW,
#[token("wclr")]
WCLR_KW,
#[token("wset")]
WSET_KW,
#[token("wuser")]
WUSER_KW,
#[token("compact")]
COMPACT_KW,
#[token("regalign")]
REGALIGN_KW,
#[token("fullalign")]
FULLALIGN_KW,
#[token("hw")]
HW_KW,
#[token("sw")]
SW_KW,
#[token("posedge")]
POSEDGE_KW,
#[token("negedge")]
NEGEDGE_KW,
#[token("bothedge")]
BOTHEDGE_KW,
#[token("level")]
LEVEL_KW,
#[token("nonsticky")]
NONSTICKY_KW,
#[token("abstract")]
ABSTRACT_KW,
#[token("all")]
ALL_KW,
#[token("component")]
COMPONENT_KW,
#[token("componentwidth")]
COMPONENTWIDTH_KW,
#[token("constraint")]
CONSTRAINT_KW,
#[token("default")]
DEFAULT_KW,
#[token("enum")]
ENUM_KW,
#[token("encode")]
ENCODE_KW,
#[token("inside")]
INSIDE_KW,
#[token("number")]
NUMBER_KW,
#[token("property")]
PROPERTY_KW,
#[token("ref")]
REF_KW,
#[token("struct")]
STRUCT_KW,
#[token("this")]
THIS_KW,
#[token("type")]
TYPE_KW,
#[token("alternate")]
ALTERNATE_KW,
#[token("byte")]
BYTE_KW,
#[token("int")]
INT_KW,
#[token("precedencetype")]
PRECEDENCETYPE_KW,
#[token("real")]
REAL_KW,
#[token("shortint")]
SHORTINT_KW,
#[token("shortreal")]
SHORTREAL_KW,
#[token("signed")]
SIGNED_KW,
#[token("with")]
WITH_KW,
#[token("within")]
WITHIN_KW,
#[token("+")]
PLUS,
#[token("-")]
MINUS,
#[token("!")]
BNOT,
#[token("~")]
NOT,
#[token("&&")]
BAND,
#[token("~&")]
NAND,
#[token("&")]
AND,
#[token("|")]
OR,
#[token("||")]
BOR,
#[token("~|")]
NOR,
#[token("^")]
XOR,
#[token("~^")]
#[token("^~")]
XNOR,
#[token("<<")]
LSHIFT,
#[token(">>")]
RSHIFT,
#[token("*")]
MULT,
#[token("**")]
EXP,
#[token("/")]
DIV,
#[token("%")]
MOD,
#[token("==")]
EQ,
#[token("=")]
ASSIGN,
#[token("!=")]
NEQ,
#[token("<=")]
LEQ,
#[token("<")]
LT,
#[token(">=")]
GEQ,
#[token(">")]
GT,
#[token("@")]
AT,
#[token("+=")]
INC,
#[token("%=")]
ALIGN,
#[token(";")]
SEMICOLON,
#[token("{")]
L_BRACE,
#[token("}")]
R_BRACE,
#[token("(")]
L_PAREN,
#[token(")")]
R_PAREN,
#[token("[")]
L_BRACK,
#[token("]")]
R_BRACK,
#[token("#")]
HASH,
#[token(",")]
COMMA,
#[token(".")]
DOT,
#[token(":")]
COLON,
#[token("::")]
DOUBLE_COLON,
#[token("->")]
ARROW,
#[token("?")]
QUESTION,
#[token("'")]
TICK,
LEX_ERROR,
EOF,
SOURCE_FILE,
COMPONENT_DEF,
COMPONENT_NAMED_DEF,
COMPONENT_ANON_DEF,
COMPONENT_BODY,
COMPONENT_TYPE,
COMPONENT_INST_TYPE,
COMPONENT_INSTS,
COMPONENT_INST,
COMPONENT_INST_ALIAS,
EXPLICIT_COMPONENT_INST,
FIELD_INST_RESET,
INST_ADDR_FIXED,
INST_ADDR_STRIDE,
INST_ADDR_ALIGN,
PARAM_DEF,
PARAM_DEF_ELEM,
PARAM_INST,
PARAM_ASSIGNMENT,
LOCAL_PROPERTY_ASSIGNMENT,
DYNAMIC_PROPERTY_ASSIGNMENT,
NORMAL_PROP_ASSIGN,
ENCODE_PROP_ASSIGN,
PROP_MOD_ASSIGN,
PROP_KEYWORD,
PROP_MOD,
UDP_DEF,
UDP_BODY,
UDP_TYPE,
UDP_DATA_TYPE,
UDP_USAGE,
UDP_COMP_TYPE,
UDP_DEFAULT,
UDP_CONSTRAINT,
ENUM_DEF,
ENUM_BODY,
ENUM_ENTRY,
ENUM_ENTRY_BODY,
ENUM_PROP_ASSIGN,
STRUCT_DEF,
STRUCT_BODY,
STRUCT_ELEM,
CONSTRAINT_DEF,
CONSTRAINT_NAMED_DEF,
CONSTRAINT_ANON_DEF,
CONSTRAINT_BODY,
CONSTRAINT_INSTS,
CONSTR_RELATIONAL,
CONSTR_PROP_ASSIGN,
CONSTR_INSIDE_VALUES,
CONSTR_INSIDE_ENUM,
CONSTR_LHS,
CONSTR_INSIDE_VALUE,
UNARY_EXPR,
BINARY_EXPR,
TERNARY_EXPR,
PAREN_EXPR,
CONCATENATE,
REPLICATE,
CAST_TYPE,
CAST_WIDTH,
MACRO_CALL,
LITERAL,
ARRAY_LITERAL,
STRUCT_LITERAL,
STRUCT_KV,
ENUM_LITERAL,
INSTANCE_REF,
INSTANCE_REF_ELEMENT,
PROP_REF,
DATA_TYPE,
BASIC_DATA_TYPE,
RANGE_SUFFIX,
ARRAY_SUFFIX,
ARRAY_TYPE_SUFFIX,
ERROR,
#[doc(hidden)]
__LAST,
}
impl SyntaxKind {
pub fn is_trivia(self) -> bool {
matches!(
self,
SyntaxKind::WHITESPACE | SyntaxKind::LINE_COMMENT | SyntaxKind::BLOCK_COMMENT
) || self.is_directive()
}
pub fn is_comment(self) -> bool {
matches!(self, SyntaxKind::LINE_COMMENT | SyntaxKind::BLOCK_COMMENT)
}
pub fn is_directive(self) -> bool {
matches!(self, SyntaxKind::DIRECTIVE | SyntaxKind::COND_DIRECTIVE)
}
pub fn is_keyword(self) -> bool {
SyntaxKind::BOOLEAN_KW <= self && self <= SyntaxKind::WITHIN_KW
}
pub fn is_ident_like(self) -> bool {
matches!(self, SyntaxKind::IDENT | SyntaxKind::MACRO_REF) || self.is_keyword()
}
pub fn from_raw(raw: u16) -> SyntaxKind {
assert!(raw < SyntaxKind::__LAST as u16, "invalid SyntaxKind: {raw}");
unsafe { std::mem::transmute::<u16, SyntaxKind>(raw) }
}
pub fn to_raw(self) -> u16 {
self as u16
}
}
fn directive_line(lex: &mut Lexer<SyntaxKind>) {
let rest = lex.remainder().as_bytes();
let mut i = 0;
while i < rest.len() {
match rest[i] {
b'\n' | b'\r' => break,
b'\\' => {
let mut j = i + 1;
if rest.get(j) == Some(&b'\r') {
j += 1;
}
if rest.get(j) == Some(&b'\n') {
i = j + 1;
} else {
i += 1;
}
}
_ => i += 1,
}
}
lex.bump(i);
}