forked from itycodes/shaderc
				
			
						commit
						7a04fceedd
					
				@ -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