mirror of
https://github.com/RubyMetric/chsrc
synced 2025-07-18 22:04:52 +08:00
Implement Generator
for rawstr4c
This commit is contained in:
parent
964fea4e11
commit
033f93b620
@ -13,7 +13,7 @@ unit module CGenerator;
|
|||||||
|
|
||||||
use ConfigParser;
|
use ConfigParser;
|
||||||
|
|
||||||
class CharConverter {
|
class CStringConverter {
|
||||||
|
|
||||||
method convert-char($char, $mode) {
|
method convert-char($char, $mode) {
|
||||||
given $mode {
|
given $mode {
|
||||||
@ -41,7 +41,7 @@ class CharConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
method convert-content($content, $mode) {
|
method convert-string($content, $mode) {
|
||||||
my $result = "";
|
my $result = "";
|
||||||
for $content.comb -> $char {
|
for $content.comb -> $char {
|
||||||
$result ~= self.convert-char($char, $mode);
|
$result ~= self.convert-char($char, $mode);
|
||||||
@ -51,7 +51,7 @@ class CharConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class VariableNameGenerator {
|
class CVariableNameGenerator {
|
||||||
|
|
||||||
method generate($global-config, $section-config, $title) {
|
method generate($global-config, $section-config, $title) {
|
||||||
|
|
||||||
@ -92,3 +92,170 @@ class VariableNameGenerator {
|
|||||||
return $postfix.as-string();
|
return $postfix.as-string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#| 生成 .h 文件或/和 .c 文件,或存储到 @variables 中
|
||||||
|
class CVariableGenerator {
|
||||||
|
has @.variables;
|
||||||
|
has $.c-header-filename;
|
||||||
|
|
||||||
|
method new($c-header-filename = "rawstr4c.h") {
|
||||||
|
self.bless(:$c-header-filename, :variables([]));
|
||||||
|
}
|
||||||
|
|
||||||
|
method add-variable($name, $content, $type) {
|
||||||
|
@.variables.push: {
|
||||||
|
name => $name,
|
||||||
|
content => $content,
|
||||||
|
type => $type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
method generate-c-header-file($output-mode = 'global-variable') {
|
||||||
|
my $header = qq:to/EOF/;
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generated by rawstr4c
|
||||||
|
*
|
||||||
|
* Date: {DateTime.now.Str}
|
||||||
|
*/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for @.variables -> $var {
|
||||||
|
given $var<type> {
|
||||||
|
when 'global-variable' {
|
||||||
|
if $output-mode eq 'global-variable-only-header' {
|
||||||
|
$header ~= "char {$var<name>}[] = \"{$var<content>}\";\n";
|
||||||
|
} else {
|
||||||
|
$header ~= "extern char {$var<name>}[];\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when 'macro' {
|
||||||
|
$header ~= "#define {$var<name>.uc} \"{$var<content>}\"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $header;
|
||||||
|
}
|
||||||
|
|
||||||
|
method generate-c-source-file() {
|
||||||
|
my $source = qq:to/EOF/;
|
||||||
|
#include "{$.c-header-filename}"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generated by rawstr4c
|
||||||
|
*
|
||||||
|
* Date: {DateTime.now.Str}
|
||||||
|
*/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for @.variables -> $var {
|
||||||
|
if $var<type> eq 'global-variable' {
|
||||||
|
$source ~= "char {$var<name>}[] = \"{$var<content>}\";\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $source;
|
||||||
|
}
|
||||||
|
|
||||||
|
method save-files($output-mode) {
|
||||||
|
$.c-header-filename.IO.spurt(self.generate-c-header-file($output-mode));
|
||||||
|
say "Generated C header file: $.c-header-filename";
|
||||||
|
|
||||||
|
if $output-mode eq 'global-variable' {
|
||||||
|
my $has-globals = @.variables.grep({ $_<type> eq 'global-variable' }).elems > 0;
|
||||||
|
if $has-globals {
|
||||||
|
my $c-source-filename = $.c-header-filename.subst(/'.h'$/, '.c');
|
||||||
|
$c-source-filename.IO.spurt(self.generate-c-source-file());
|
||||||
|
say "Generated C source file: $c-source-filename";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Generator {
|
||||||
|
has $.cstring-converter;
|
||||||
|
has $.varname-generator;
|
||||||
|
has $.variable-generator;
|
||||||
|
|
||||||
|
method new($output-file = 'rawstr4c.h') {
|
||||||
|
self.bless(
|
||||||
|
:cstring-converter(CStringConverter.new()),
|
||||||
|
:varname-generator(CVariableNameGenerator.new()),
|
||||||
|
:variable-generator(CVariableGenerator.new($output-file))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
method get-config-value($global-config, $section-config, $key, $default = '') {
|
||||||
|
return $section-config.exist($key) ??
|
||||||
|
$section-config.get($key) !!
|
||||||
|
$global-config.get($key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
method generate-for-section($global-config, $section) {
|
||||||
|
my $section-config = $section<config>;
|
||||||
|
my $title = $section<title>;
|
||||||
|
my $code = $section<raw-string>;
|
||||||
|
|
||||||
|
return unless $code;
|
||||||
|
|
||||||
|
say "=== Section: $title ===";
|
||||||
|
|
||||||
|
my $translate-mode = self.get-config-value(
|
||||||
|
$global-config, $section-config, 'translate', ':escape'
|
||||||
|
).as-mode();
|
||||||
|
|
||||||
|
my $var-name = $.varname-generator.generate($global-config, $section-config, $title);
|
||||||
|
|
||||||
|
my $output-mode = $global-config.get('output', ':terminal').as-mode();
|
||||||
|
|
||||||
|
say "Variable name: $var-name";
|
||||||
|
say "Translation mode: $translate-mode";
|
||||||
|
say "Output mode: $output-mode";
|
||||||
|
|
||||||
|
my $language = $section-config.get('language', 'None').as-string();
|
||||||
|
say "Language: $language";
|
||||||
|
say '';
|
||||||
|
|
||||||
|
my $c-string = $.cstring-converter.convert-string($code, $translate-mode);
|
||||||
|
|
||||||
|
given $output-mode {
|
||||||
|
when 'terminal' {
|
||||||
|
say 'char ' ~ $var-name ~ '[] = "' ~ $c-string ~ '";';
|
||||||
|
}
|
||||||
|
when 'global-variable' | 'global-variable-only-header' {
|
||||||
|
$.variable-generator.add-variable($var-name, $c-string, 'global-variable');
|
||||||
|
}
|
||||||
|
when 'macro' {
|
||||||
|
$.variable-generator.add-variable($var-name, $c-string, 'macro');
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
die "Illegal output mode: $output-mode";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
say "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
method generate-all($parser) {
|
||||||
|
my $global-config = $parser.global-config;
|
||||||
|
|
||||||
|
# 这个 generate-for-section() 要么把变量输出到终端,要么累计到 @variabels 中
|
||||||
|
for $parser.sections -> $section {
|
||||||
|
self.generate-for-section($global-config, $section);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $output-mode = $global-config.get('output', ':terminal').as-mode();
|
||||||
|
|
||||||
|
# 最后把累计到 @variables 的内容输出到文件
|
||||||
|
if $output-mode ne 'terminal' {
|
||||||
|
$.variable-generator.save-files($output-mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user