Skip to content

Commit

Permalink
Create rust.yml
Browse files Browse the repository at this point in the history
update rust token lexer
  • Loading branch information
limuy2022 committed Dec 31, 2023
1 parent 81aacc4 commit b2f9aaf
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 16 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Rust

on:
push:
branches: [ "master", "dev" ]
pull_request:
branches: [ "master", "dev" ]

env:
CARGO_TERM_COLOR: always

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: CD
run: cd rust
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
6 changes: 6 additions & 0 deletions rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@
Rust's modern and safe features make me very intesested in it and decided to learn it by developing this project.

So this is just an experimental project and I will keep develop c++ version and rust version(maybe more kinds of compilers developing by other languages will be added in future)

## Build

Like other common rust project.Just use ```cargo build```

Running tests is like other rust project,too.Just ```cargo test```
21 changes: 21 additions & 0 deletions rust/docs/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The usage of Rust version Trc

## First written value for Trc

you can write integer value in the following ways:
|Way|Explain|
|:---|:---|
|12321312|commom value|
|122_32432_4324324|use underline to split the number to read more easily|
|0b32132|number in 2 radix|
|0o324243|number in 8 radix|
|0x324324|number in 16 radix|

Tip:No matter how large is your number.Trc compiler will take it into enough type to store!Don't worry!

The next is the string value. To make you to write strings more easily:

|Way|Explain|
|:---|:---|
|"hello world"|commom value|
|"hello_world"|use underline to split the number to read more easily|
Empty file added rust/src/base.rs
Empty file.
Empty file added rust/src/base/error.rs
Empty file.
32 changes: 25 additions & 7 deletions rust/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
mod token;
use std::fs;

pub struct compiler {
input:fs::File
use std::io;
use std::collections::hash_set;

pub struct ConstPool {
const_ints: hash_set::HashSet<i32>,
}

impl ConstPool {
fn new() -> Self {
ConstPool {
const_ints: hash_set::HashSet::new(),
}
}
}

pub struct Compiler<T:io::Read> {
input:T,
line: usize,
const_pool: ConstPool
}

impl compiler {
fn new(f:fs::File) -> compiler {
compiler {
input:f
impl<T:io::Read> Compiler<T> {
fn new(f: T) -> Self {
Compiler {
input:f,
line:1,
const_pool: ConstPool::new(),
}
}
}
187 changes: 183 additions & 4 deletions rust/src/compiler/token.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,201 @@
enum TokenType {
use std::str::{Chars, CharIndices};

use super::Compiler;
use std::io;

#[derive(PartialEq, Debug)]
enum TokenType {
DOT,
COMMA,
INT_VALUE,
STRING_VALUE,
FLOAT_VALUE,
LONG_INT_VALUE,
LONG_FLOAT_VALUE
}

enum Data {

#[derive(PartialEq, Debug)]
pub enum Data {
Int(i32),
Str(String),
FLOAT(f64)
}

#[derive(PartialEq, Debug)]
struct Token {
tp:TokenType,
data:Data
}

struct TokenLex {

struct TokenLex<'code, T:io::Read> {
code: &'code str,
pos: CharIndices<'code>,
compiler_data:&'code mut Compiler<T>
}

impl Token {
fn new(tp:TokenType, data:Option<Data>) -> Token {
match data {
Some(data) => Token {
tp,
data
},
None => Token {
tp,
data:Data::Int(0)
}
}
}
}

impl<T:io::Read> Iterator for TokenLex<'_, T> {
type Item = Token;
fn next(&mut self) -> Option<Self::Item> {
self.next_token()
}
}

impl<T:io::Read> TokenLex<'_, T> {
fn new<'a>(code:&'a str, compiler_data:&'a mut Compiler<T>) -> TokenLex<'a, T> {
TokenLex {
code,
pos:code.char_indices(),
compiler_data
}
}

fn lex_symbol(&mut self, c:char) -> Token {
match c {
'.' => Token::new(TokenType::DOT, None),
',' => Token::new(TokenType::COMMA, None),
_ => panic!("Not a symbol.Compiler error")
}
}

fn lex_num(&mut self, c:char) -> Token {
// to save the int in str
let mut s = c.to_string();
// the radix of result
let mut radix = 10;
let mut presecnt_lex: Option<(usize, char)> = self.pos.next();
match presecnt_lex {
Some(c) => {
let c = c.1;
if c == '0' {
presecnt_lex = self.pos.next();
match presecnt_lex {
Some(c) => {
let c = c.1;
match c {
'x' | 'X' => {
s += "0x";
radix = 16;
},
'b' | 'B' => {
s += "0b";
radix = 2;
},
'o' | 'O' => {
s += "0o";
radix = 8;
},
_ => {}
}
},
None => {
return Token::new(TokenType::INT_VALUE, Some(Data::Int(0)));
}
}
}
},
None => {
panic!("Not a num.Compiler error");
}
}
loop {
match self.pos.next() {
None => {
break;
},
Some(c) => {
let c = c.1;
if c.is_digit(10) {
s.push(c);
} else {
self.pos.next_back();
break;
}
}
}
}
Token::new(TokenType::INT_VALUE, Some(Data::Int(s.parse().expect("wrong string to int"))))
}

fn next_token(&mut self) -> Option<Token> {
let mut presecnt_lex = self.pos.next();
loop {
presecnt_lex = self.pos.next();
match presecnt_lex {
Some(c) => {
let c = c.1;
if c == '\n' || c == '\t' || c == ' ' {
continue;
}
break;
},
None => {
return None;
}
}
}
let presecnt_lex = presecnt_lex.unwrap().1;
if presecnt_lex.is_digit(10) {
Some(self.lex_num(presecnt_lex));
}
Some(self.lex_symbol(presecnt_lex))
}
}

#[cfg(test)]
mod tests {
use super::*;

fn check<T:io::Read>(tokenlex:&mut TokenLex<T>, expected_res: Vec<Token>) {
for i in expected_res {
assert_eq!(i, tokenlex.next().unwrap());
}
assert_eq!(None, tokenlex.next());
}

#[test]
fn test_next_token() {
let mut env = Compiler::new(io::stdin());
let mut t = TokenLex::new(r#",,.,100
123.9 232_304904
0b011
0x2aA4
0o2434 0"#, &mut env);
let res = vec![Token::new(TokenType::COMMA, None),
Token::new(TokenType::COMMA, None),
Token::new(TokenType::DOT, None),
Token::new(TokenType::COMMA, None),
Token::new(TokenType::FLOAT_VALUE, Some(Data::FLOAT(123.9))),
Token::new(TokenType::INT_VALUE, Some(Data::Int(232_304904))),
Token::new(TokenType::INT_VALUE, Some(Data::Int(0b011))),
Token::new(TokenType::INT_VALUE, Some(Data::Int(0x2aA4))),
Token::new(TokenType::INT_VALUE, Some(Data::Int(0o2434))),
Token::new(TokenType::INT_VALUE, Some(Data::Int(0)))];
check(&mut t, res);
}

#[test]
#[should_panic]
fn test_token_wrong() {
let mut env = Compiler::new(io::stdin());
let t = TokenLex::new(r#"0xtghhy 0b231"#, &mut env);
for _ in t {}
}
}
1 change: 1 addition & 0 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

14 changes: 9 additions & 5 deletions rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
pub mod tools;
pub mod compiler;
pub mod base;

use std::io;
use rand::Rng;
use std::cmp::Ordering;
use std::env;
use std::env::args;
use std::process::exit;

fn main() {
let mode = args().nth(1).expect("a mode isn't given");
let mode:String = match args().nth(1) {
Some(tr) => tr,
_ => {
println!("A mode isn't given.");
exit(0);
},
};
if mode == "build" {
tools::compile();
} else if mode == "run" {
Expand Down
Empty file added rust/tests/test_compiler.rs
Empty file.

0 comments on commit b2f9aaf

Please sign in to comment.