add: integer_node_parser

This commit is contained in:
jackfiled 2024-09-11 18:11:06 +08:00
parent 58e1e9c62c
commit e51d02dd6f
8 changed files with 221 additions and 5 deletions

View File

@ -1 +1,2 @@
pub mod tokenizer;
pub mod tokenizer;
pub mod parser;

3
src/parser.rs Normal file
View File

@ -0,0 +1,3 @@
mod syntax_tree;
mod grammar_parser;

View File

@ -0,0 +1,32 @@
use crate::parser::syntax_tree::SyntaxNode;
use crate::tokenizer::{LexicalTokenSpan, LexicalTokenType};
use nom::bytes::complete::tag;
use nom::combinator::map;
use nom::{IResult};
fn integer_node_parser(input: LexicalTokenSpan) -> IResult<LexicalTokenSpan, SyntaxNode> {
map(tag(LexicalTokenType::ConstInteger(0)),
|t: LexicalTokenSpan| {
if let LexicalTokenType::ConstInteger(number) = t.span[0].token_type {
SyntaxNode::const_integer(number, t)
} else {
panic!("Illegal integer constant: {}", t.as_str())
}
})(input)
}
#[cfg(test)]
mod test {
use super::*;
use crate::parser::syntax_tree::SyntaxNodeType;
use crate::tokenizer::lexical_parser;
#[test]
fn number_parser_test() {
let (_, input) = lexical_parser("123").unwrap();
dbg!(&input);
let (_, node) = integer_node_parser((&input).into()).unwrap();
assert_eq!(SyntaxNodeType::ConstIntegerNode(123), node.node_type);
}
}

22
src/parser/syntax_tree.rs Normal file
View File

@ -0,0 +1,22 @@
use crate::tokenizer::LexicalTokenSpan;
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum SyntaxNodeType {
ConstIntegerNode(u32),
ConstFloatNode(f32),
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SyntaxNode<'a> {
pub node_type: SyntaxNodeType,
pub lexical_tokens: LexicalTokenSpan<'a>
}
impl<'a> SyntaxNode<'a> {
pub fn const_integer(number: u32, span: LexicalTokenSpan<'a>) -> Self {
SyntaxNode {
node_type: SyntaxNodeType::ConstIntegerNode(number),
lexical_tokens: span
}
}
}

View File

@ -1,9 +1,10 @@
use nom::IResult;
use crate::tokenizer::parser::{combine_parser, junk_parser};
use crate::tokenizer::lexical_parser::{combine_parser, junk_parser};
mod parser;
mod lexical_parser;
mod lexical_token;
#[derive(PartialEq, Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone)]
pub enum LexicalTokenType {
Identifier,
ConstInteger(u32),
@ -19,6 +20,11 @@ pub struct LexicalToken<'a> {
pub literal_value: &'a str,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct LexicalTokenSpan<'a> {
pub span: &'a [LexicalToken<'a>]
}
pub fn lexical_parser(mut input: &str) -> IResult<&str, Vec<LexicalToken>> {
let mut array = vec![];

View File

@ -0,0 +1,143 @@
use crate::tokenizer::{LexicalToken, LexicalTokenSpan, LexicalTokenType};
use nom::{Compare, CompareResult, InputLength, InputTake};
impl<'a> LexicalTokenSpan<'a> {
pub fn new(span: &'a [LexicalToken]) -> Self {
Self {
span
}
}
}
impl<'a> From<&'a [LexicalToken<'a>]> for LexicalTokenSpan<'a> {
fn from(value: &'a [LexicalToken<'a>]) -> Self {
LexicalTokenSpan::new(value)
}
}
impl<'a> From<&'a Vec<LexicalToken<'a>>> for LexicalTokenSpan<'a> {
fn from(value: &'a Vec<LexicalToken<'a>>) -> Self {
LexicalTokenSpan::new(value.as_slice())
}
}
impl LexicalTokenSpan<'_> {
pub fn as_str(&self) -> &str {
self.span[0].literal_value
}
}
impl PartialEq for LexicalTokenType {
fn eq(&self, other: &Self) -> bool {
match self {
LexicalTokenType::ConstInteger(_) => {
match other {
LexicalTokenType::ConstInteger(_) => true,
_ => false
}
}
LexicalTokenType::ConstFloat(_) => {
match other {
LexicalTokenType::ConstFloat(_) => true,
_ => false
}
}
LexicalTokenType::Keyword => {
match other {
LexicalTokenType::Keyword => true,
_ => false
}
}
LexicalTokenType::Identifier => {
match other {
LexicalTokenType::Identifier => true,
_ => false
}
}
LexicalTokenType::Delimiter => {
match other {
LexicalTokenType::Delimiter => true,
_ => false
}
}
LexicalTokenType::Operator => {
match other {
LexicalTokenType::Operator => true,
_ => false
}
}
}
}
}
impl InputLength for LexicalTokenType {
fn input_len(&self) -> usize {
1
}
}
impl InputLength for LexicalToken<'_> {
fn input_len(&self) -> usize {
1
}
}
impl Compare<LexicalTokenType> for LexicalTokenSpan<'_> {
fn compare(&self, t: LexicalTokenType) -> CompareResult {
if self.span.is_empty() {
CompareResult::Incomplete
} else if self.span[0].token_type == t {
CompareResult::Ok
} else {
CompareResult::Error
}
}
fn compare_no_case(&self, t: LexicalTokenType) -> CompareResult {
self.compare(t)
}
}
impl<'a> Compare<LexicalToken<'a>> for LexicalTokenSpan<'a> {
fn compare(&self, t: LexicalToken) -> CompareResult {
if self.span.is_empty() {
CompareResult::Incomplete
} else if self.span[0] == t {
CompareResult::Ok
} else {
CompareResult::Error
}
}
fn compare_no_case(&self, t: LexicalToken) -> CompareResult {
self.compare(t)
}
}
impl InputTake for LexicalTokenSpan<'_> {
fn take(&self, count: usize) -> Self {
LexicalTokenSpan::new(&self.span[..count])
}
fn take_split(&self, count: usize) -> (Self, Self) {
let (prefix, suffix) = self.span.split_at(count);
// 先返回suffix再返回prefix
// 这TM谁能第一次写对
(LexicalTokenSpan::new(suffix), LexicalTokenSpan::new(prefix))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lexical_token_type_test() {
assert_eq!(LexicalTokenType::Identifier, LexicalTokenType::Identifier);
assert_eq!(LexicalTokenType::ConstInteger(1), LexicalTokenType::ConstInteger(2));
assert_eq!(LexicalTokenType::ConstFloat(3.0), LexicalTokenType::ConstFloat(3.0));
assert_ne!(LexicalTokenType::Identifier, LexicalTokenType::Keyword);
assert_ne!(LexicalTokenType::ConstInteger(1), LexicalTokenType::Operator);
}
}

View File

@ -14,10 +14,12 @@ fn validate_tokens(input: &'static str, tokens: Vec<LexicalTokenType>) {
#[test]
fn main_test() {
validate_tokens("int main { return 0; }", vec![
validate_tokens("int main() { return 0; }", vec![
Keyword,
Identifier,
Delimiter,
Delimiter,
Delimiter,
Keyword,
ConstInteger(0),
Delimiter,
@ -25,6 +27,13 @@ fn main_test() {
]);
}
#[test]
fn number_test() {
validate_tokens("123", vec![
ConstInteger(123)
])
}
#[test]
fn hexadecimal_test() {
validate_tokens("// test hexadecimal define