forked from itycodes/shaderc
				
			
						commit
						0902762066
					
				| @ -0,0 +1 @@ | ||||
| /target | ||||
| @ -0,0 +1,7 @@ | ||||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 4 | ||||
| 
 | ||||
| [[package]] | ||||
| name = "shaderc" | ||||
| version = "0.1.0" | ||||
| @ -0,0 +1,6 @@ | ||||
| [package] | ||||
| name = "shaderc" | ||||
| version = "0.1.0" | ||||
| edition = "2024" | ||||
| 
 | ||||
| [dependencies] | ||||
| @ -0,0 +1,49 @@ | ||||
| use std::fmt::Write; | ||||
| pub mod parser; | ||||
| 
 | ||||
| fn main() { | ||||
|     let mut ops: Vec<(Option<String>, Vec<String>)> = Vec::new(); | ||||
|     
 | ||||
|     //    OpMemoryModel Logical GLSL450
 | ||||
|     //    OpEntryPoint Fragment %main "main"
 | ||||
|     //    OpExecutionMode %main OriginUpperLeft
 | ||||
|     //    OpSource GLSL 450
 | ||||
|     //    OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
 | ||||
|     //    OpSourceExtension "GL_GOOGLE_include_directive"
 | ||||
|     //    OpName %main "main"
 | ||||
|     //%void = OpTypeVoid
 | ||||
|     //%3 = OpTypeFunction %void
 | ||||
|     //%main = OpFunction %void None %3
 | ||||
|     //%5 = OpLabel
 | ||||
|     //    OpReturn
 | ||||
|     //    OpFunctionEnd
 | ||||
|     
 | ||||
|     ops.push((None, vec!["OpCapability".to_string(), "Shader".to_string()])); | ||||
|     ops.push((Some("%1".to_string()), vec!["OpExtInstImport".to_string(), "\"GLSL.std.450\"".to_string()])); | ||||
|     ops.push((None, vec!["OpMemoryModel".to_string(), "Logical".to_string(), "GLSL450".to_string()])); | ||||
|     ops.push((None, vec!["OpEntryPoint".to_string(), "Fragment".to_string(), "%main".to_string(), "\"main\"".to_string()])); | ||||
|     ops.push((None, vec!["OpExecutionMode".to_string(), "%main".to_string(), "OriginUpperLeft".to_string()])); | ||||
|     ops.push((None, vec!["OpSource".to_string(), "GLSL".to_string(), "450".to_string()])); | ||||
|     ops.push((None, vec!["OpSourceExtension".to_string(), "\"GL_GOOGLE_cpp_style_line_directive\"".to_string()])); | ||||
|     ops.push((None, vec!["OpSourceExtension".to_string(), "\"GL_GOOGLE_include_directive\"".to_string()])); | ||||
|     ops.push((None, vec!["OpName".to_string(), "%main".to_string(), "\"main\"".to_string()])); | ||||
|     ops.push((Some("%void".to_string()), vec!["OpTypeVoid".to_string()])); | ||||
|     ops.push((Some("%3".to_string()), vec!["OpTypeFunction".to_string(), "%void".to_string()])); | ||||
|     ops.push((Some("%main".to_string()), vec!["OpFunction".to_string(), "%void".to_string(), "None".to_string(), "%3".to_string()])); | ||||
|     ops.push((Some("%5".to_string()), vec!["OpLabel".to_string()])); | ||||
|     ops.push((None, vec!["OpReturn".to_string()])); | ||||
|     ops.push((None, vec!["OpFunctionEnd".to_string()])); | ||||
|     
 | ||||
|     let mut out: String = String::new(); | ||||
| 
 | ||||
|     for op in ops { | ||||
|         if op.0.is_some() { | ||||
|             write!(out, "{} = ", op.0.unwrap()).unwrap(); | ||||
|         } | ||||
|         for arg in op.1 { | ||||
|             write!(out, "{} ", arg).unwrap(); | ||||
|         } | ||||
|         writeln!(out).unwrap(); | ||||
|     } | ||||
|     println!("{}", out); | ||||
| } | ||||
| @ -0,0 +1,68 @@ | ||||
| #[cfg(test)] | ||||
| mod tests; | ||||
| 
 | ||||
| use std::iter::Peekable; | ||||
| use std::vec::IntoIter; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum Token { | ||||
|     LeftParen, | ||||
|     RightParen, | ||||
|     Symbol(String), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum Ast { | ||||
|     Symbol(String), | ||||
|     List(Vec<Ast>), | ||||
|     Root(Vec<Ast>), | ||||
| } | ||||
| 
 | ||||
| pub fn tokenize(input: &str) -> Vec<Token> { | ||||
|     let mut tokens = Vec::new(); | ||||
|     let mut chars = input.chars().peekable(); | ||||
|     while let Some(c) = chars.next() { | ||||
|         match c { | ||||
|             '(' => tokens.push(Token::LeftParen), | ||||
|             ')' => tokens.push(Token::RightParen), | ||||
|             _ if c.is_whitespace() => (), | ||||
|             _ => { | ||||
|                 let mut symbol = c.to_string(); | ||||
|                 while let Some(&c) = chars.peek() { | ||||
|                     if c.is_whitespace() || c == '(' || c == ')' { | ||||
|                         break; | ||||
|                     } | ||||
|                     symbol.push(c); | ||||
|                     chars.next(); | ||||
|                 } | ||||
|                 tokens.push(Token::Symbol(symbol)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     tokens | ||||
| } | ||||
| 
 | ||||
| fn parse_expr(tokens: &mut Peekable<IntoIter<Token>>) -> Ast { | ||||
|     match tokens.next() { | ||||
|         Some(Token::LeftParen) => { | ||||
|             let mut list = Vec::new(); | ||||
|             while tokens.peek() != Some(&Token::RightParen) { | ||||
|                 list.push(parse_expr(tokens)); | ||||
|             } | ||||
|             tokens.next(); | ||||
|             Ast::List(list) | ||||
|         } | ||||
|         Some(Token::RightParen) => panic!("unexpected )"), | ||||
|         Some(Token::Symbol(s)) => Ast::Symbol(s), | ||||
|         None => panic!("unexpected EOF"), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn parse(tokens: Vec<Token>) -> Ast { | ||||
|     let mut tokens = tokens.into_iter().peekable(); | ||||
|     let mut ast: Vec<Ast> = Vec::new(); | ||||
|     while tokens.peek().is_some() { | ||||
|         ast.push(parse_expr(&mut tokens)); | ||||
|     } | ||||
|     Ast::Root(ast) | ||||
| } | ||||
| @ -0,0 +1,125 @@ | ||||
| use crate::parser::{tokenize, parse, Token, Ast}; | ||||
| 
 | ||||
| #[test] | ||||
| fn test_tokenize() { | ||||
|     let input = "(+ (* 1:u8 2) 2)"; | ||||
|     let expected = vec![ | ||||
|         Token::LeftParen, | ||||
|         Token::Symbol("+".to_string()), | ||||
|         Token::LeftParen, | ||||
|         Token::Symbol("*".to_string()), | ||||
|         Token::Symbol("1:u8".to_string()), | ||||
|         Token::Symbol("2".to_string()), | ||||
|         Token::RightParen, | ||||
|         Token::Symbol("2".to_string()), | ||||
|         Token::RightParen, | ||||
|     ]; | ||||
|     assert_eq!(tokenize(input), expected); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn test_parse() { | ||||
|     let src = " | ||||
| (module Shader Logical GLSL450) | ||||
| (import :std GLSL.std.450) | ||||
| (bind (frag-coord:*vec4fi) (Builtin FragCoord)) | ||||
| (bind (out-color:*vec4fo) (Location 0)) | ||||
| (dec frag-coord:*vec4fi Input) | ||||
| (dec out-color:*vec4fo Output) | ||||
| (entry main Fragment OriginUpperLeft (:frag-coord :out-color)) | ||||
| (fun (main) | ||||
|   (store-ptr (out-color) | ||||
|     (vec4fi (/ (.xy (load-ptr frag-coord)) | ||||
|                (vec2f 1920.0 1080.0)) 
 | ||||
|             1.0 
 | ||||
|             1.0))) | ||||
| "; | ||||
|     let ast = parse(tokenize(src)); | ||||
|     println!("{:?}", ast); | ||||
|     let test_ast: Ast = Ast::Root(vec![ | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("module".to_string()), | ||||
|             Ast::Symbol("Shader".to_string()), | ||||
|             Ast::Symbol("Logical".to_string()), | ||||
|             Ast::Symbol("GLSL450".to_string()), | ||||
|         ]), | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("import".to_string()), | ||||
|             Ast::Symbol(":std".to_string()), | ||||
|             Ast::Symbol("GLSL.std.450".to_string()), | ||||
|         ]), | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("bind".to_string()), | ||||
|             Ast::List(vec![ | ||||
|                 Ast::Symbol("frag-coord:*vec4fi".to_string()), | ||||
|             ]), | ||||
|             Ast::List(vec![ | ||||
|                 Ast::Symbol("Builtin".to_string()), | ||||
|                 Ast::Symbol("FragCoord".to_string()), | ||||
|             ]), | ||||
|         ]), | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("bind".to_string()), | ||||
|             Ast::List(vec![ | ||||
|                 Ast::Symbol("out-color:*vec4fo".to_string()), | ||||
|             ]), | ||||
|             Ast::List(vec![ | ||||
|                 Ast::Symbol("Location".to_string()), | ||||
|                 Ast::Symbol("0".to_string()), | ||||
|             ]), | ||||
|         ]), | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("dec".to_string()), | ||||
|             Ast::Symbol("frag-coord:*vec4fi".to_string()), | ||||
|             Ast::Symbol("Input".to_string()), | ||||
|         ]), | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("dec".to_string()), | ||||
|             Ast::Symbol("out-color:*vec4fo".to_string()), | ||||
|             Ast::Symbol("Output".to_string()), | ||||
|         ]), | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("entry".to_string()), | ||||
|             Ast::Symbol("main".to_string()), | ||||
|             Ast::Symbol("Fragment".to_string()), | ||||
|             Ast::Symbol("OriginUpperLeft".to_string()), | ||||
|             Ast::List(vec![ | ||||
|                 Ast::Symbol(":frag-coord".to_string()), | ||||
|                 Ast::Symbol(":out-color".to_string()), | ||||
|             ]), | ||||
|         ]), | ||||
|         Ast::List(vec![ | ||||
|             Ast::Symbol("fun".to_string()), | ||||
|             Ast::List(vec![ | ||||
|                 Ast::Symbol("main".to_string()), | ||||
|             ]), | ||||
|             Ast::List(vec![ | ||||
|                 Ast::Symbol("store-ptr".to_string()), | ||||
|                 Ast::List(vec![ | ||||
|                     Ast::Symbol("out-color".to_string()), | ||||
|                 ]), | ||||
|                 Ast::List(vec![ | ||||
|                     Ast::Symbol("vec4fi".to_string()), | ||||
|                     Ast::List(vec![ | ||||
|                         Ast::Symbol("/".to_string()), | ||||
|                         Ast::List(vec![ | ||||
|                             Ast::Symbol(".xy".to_string()), | ||||
|                             Ast::List(vec![ | ||||
|                                 Ast::Symbol("load-ptr".to_string()), | ||||
|                                 Ast::Symbol("frag-coord".to_string()), | ||||
|                             ]), | ||||
|                         ]), | ||||
|                         Ast::List(vec![ | ||||
|                             Ast::Symbol("vec2f".to_string()), | ||||
|                             Ast::Symbol("1920.0".to_string()), | ||||
|                             Ast::Symbol("1080.0".to_string()), | ||||
|                         ]), | ||||
|                     ]), | ||||
|                     Ast::Symbol("1.0".to_string()), | ||||
|                     Ast::Symbol("1.0".to_string()), | ||||
|                 ]), | ||||
|             ]), | ||||
|         ]), | ||||
|     ]); | ||||
|     assert_eq!(ast, test_ast); | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue