mirror of
https://github.com/ValKmjolnir/Nasal-Interpreter.git
synced 2026-07-26 21:08:45 +08:00
update
This commit is contained in:
+46
-26
@@ -1,5 +1,26 @@
|
|||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
|
|
||||||
|
nasal_resource resource;
|
||||||
|
nasal_lexer lexer;
|
||||||
|
nasal_parse parse;
|
||||||
|
std::string command;
|
||||||
|
|
||||||
|
void help()
|
||||||
|
{
|
||||||
|
std::cout<<">> [\'file\'] input a file."<<std::endl;
|
||||||
|
std::cout<<">> [cls ] clear the screen."<<std::endl;
|
||||||
|
std::cout<<">> [del ] clear the resource code."<<std::endl;
|
||||||
|
std::cout<<">> [lib ] add lib file."<<std::endl;
|
||||||
|
std::cout<<">> [rs ] print resource code."<<std::endl;
|
||||||
|
std::cout<<">> [lex ] turn code into tokens."<<std::endl;
|
||||||
|
std::cout<<">> [par ] turn tokens into abstract syntax tree."<<std::endl;
|
||||||
|
std::cout<<">> [ast ] check the abstract syntax tree."<<std::endl;
|
||||||
|
std::cout<<">> [run ] run code."<<std::endl;
|
||||||
|
std::cout<<">> [logo ] print logo of nasal ."<<std::endl;
|
||||||
|
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void logo()
|
void logo()
|
||||||
{
|
{
|
||||||
std::cout<<" __ _ "<<std::endl;
|
std::cout<<" __ _ "<<std::endl;
|
||||||
@@ -10,9 +31,26 @@ void logo()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_resource resource;
|
void lex_func()
|
||||||
nasal_lexer lexer;
|
{
|
||||||
std::string command;
|
lexer.scanner(resource.get_file());
|
||||||
|
if(!lexer.get_error()) lexer.print_token();
|
||||||
|
else std::cout<<">> [lexer] error occurred,stop.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void par_func()
|
||||||
|
{
|
||||||
|
lexer.scanner(resource.get_file());
|
||||||
|
if(!lexer.get_error())
|
||||||
|
{
|
||||||
|
parse.set_toklist(lexer.get_token_list());
|
||||||
|
if(parse.get_error()) std::cout<<">> [parse] error occurred,stop.\n";
|
||||||
|
}
|
||||||
|
else std::cout<<">> [lexer] error occurred,stop.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -39,19 +77,7 @@ int main()
|
|||||||
std::cout<<">> ";
|
std::cout<<">> ";
|
||||||
std::cin>>command;
|
std::cin>>command;
|
||||||
if(command=="help")
|
if(command=="help")
|
||||||
{
|
help();
|
||||||
std::cout<<">> [\'file\'] input a file."<<std::endl;
|
|
||||||
std::cout<<">> [cls ] clear the screen."<<std::endl;
|
|
||||||
std::cout<<">> [del ] clear the resource code."<<std::endl;
|
|
||||||
std::cout<<">> [lib ] add lib file."<<std::endl;
|
|
||||||
std::cout<<">> [rs ] print resource code."<<std::endl;
|
|
||||||
std::cout<<">> [lex ] turn code into tokens."<<std::endl;
|
|
||||||
std::cout<<">> [par ] turn tokens into abstract syntax tree."<<std::endl;
|
|
||||||
std::cout<<">> [ast ] check the abstract syntax tree."<<std::endl;
|
|
||||||
std::cout<<">> [run ] run code."<<std::endl;
|
|
||||||
std::cout<<">> [logo ] print logo of nasal ."<<std::endl;
|
|
||||||
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
|
|
||||||
}
|
|
||||||
else if(command=="cls")
|
else if(command=="cls")
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -67,6 +93,8 @@ int main()
|
|||||||
else if(command=="del")
|
else if(command=="del")
|
||||||
{
|
{
|
||||||
resource.delete_file();
|
resource.delete_file();
|
||||||
|
lexer.delete_tokens();
|
||||||
|
parse.clear();
|
||||||
std::cout<<">> [Delete] complete."<<std::endl;
|
std::cout<<">> [Delete] complete."<<std::endl;
|
||||||
}
|
}
|
||||||
else if(command=="lib")
|
else if(command=="lib")
|
||||||
@@ -74,17 +102,9 @@ int main()
|
|||||||
else if(command=="rs")
|
else if(command=="rs")
|
||||||
resource.print_file();
|
resource.print_file();
|
||||||
else if(command=="lex")
|
else if(command=="lex")
|
||||||
{
|
lex_func();
|
||||||
lexer.scanner(resource.get_file());
|
|
||||||
if(!lexer.get_error())
|
|
||||||
lexer.print_token();
|
|
||||||
else
|
|
||||||
std::cout<<">> [lexer] error occurred,stop.\n";
|
|
||||||
}
|
|
||||||
else if(command=="par")
|
else if(command=="par")
|
||||||
{
|
par_func();
|
||||||
;
|
|
||||||
}
|
|
||||||
else if(command=="ast")
|
else if(command=="ast")
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
(*
|
||||||
|
<> must choose
|
||||||
|
[] can choose
|
||||||
|
{} can repeat 0 to infinite time(s)
|
||||||
|
| or
|
||||||
|
::= is defined as
|
||||||
|
*)
|
||||||
|
|
||||||
|
nil ::= nil;
|
||||||
|
id ::= identifier;
|
||||||
|
number::= number;
|
||||||
|
string::= string;
|
||||||
|
vector::=
|
||||||
|
'[' {calculation ','} ']'
|
||||||
|
;
|
||||||
|
hash ::=
|
||||||
|
'{' {hashmember ','} '}'
|
||||||
|
;
|
||||||
|
hashmember::=
|
||||||
|
id ':' calculation
|
||||||
|
;
|
||||||
|
function::=
|
||||||
|
func argument_list expressions
|
||||||
|
;
|
||||||
|
argument_list::=
|
||||||
|
'(' [{id ','} ([id '...']|{id '=' calculation ','})] ')'
|
||||||
|
;
|
||||||
|
expressions::=
|
||||||
|
'{' {definition|assignment|calculation|loop|conditional} '}'
|
||||||
|
|definition ';'
|
||||||
|
|multi_assignment ';'
|
||||||
|
|calculation ';'
|
||||||
|
|loop
|
||||||
|
|conditional
|
||||||
|
;
|
||||||
|
calculation::=
|
||||||
|
'(' calculation ')'
|
||||||
|
|scalar_gen
|
||||||
|
|trinocular
|
||||||
|
|and_expr
|
||||||
|
|calculation ('=' | '+=' | '-=' | '*=' | '/=' | '~=') calculation
|
||||||
|
;
|
||||||
|
trinocular::=
|
||||||
|
calculation '?' calculation ':' calculation
|
||||||
|
;
|
||||||
|
and_expr::=
|
||||||
|
or_expr and or_expr
|
||||||
|
;
|
||||||
|
or_expr::=
|
||||||
|
cmp_expr or cmp_expr
|
||||||
|
;
|
||||||
|
cmp_expr::=
|
||||||
|
additive_expr ('==' | '!=' | '>' | '<' | '>=' | '<=') additive_expr
|
||||||
|
;
|
||||||
|
additive_expr::=
|
||||||
|
multive_expr ('+' | '-' | '~') multive_expr
|
||||||
|
;
|
||||||
|
multive_expr::=
|
||||||
|
unary ('*' | '/') unary
|
||||||
|
;
|
||||||
|
unary::=
|
||||||
|
('-'|'!') calculation
|
||||||
|
;
|
||||||
|
scalar_gen::=
|
||||||
|
function_call
|
||||||
|
|identifier_call
|
||||||
|
|vector_call
|
||||||
|
|hash_call
|
||||||
|
|number
|
||||||
|
|string
|
||||||
|
;
|
||||||
|
function_call::=
|
||||||
|
function {call_scalar}
|
||||||
|
;
|
||||||
|
identifier_call::=
|
||||||
|
id {call_scalar}
|
||||||
|
;
|
||||||
|
vector_call::=
|
||||||
|
vector {call_scalar}
|
||||||
|
;
|
||||||
|
hash_call::=
|
||||||
|
hash {call_scalar}
|
||||||
|
;
|
||||||
|
call_scalar::=
|
||||||
|
'.' id
|
||||||
|
|'[' {(calculation | subvec) ','} ']'
|
||||||
|
|'(' {calculation ','} ')'
|
||||||
|
|'(' {hashmember ','} ')'
|
||||||
|
;
|
||||||
|
subvec::=
|
||||||
|
calculation ':' calculation
|
||||||
|
|calculation ':'
|
||||||
|
|':' calculation
|
||||||
|
;
|
||||||
|
definition::=
|
||||||
|
var id '=' calculation
|
||||||
|
|var '(' multi_id ')' '=' (calculation | multi_scalar)
|
||||||
|
|'(' var multi_id ')' '=' (calculation | multi_scalar)
|
||||||
|
;
|
||||||
|
multi_id::=
|
||||||
|
{id ','} <id>
|
||||||
|
;
|
||||||
|
multi_scalar::=
|
||||||
|
'(' {calculation ','} <calculation> ')'
|
||||||
|
;
|
||||||
|
multi_assignment::=
|
||||||
|
multi_scalar '=' multi_scalar
|
||||||
|
;
|
||||||
|
loop::=
|
||||||
|
while '(' calculation ')' expressions
|
||||||
|
|for '(' [definition] ';' [calculation] ';' [calculation] ')' expressions
|
||||||
|
|(forindex | foreach) '(' (definition | assignment) ';' calculation ')' expressions
|
||||||
|
;
|
||||||
|
conditional::=
|
||||||
|
if '(' calculation ')' expressions
|
||||||
|
{elsif '(' calculation ')' expressions}
|
||||||
|
[else expressions]
|
||||||
|
;
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "nasal_misc.h"
|
#include "nasal_misc.h"
|
||||||
#include "nasal_resource.h"
|
#include "nasal_resource.h"
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_lexer.h"
|
||||||
|
#include "nasal_ast.h"
|
||||||
#include "nasal_parse.h"
|
#include "nasal_parse.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#ifndef __NASAL_AST_H__
|
||||||
|
#define __NASAL_AST_H__
|
||||||
|
|
||||||
|
class nasal_ast
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int line;
|
||||||
|
int type;
|
||||||
|
std::string str;
|
||||||
|
std::vector<nasal_ast> children;
|
||||||
|
public:
|
||||||
|
nasal_ast();
|
||||||
|
nasal_ast(const nasal_ast&);
|
||||||
|
~nasal_ast();
|
||||||
|
void clear();
|
||||||
|
void set_line(int);
|
||||||
|
void set_type(int);
|
||||||
|
void set_str(std::string&);
|
||||||
|
void add_child(nasal_ast&);
|
||||||
|
int get_line();
|
||||||
|
int get_type();
|
||||||
|
std::string get_str();
|
||||||
|
std::vector<nasal_ast>& get_children();
|
||||||
|
};
|
||||||
|
|
||||||
|
nasal_ast::nasal_ast()
|
||||||
|
{
|
||||||
|
this->line=0;
|
||||||
|
this->type=ast_null;
|
||||||
|
this->str="";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||||
|
{
|
||||||
|
this->line=tmp.line;
|
||||||
|
this->type=tmp.type;
|
||||||
|
this->str=tmp.str;
|
||||||
|
this->children=tmp.children;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nasal_ast::~nasal_ast()
|
||||||
|
{
|
||||||
|
this->str.clear();
|
||||||
|
this->children.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_ast::clear()
|
||||||
|
{
|
||||||
|
this->line=0;
|
||||||
|
this->type=ast_null;
|
||||||
|
this->str="";
|
||||||
|
this->children.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_ast::set_line(int l)
|
||||||
|
{
|
||||||
|
this->line=l;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_ast::set_type(int t)
|
||||||
|
{
|
||||||
|
this->type=t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_ast::set_str(std::string& s)
|
||||||
|
{
|
||||||
|
this->str=s;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_ast::add_child(nasal_ast& ast)
|
||||||
|
{
|
||||||
|
children.push_back(ast);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nasal_ast::get_line()
|
||||||
|
{
|
||||||
|
return this->line;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nasal_ast::get_type()
|
||||||
|
{
|
||||||
|
return this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string nasal_ast::get_str()
|
||||||
|
{
|
||||||
|
return this->str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<nasal_ast>& nasal_ast::get_children()
|
||||||
|
{
|
||||||
|
return this->children;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -18,4 +18,12 @@ enum token_type
|
|||||||
tok_cmp_equal,tok_cmp_not_equal,tok_less_than,tok_greater_than,tok_less_equal,tok_greater_equal
|
tok_cmp_equal,tok_cmp_not_equal,tok_less_than,tok_greater_than,tok_less_equal,tok_greater_equal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ast_node
|
||||||
|
{
|
||||||
|
ast_null=0,
|
||||||
|
ast_nil,ast_number,ast_string,ast_identifier,
|
||||||
|
ast_for,ast_forindex,ast_foreach,ast_while,
|
||||||
|
ast_definition,ast_assignment
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -81,14 +81,15 @@ class nasal_lexer
|
|||||||
private:
|
private:
|
||||||
int error;
|
int error;
|
||||||
std::vector<token> token_list;
|
std::vector<token> token_list;
|
||||||
public:
|
|
||||||
std::string identifier_gen(std::vector<char>&,int&,int&);
|
std::string identifier_gen(std::vector<char>&,int&,int&);
|
||||||
std::string number_gen(std::vector<char>&,int&,int&);
|
std::string number_gen(std::vector<char>&,int&,int&);
|
||||||
std::string string_gen(std::vector<char>&,int&,int&);
|
std::string string_gen(std::vector<char>&,int&,int&);
|
||||||
|
public:
|
||||||
void delete_tokens();
|
void delete_tokens();
|
||||||
void scanner(std::vector<char>&);
|
void scanner(std::vector<char>&);
|
||||||
void print_token();
|
void print_token();
|
||||||
int get_error();
|
int get_error();
|
||||||
|
std::vector<token>& get_token_list();
|
||||||
};
|
};
|
||||||
|
|
||||||
void nasal_lexer::delete_tokens()
|
void nasal_lexer::delete_tokens()
|
||||||
@@ -323,4 +324,9 @@ int nasal_lexer::get_error()
|
|||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<token>& nasal_lexer::get_token_list()
|
||||||
|
{
|
||||||
|
return token_list;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1,4 +1,127 @@
|
|||||||
#ifndef __NASAL_PARSE_H__
|
#ifndef __NASAL_PARSE_H__
|
||||||
#define __NAsAL_PARSE_H__
|
#define __NAsAL_PARSE_H__
|
||||||
|
|
||||||
|
class nasal_parse
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int tok_list_size;
|
||||||
|
int ptr;
|
||||||
|
int error;
|
||||||
|
nasal_ast root;
|
||||||
|
std::vector<token> tok_list;
|
||||||
|
void reset();
|
||||||
|
nasal_ast nil_gen();
|
||||||
|
nasal_ast number_gen();
|
||||||
|
nasal_ast string_gen();
|
||||||
|
nasal_ast id_gen();
|
||||||
|
nasal_ast vector_gen();
|
||||||
|
nasal_ast hash_gen();
|
||||||
|
nasal_ast hash_member_gen();
|
||||||
|
nasal_ast func_gen();
|
||||||
|
nasal_ast args_list_gen();
|
||||||
|
nasal_ast exprs_gen();
|
||||||
|
nasal_ast calculation();
|
||||||
|
nasal_ast trinocular();
|
||||||
|
nasal_ast and_expr();
|
||||||
|
nasal_ast or_expr();
|
||||||
|
nasal_ast cmp_expr();
|
||||||
|
nasal_ast additive_expr();
|
||||||
|
nasal_ast multive_expr();
|
||||||
|
nasal_ast unary();
|
||||||
|
nasal_ast scalar_gen();
|
||||||
|
nasal_ast func_call();
|
||||||
|
nasal_ast id_call();
|
||||||
|
nasal_ast vector_call();
|
||||||
|
nasal_ast hash_call();
|
||||||
|
nasal_ast call_scalar();
|
||||||
|
nasal_ast subvec();
|
||||||
|
nasal_ast definition();
|
||||||
|
nasal_ast multi_id();
|
||||||
|
nasal_ast multi_scalar();
|
||||||
|
nasal_ast multi_assgin();
|
||||||
|
nasal_ast loop();
|
||||||
|
nasal_ast conditional();
|
||||||
|
public:
|
||||||
|
int get_error();
|
||||||
|
void clear();
|
||||||
|
void set_toklist(std::vector<token>&);
|
||||||
|
void main_process();
|
||||||
|
};
|
||||||
|
|
||||||
|
int nasal_parse::get_error()
|
||||||
|
{
|
||||||
|
return this->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_parse::clear()
|
||||||
|
{
|
||||||
|
this->tok_list_size=0;
|
||||||
|
this->ptr=0;
|
||||||
|
this->error=0;
|
||||||
|
this->tok_list.clear();
|
||||||
|
this->root.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_parse::set_toklist(std::vector<token>& lex_token)
|
||||||
|
{
|
||||||
|
this->tok_list=lex_token;
|
||||||
|
tok_list_size=this->tok_list.size();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_parse::main_process()
|
||||||
|
{
|
||||||
|
this->reset();
|
||||||
|
while(ptr<tok_list_size)
|
||||||
|
{
|
||||||
|
if(tok_list[ptr].type);
|
||||||
|
++ptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasal_parse::reset()
|
||||||
|
{
|
||||||
|
this->ptr=0;
|
||||||
|
this->error=0;
|
||||||
|
this->root.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nasal_ast nasal_parse::nil_gen()
|
||||||
|
{
|
||||||
|
nasal_ast node;
|
||||||
|
node.set_line(tok_list[ptr].line);
|
||||||
|
node.set_type(ast_nil);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
nasal_ast nasal_parse::number_gen()
|
||||||
|
{
|
||||||
|
nasal_ast node;
|
||||||
|
node.set_line(tok_list[ptr].line);
|
||||||
|
node.set_type(ast_number);
|
||||||
|
node.set_str(tok_list[ptr].str);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
nasal_ast nasal_parse::string_gen()
|
||||||
|
{
|
||||||
|
nasal_ast node;
|
||||||
|
node.set_line(tok_list[ptr].line);
|
||||||
|
node.set_type(ast_string);
|
||||||
|
node.set_str(tok_list[ptr].str);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
nasal_ast nasal_parse::id_gen()
|
||||||
|
{
|
||||||
|
nasal_ast node;
|
||||||
|
node.set_line(tok_list[ptr].line);
|
||||||
|
node.set_type(ast_identifier);
|
||||||
|
node.set_str(tok_list[ptr].str);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user