Initial Commit.

This commit is contained in:
Creeper Lv
2026-05-26 16:59:39 +10:00
commit dee5b8dfb5
8 changed files with 286 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
bin/
env.sh
.vscode/
+62
View File
@@ -0,0 +1,62 @@
#ifndef __SCC_CORE_H_
#define __SCC_CORE_H_
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
typedef enum scc_target_language
{
c_language,
csharp,
} scc_target_language;
typedef struct scc_options
{
scc_target_language target_language;
char *header_output;
char *namespace_name;
char *class_name;
char *prefix;
char *data_type_name;
char *slex_namespace_name;
char *slex_class_name;
char *slex_prefix;
char *slex_data_type_name;
} scc_options;
typedef struct scc_matching
{
char **match_ids;
uint64_t match_ids;
char *target_syntax_id;
char **using_match_id;
uint64_t using_match_id_count;
} scc_matching;
typedef struct scc_rule
{
char *node_type_name;
scc_matching **matchings;
uint64_t matching_count;
} scc_rule;
typedef struct code_block
{
scc_target_language target_languge;
char *post_processor_code;
char *variables;
} code_block;
typedef struct scc_rules
{
scc_rule *rules;
uint64_t rule_count;
char **syntax_ids;
uint64_t syntax_id_count;
} scc_rules;
bool scc_read_rule_from_file(FILE *f, scc_rules *output_rule);
bool scc_read_rule_from_cstr(char *content, scc_rules *output_rule);
bool scc_translate_to_file_c(scc_options *options, scc_rules *rules, FILE *output_file);
bool scc_translate_to_file_csharp(scc_options *options, scc_rules *rules, FILE *output_file);
bool scc_translate_to_file(scc_options *options, scc_rules *rules, FILE *output_file);
#endif
+176
View File
@@ -0,0 +1,176 @@
# SCC
Simple Compiler-Compiler. This program is designed to generate a parser that builds a syntax tree using a rule file with `slex` lexer.
Currently, this project aims on supporting following target platform/languages:
|Language| Version| Platform|
|--------|--------|--------- |
|C | 99 | Win32, POSIX, ESP32 |
|C# | 9.0 | .netstandard2.1(all possible target platform, including Unity)|
## SCC Rule format
```
syntax_ids:
<id0>
<id1>
...
rules:
node_type
: [node_type/slex_id/slex_tag/direct_string] [node_type/slex_id/slex_tag/direct_string] ...
=> [operation] $0 $1 ...
: [node_type/slex_id/slex_tag/direct_string] [node_type/slex_id/slex_tag/direct_string] ...
=> [operation] $0 $1 ...
;
#
# $0 and $1 here means selected node/segment from matching element list.
#
```
### Operations
- `new_node <syntax-id>`: create a new node and attach to parent node
- `append_as_child`: append selected
- `skip`: do nothing
### Sample:
```
syntax_ids:
binary_expr
function_call_expr
argument_list
variable
rules:
expr
: expr binary_operator expr
=> new_node binary_expr $0 $1 $2
: name "(" argument_list ")"
=> new_node function_call_expr $0
| name
=> new_node variable $0
;
argument_list
:argument_list "," expr
=> append_as_child $2
:expr
=> new_node argument_list $0
;
```
## Usage
```
scc [options] <input_file> [options]
input file usually ends with `.scc`
Options:
-o <output> output file/output folder
-l <language> specify target language, e.g: c, c#, csharp
-h <header> output header file (will separate output implementation and definitions when language is c or c++. Note: c++ is currently not supported.)
-ns <namespace> specify namespace (supported languages only). Default is `scc_generated`, `SCCGenerated`, `io.creeperlv.scc.generated` for applicable language.
-class <class_name> specify class name (supported languages only). Default is `scc`, `SCC`.
-prefix <function_prefix> specify prefix for functions. Default is `scc_` for languages does not support namespace/class, `` (empty string) for languages support namespace/class.
-data_type <data_type_name> specify the name of the syntax node data type.
-slex-ns <namespace> specify namespace used in slex.
-slex-class <class_name> specify class name used in slex.
-slex-prefix <function_prefix> specify function prefix used in slex.
-slex-data_type <data_type_name> specify segment data type used in slex.
```
### Data Type Name Table
|Language | Type Name |
| ------- | ---------------- |
| C | scc_syntax_node |
| C# | SyntaxNode |
### Generated parser
All usages here uses default settings
#### C99
Usage sample:
```
void scc_sample(FILE* f, char* file_name){
struct slex_segment* head;
const char* str="<some_inputs>";
if(slex_file(f, file_name, &head)){
//Success
struct scc_syntax_node* root;
if(scc_parse(head,&root)){
//Success
}
}
slex_free(head);
}
```
API and defined data types:
```c
typedef struct scc_syntax_node_enclosure{
enum scc_syntax_node_type;
void* data;
}scc_syntax_node_enclosure;
typedef enum scc_syntax_node_type{
scc_node, scc_segment
}scc_syntax_node_type;
typedef struct scc_syntax_node{
enum scc_syntax_id;
char* syntax_name;
scc_syntax_node_enclosure* children;
uint64_t child_count;
scc_syntax_node* parent;
} scc_syntax_node;
typedef enum scc_syntax_id{
default,<generated from rule file>
}scc_syntax_id;
char scc_parse(slex_segment* head, scc_syntax_node** output);
char scc_free(scc_syntax_node* root);
```
#### C#
##### APIs:
```
using SLexGenerated;
namesapce SCCGenerated{
public class SCC{
public bool Parse(Segment head, out SyntaxNode Root);
}
public enum SyntaxId{
Default,<Generated-from-rule-file>
}
public class SyntaxNodeEnclosure{
public SyntaxNode? Node;
public Segment? Segment;
public EnclosureType EnclosureType;
}
public enum EnclosureType{
Node, Segment
}
public class SyntaxNode{
public SyntaxNode? Parent;
public string SyntaxName;
public SyntaxId Id;
public List<SyntaxNodeEnclosure> Children;
}
}
```
+6
View File
@@ -0,0 +1,6 @@
#include "../../../Headers/scc_core.h"
bool scc_translate_to_file_c(scc_options *options, scc_rules *rules, FILE *output_file){
//Stub for now.
return false;
}
+6
View File
@@ -0,0 +1,6 @@
#include "../../../Headers/scc_core.h"
bool scc_translate_to_file_csharp(scc_options *options, scc_rules *rules, FILE *output_file){
//Stub for now.
return false;
}
+7
View File
@@ -0,0 +1,7 @@
#include "../../Headers/scc_core.h"
int main(int ac, char **av)
{
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
#include "../Headers/scc_core.h"
bool scc_translate_to_file(scc_options *options, scc_rules *rules, FILE *output_file){
//Stub for now.
return false;
}
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh
mkdir -p ./bin/
if [ -f "./env.sh" ];
then
source ./env.sh
fi
if [ -z "$CC" ];
then
CC=cc
fi
if [ -z "$SKIP_EXE" ];
then
COMMAND="$CC ./Source/*.c ./Source/cli/*.c ./Source/Languages/*/*.c -o ./bin/scc"
echo "$COMMAND"
$COMMAND
fi