Initial Commit.
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
bin/
|
||||
env.sh
|
||||
.vscode/
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "../../Headers/scc_core.h"
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user