Skip to content

Commit

Permalink
Implement OpenQASM 3 lexer (#2129)
Browse files Browse the repository at this point in the history
This PR adds our own implementation of an OpenQASM3 parser to the `compiler/qsc_qasm3` directory.
  • Loading branch information
orpuente-MS authored Feb 2, 2025
1 parent 3b32013 commit f6725ef
Show file tree
Hide file tree
Showing 9 changed files with 3,509 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion compiler/qsc_qasm3/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ version.workspace = true

[dependencies]
bitflags = { workspace = true }
enum-iterator = { workspace = true }
num-bigint = { workspace = true }
miette = { workspace = true }
qsc_ast = { path = "../qsc_ast" }
Expand All @@ -20,7 +21,6 @@ thiserror = { workspace = true }
oq3_source_file = { workspace = true }
oq3_syntax = { workspace = true }
oq3_parser = { workspace = true }
oq3_lexer = { workspace = true }
oq3_semantics = { workspace = true }

[dev-dependencies]
Expand Down
104 changes: 104 additions & 0 deletions compiler/qsc_qasm3/src/keyword.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use enum_iterator::Sequence;
use std::{
fmt::{self, Display, Formatter},
str::FromStr,
};

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Sequence)]
pub enum Keyword {
Box,
Break,
Cal,
Case,
Continue,
Def,
Default,
Defcalgrammar,
Else,
End,
Extern,
For,
Gate,
If,
In,
Include,
Let,
OpenQASM,
Pragma,
Return,
Switch,
While,
}

impl Keyword {
pub(super) fn as_str(self) -> &'static str {
match self {
Keyword::Box => "box",
Keyword::Break => "break",
Keyword::Cal => "cal",
Keyword::Case => "case",
Keyword::Continue => "continue",
Keyword::Def => "def",
Keyword::Default => "default",
Keyword::Defcalgrammar => "defcalgrammar",
Keyword::Else => "else",
Keyword::End => "end",
Keyword::Extern => "extern",
Keyword::For => "for",
Keyword::Gate => "gate",
Keyword::If => "if",
Keyword::In => "in",
Keyword::Include => "include",
Keyword::Let => "let",
Keyword::OpenQASM => "openqasm",
Keyword::Pragma => "pragma",
Keyword::Return => "return",
Keyword::Switch => "switch",
Keyword::While => "while",
}
}
}

impl Display for Keyword {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(self.as_str())
}
}

impl FromStr for Keyword {
type Err = ();

// This is a hot function. Use a match expression so that the Rust compiler
// can optimize the string comparisons better, and order the cases by
// frequency in Q# so that fewer comparisons are needed on average.
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"box" => Ok(Self::Box),
"break" => Ok(Self::Break),
"cal" => Ok(Self::Cal),
"case" => Ok(Self::Case),
"continue" => Ok(Self::Continue),
"def" => Ok(Self::Def),
"default" => Ok(Self::Default),
"defcalgrammar" => Ok(Self::Defcalgrammar),
"else" => Ok(Self::Else),
"end" => Ok(Self::End),
"extern" => Ok(Self::Extern),
"for" => Ok(Self::For),
"gate" => Ok(Self::Gate),
"if" => Ok(Self::If),
"in" => Ok(Self::In),
"include" => Ok(Self::Include),
"let" => Ok(Self::Let),
"openqasm" => Ok(Self::OpenQASM),
"pragma" => Ok(Self::Pragma),
"return" => Ok(Self::Return),
"switch" => Ok(Self::Switch),
"while" => Ok(Self::While),
_ => Err(()),
}
}
}
51 changes: 51 additions & 0 deletions compiler/qsc_qasm3/src/lex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#![allow(unused)]

pub mod cooked;
pub mod raw;
use enum_iterator::Sequence;

pub(super) use cooked::{Error, Lexer, Token, TokenKind};

/// A delimiter token.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Sequence)]
pub enum Delim {
/// `{` or `}`
Brace,
/// `[` or `]`
Bracket,
/// `(` or `)`
Paren,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Sequence)]
pub enum Radix {
Binary,
Octal,
Decimal,
Hexadecimal,
}

impl From<Radix> for u32 {
fn from(value: Radix) -> Self {
match value {
Radix::Binary => 2,
Radix::Octal => 8,
Radix::Decimal => 10,
Radix::Hexadecimal => 16,
}
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Sequence)]
pub enum InterpolatedStart {
DollarQuote,
RBrace,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Sequence)]
pub enum InterpolatedEnding {
Quote,
LBrace,
}
Loading

0 comments on commit f6725ef

Please sign in to comment.