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