diff --git a/rawstr4c/rawstr4c.raku b/rawstr4c/rawstr4c.raku index 2165bd2..4c23458 100644 --- a/rawstr4c/rawstr4c.raku +++ b/rawstr4c/rawstr4c.raku @@ -4,219 +4,46 @@ # File Authors : Aoran Zeng # Contributors : Nul None # Created On : <2025-07-12> -# Last Modified : <2025-07-12> +# Last Modified : <2025-07-13> # -# Generate raw strings for C programming language +# rawstr4c: # -# --------------------------------------------------------------- -# 全局设置称为 Global config,其他均称为 section config -# 每一部分称为 section,我们要处理的input,都在 code block 里,我们简称为 block +# Raw strings for C programming language +# +# Usage: +# rawstr4c # 指定具体某文件名 +# rawstr4c # 使用某一目录寻找 rawstr4c.md 文件 +# +# 要注意的是,该程序一次性只能处理唯一一个文件 # --------------------------------------------------------------- -unless @*ARGS { - die "Usage: rawstr4c \n"; -} +use Parser; +use Generator; -my $markdown-file = @*ARGS[0]; +sub MAIN( + Str $input-path, + Bool :$debug = False #= --debug +) { + my $markdown-file; -unless $markdown-file.IO.e { - die "Error: File '$markdown-file' not found.\n"; -} - -# 根据转换模式处理字符 -sub convert-char($char, $mode) { - given $mode { - when 'oct' { - my $bytes = $char.encode('UTF-8'); - return $bytes.map({ "\\" ~ sprintf("%03o", $_) }).join(''); - } - when 'hex' { - my $bytes = $char.encode('UTF-8'); - return $bytes.map({ "\\x" ~ sprintf("%02x", $_) }).join(''); - } - when 'escape' { - # 只转义必要的字符 - given $char { - when '"' { return '\\"'; } - when "'" { return "\\'"; } - when '\\' { return '\\\\'; } - when "\n" { return '\\n'; } - when "\t" { return '\\t'; } - when "\r" { return '\\r'; } - when "\0" { return '\\0'; } - default { return $char; } - } - } - default { - die "Unknown translation mode: $mode"; + if $input-path.IO.d { + $markdown-file = $input-path.IO.add("rawstr4c.md"); + unless $markdown-file.e { + die "Error: No 'rawstr4c.md' file found in directory '$input-path'\n"; } } -} - -# 处理字符串转换 -sub process-content($content, $mode) { - my $result = ""; - for $content.comb -> $char { - $result ~= convert-char($char, $mode); - } - return $result; -} - -# 生成变量名 -sub generate-variable-name($global-config, $section-config, $title) { - my $prefix = $global-config // "_rawstr4c"; - my $postfix = $global-config // ""; - - # 处理前缀 - $prefix = $prefix.subst(/^'`'/, '').subst(/'`'$/, ''); - - # 处理后缀 - if $postfix { - $postfix = $postfix.subst(/^':'/, ''); - if $section-config { - my $lang = $section-config.subst(/^'`'/, '').subst(/'`'$/, ''); - $postfix = $postfix.subst('use-language', "in_$lang"); - } else { - $postfix = $postfix.subst('use-language', ''); # 默认为无语言 - } - } - - # 生成的变量名称 - my $name = $section-config // $title.lc; - $name = $name.subst(/^'`'/, '').subst(/'`'$/, ''); - # 处理标题中包含的空格 - $name = $name.subst(/\s+/, '_', :g); - - my $var-name = $prefix; - if $name { - $var-name ~= "_" ~ $name; - } - - if $postfix { - $var-name ~= "_" ~ $postfix; - } - - return $var-name; -} - -#`( 真正的 main 流程开始 -) -my $content = $markdown-file.IO.slurp; -my @lines = $content.lines; - -my %global-config; -my @sections; -my $current-section; -my $in-global = True; -my $in-code-block = False; -my $current-code = ""; - -for @lines -> $line { - # 检查标题级别 (注意,要确保不在代码块内) - if !$in-code-block && $line ~~ /^ '#' ('#'*) \s* (.+) / { - my $level = 1 + $0.chars; - my $title = ~$1; - - # 如果之前有代码块,保存 - if $current-code && $current-section && $current-section { - $current-section<code> = $current-code; - @sections.push: $current-section; - } - - # 重置代码块 - $current-code = ""; - - # 一级标题后面是全局配置,其他级别标题开始新的section - if $level == 1 { - $in-global = True; - $current-section = {}; - } else { - $in-global = False; - $current-section = { - title => $title, - level => $level, - config => {}, - }; - } - next; - } - - # 解析配置项 - if $line ~~ /^ '-' \s* (<[a..z\-]>+) \s* '=' \s* '`' (.+?) '`' / { - my $key = ~$0; - my $value = ~$1; - - if $in-global { - %global-config{$key} = $value; - } elsif $current-section { - $current-section<config>{$key} = $value; - } - next; - } - - # 处理代码块,即真正想要转换的 raw string - # 检测代码块语言并记录 - if $line ~~ /^ '```' (.*)? / { - if $in-code-block { - # 代码块结束 - $in-code-block = False; - } else { - # 代码块开始,记录语言 - $in-code-block = True; - my $lang = ~($0 // ''); - if $lang && $current-section { - # 如果代码块指定了语言,且当前section没有language配置,则自动设置 - unless $current-section<config><language> { - $current-section<config><language> = $lang; - } - } - } - next; - } - - if $in-code-block { - $current-code ~= $line ~ "\n"; - } -} - -# 保存最后一个代码块 -if $current-code && $current-section && $current-section<title> { - $current-section<code> = $current-code; - @sections.push: $current-section; -} - -# 解析完毕,最后输出结果 -say "Global config:"; -for %global-config.kv -> $k, $v { - say " $k = $v"; -} -say ""; - -say "Found " ~ @sections.elems ~ " sections:"; -for @sections -> $section { - say "Section: " ~ $section<title>; -} -say ""; - -for @sections -> $section { - say "=== Section: " ~ $section<title> ~ " ==="; - - # 确定转换模式 (section config 优先,否则使用 global config) - my $translate = $section<config><translate> // %global-config<translate> // ':oct'; - $translate = $translate.subst(/^':'/, ''); - - # 生成变量名 - my $var-name = generate-variable-name(%global-config, $section<config>, $section<title>); - - say "Variable name: $var-name"; - say "Translation mode: $translate"; - - my $language = $section<config><language>; - say "Language: $language"; - - if $section<code> { - say ''; - say 'char ' ~ $var-name ~ '[] = "' ~ process-content($section<code>, $translate) ~ '";'; - } - say "\n"; + elsif $input-path.IO.f { + $markdown-file = $input-path.IO; + } else { + die "Error: '$input-path' is neither a file nor a directory\n"; + } + + my $content = $markdown-file.IO.slurp; + + my $parser = Parser::Parser.new(); + + $parser.parse($content); + $parser.debug if $debug; + + Generator::Generator.new.generate($parser); }