From 3357fa8140498bad55f50dd1c5de4da9d9b9e236 Mon Sep 17 00:00:00 2001 From: Valk Richard Li <48872266+ValKmjolnir@users.noreply.github.com> Date: Mon, 4 Nov 2019 18:11:16 +0800 Subject: [PATCH] subset of nasal --- balloon/abstract_syntax_tree.h | 33 +++ balloon/balloon.h | 16 ++ balloon/balloon_lexer.h | 414 +++++++++++++++++++++++++++++++++ balloon/balloon_parse.h | 37 +++ balloon/balloon_type.h | 134 +++++++++++ balloon/balloon_var.h | 132 +++++++++++ balloon/main.cpp | 65 ++++++ 7 files changed, 831 insertions(+) create mode 100644 balloon/abstract_syntax_tree.h create mode 100644 balloon/balloon.h create mode 100644 balloon/balloon_lexer.h create mode 100644 balloon/balloon_parse.h create mode 100644 balloon/balloon_type.h create mode 100644 balloon/balloon_var.h create mode 100644 balloon/main.cpp diff --git a/balloon/abstract_syntax_tree.h b/balloon/abstract_syntax_tree.h new file mode 100644 index 0000000..f30e243 --- /dev/null +++ b/balloon/abstract_syntax_tree.h @@ -0,0 +1,33 @@ +#ifndef __ABSTRACT_SYNTAX_TREE_H__ +#define __ABSTRACT_SYNTAX_TREE_H__ + +class abstract_syntax_tree +{ + private: + int type; + double number; + std::string str; + std::string name; + std::list children; + public: + abstract_syntax_tree() + { + type=__null_node; + number=0; + str=""; + name=""; + children.clear(); + return; + } + abstract_syntax_tree(const abstract_syntax_tree& p) + { + type=p.type; + number=p.number; + str=p.str; + name=p.name; + children=p.children; + return; + } +}; + +#endif diff --git a/balloon/balloon.h b/balloon/balloon.h new file mode 100644 index 0000000..cef87f2 --- /dev/null +++ b/balloon/balloon.h @@ -0,0 +1,16 @@ +#ifndef __BALLOON_H__ +#define __BALLOON_H__ + +#include +#include +#include +#include +#include + +#include "balloon_type.h" +#include "balloon_var.h" +#include "abstract_syntax_tree.h" +#include "balloon_lexer.h" +#include "balloon_parse.h" + +#endif diff --git a/balloon/balloon_lexer.h b/balloon/balloon_lexer.h new file mode 100644 index 0000000..7ce7b39 --- /dev/null +++ b/balloon/balloon_lexer.h @@ -0,0 +1,414 @@ +#ifndef __BALLOON_LEXER_H__ +#define __BALLOON_LEXER_H__ + +std::string reserve_word[15]= +{ + "for","foreach","forindex","while", + "var","func","break","continue","return", + "if","else","elsif","nil","and","or" +}; +int is_reserve_word(std::string str) +{ + for(int i=0;i<15;++i) + if(reserve_word[i]==str) + return __reserve_word; + return __token_identifier; +} + + + +class resource_file +{ + private: + std::list resource; + public: + void set_clear() + { + resource.clear(); + return; + } + void input_file(std::string filename) + { + std::ifstream fin(filename,std::ios::binary); + char c; + while(!fin.eof()) + { + c=fin.get(); + if(fin.eof()) + break; + resource.push_back(c); + } + resource.push_back('\n'); + return; + } + std::list& get_resource() + { + return resource; + } + void print_file() + { + int line=1; + std::cout<::iterator i=resource.begin();i!=resource.end();++i) + { + std::cout<<*i; + if(*i=='\n') + { + ++line; + std::cout< token_list; + std::list detail_token; + public: + void set_clear() + { + token_list.clear(); + detail_token.clear(); + return; + } + void print_token_list() + { + for(std::list::iterator i=token_list.begin();i!=token_list.end();++i) + { + std::cout<<"( "; + print_token(i->type); + std::cout<<" | "<str<<" )"<::iterator i=detail_token.begin();i!=detail_token.end();++i) + { + std::cout<<"( "; + print_detail_token(i->type); + std::cout<<" | "<str<<" )"<& res) + { + token_list.clear(); + error=0; + + int line=1; + std::string token_str; + std::list::iterator ptr=res.begin(); + while(1) + { + while(*ptr==' ' || *ptr=='\n' || *ptr=='\t' || *ptr=='\r' || *ptr<0 || *ptr>127) + { + if(*ptr=='\n') + ++line; + ++ptr; + if(ptr==res.end()) + break; + } + if(ptr==res.end()) + break; + if(*ptr=='_' || ('a'<=*ptr && *ptr<='z') || ('A'<=*ptr && *ptr<='Z')) + { + token_str=""; + while(*ptr=='_' || ('a'<=*ptr && *ptr<='z') || ('A'<=*ptr && *ptr<='Z') || ('0'<=*ptr && *ptr<='9')) + { + token_str+=*ptr; + ++ptr; + if(ptr==res.end()) + break; + } + if(*ptr=='.') + { + ++ptr; + if(ptr!=res.end() && *ptr=='.') + { + ++ptr; + if(ptr!=res.end() && *ptr=='.') + { + token_str+="..."; + ++ptr; + } + else + { + --ptr; + --ptr; + } + } + else + --ptr; + } + token new_token; + new_token.line=line; + new_token.type=is_reserve_word(token_str); + new_token.str=token_str; + token_list.push_back(new_token); + if(ptr==res.end()) + break; + } + else if('0'<=*ptr && *ptr<='9') + { + token_str=""; + while(('0'<=*ptr && *ptr<='9') || *ptr=='.' || *ptr=='x' || *ptr=='o') + { + token_str+=*ptr; + ++ptr; + if(ptr==res.end()) + break; + } + token new_token; + new_token.line=line; + new_token.type=__token_number; + new_token.str=token_str; + token_list.push_back(new_token); + if(ptr==res.end()) + break; + } + else if(*ptr=='(' || *ptr==')' || *ptr=='[' || *ptr==']' || *ptr=='{' || + *ptr=='}' || *ptr==',' || *ptr==';' || *ptr=='|' || *ptr==':' || + *ptr=='?' || *ptr=='.' || *ptr=='`' || *ptr=='&' || *ptr=='@' || + *ptr=='%' || *ptr=='$' || *ptr=='^' || *ptr=='\\') + { + token_str=""; + token_str+=*ptr; + token new_token; + new_token.line=line; + new_token.type=__token_operator; + new_token.str=token_str; + token_list.push_back(new_token); + ++ptr; + if(ptr==res.end()) + break; + } + else if(*ptr=='\'' || *ptr=='\"') + { + char str_begin=*ptr; + token_str=""; + ++ptr; + if(ptr==res.end()) + break; + while(*ptr!=str_begin && *ptr!='\n') + { + token_str+=*ptr; + if(*ptr=='\\') + { + ++ptr; + if(ptr!=res.end()) + { + token_str+=*ptr; + ++ptr; + } + } + else + ++ptr; + if(ptr==res.end()) + break; + } + if(ptr==res.end() || *ptr!=str_begin) + { + ++error; + std::cout<<">>[Lexer-error] line "<' || *ptr=='~') + { + token_str=""; + token_str+=*ptr; + ++ptr; + if(ptr!=res.end() && *ptr=='=') + { + token_str+=*ptr; + ++ptr; + } + token new_token; + new_token.line=line; + new_token.type=__token_operator; + new_token.str=token_str; + token_list.push_back(new_token); + if(ptr==res.end()) + break; + } + else if(*ptr=='#') + { + while(ptr!=res.end() && *ptr!='\n')++ptr; + if(ptr==res.end()) + break; + } + } + return; + } + void generate_detail_token() + { + token detail; + detail_token.clear(); + for(std::list::iterator i=token_list.begin();i!=token_list.end();++i) + { + if(i->type==__token_number) + { + detail.line=i->line; + detail.str=i->str; + detail.type=__number; + detail_token.push_back(detail); + } + else if(i->type==__token_string) + { + detail.line=i->line; + detail.str=i->str; + detail.type=__string; + detail_token.push_back(detail); + } + else if(i->type==__reserve_word) + { + detail.line=i->line; + detail.str=i->str; + if(i->str=="for") + detail.type=__for; + else if(i->str=="foreach") + detail.type=__foreach; + else if(i->str=="forindex") + detail.type=__forindex; + else if(i->str=="while") + detail.type=__while; + else if(i->str=="var") + detail.type=__var; + else if(i->str=="func") + detail.type=__func; + else if(i->str=="break") + detail.type=__break; + else if(i->str=="continue") + detail.type=__continue; + else if(i->str=="return") + detail.type=__return; + else if(i->str=="if") + detail.type=__if; + else if(i->str=="else") + detail.type=__else; + else if(i->str=="elsif") + detail.type=__elsif; + else if(i->str=="nil") + detail.type=__nil; + else if(i->str=="and") + detail.type=__and_operator; + else if(i->str=="or") + detail.type=__or_operator; + detail_token.push_back(detail); + } + else if(i->type==__token_identifier) + { + detail.line=i->line; + detail.str=i->str; + if(i->str.length()<=3) + detail.type=__id; + else + { + std::string tempstr=i->str; + int strback=tempstr.length()-1; + if(tempstr[strback]=='.' && tempstr[strback-1]=='.' && tempstr[strback-2]=='.') + detail.type=__dynamic_id; + else + detail.type=__id; + } + detail_token.push_back(detail); + } + else if(i->type==__token_operator) + { + detail.line=i->line; + detail.str=i->str; + if(i->str=="+") + detail.type=__add_operator; + else if(i->str=="-") + detail.type=__sub_operator; + else if(i->str=="*") + detail.type=__mul_operator; + else if(i->str=="/") + detail.type=__div_operator; + else if(i->str=="~") + detail.type=__link_operator; + else if(i->str=="+=") + detail.type=__add_equal; + else if(i->str=="-=") + detail.type=__sub_equal; + else if(i->str=="*=") + detail.type=__mul_equal; + else if(i->str=="/=") + detail.type=__div_equal; + else if(i->str=="~=") + detail.type=__link_equal; + else if(i->str=="=") + detail.type=__equal; + else if(i->str=="==") + detail.type=__cmp_equal; + else if(i->str=="!=") + detail.type=__cmp_not_equal; + else if(i->str=="<") + detail.type=__cmp_less; + else if(i->str=="<=") + detail.type=__cmp_less_or_equal; + else if(i->str==">") + detail.type=__cmp_more; + else if(i->str==">=") + detail.type=__cmp_more_or_equal; + else if(i->str==";") + detail.type=__semi; + else if(i->str==".") + detail.type=__dot; + else if(i->str==":") + detail.type=__colon; + else if(i->str==",") + detail.type=__comma; + else if(i->str=="!") + detail.type=__nor_operator; + else if(i->str=="[") + detail.type=__left_bracket; + else if(i->str=="]") + detail.type=__right_bracket; + else if(i->str=="(") + detail.type=__left_curve; + else if(i->str==")") + detail.type=__right_curve; + else if(i->str=="{") + detail.type=__left_brace; + else if(i->str=="}") + detail.type=__right_brace; + else + { + ++error; + std::cout<<">>[Lexer-error] line "<& get_detail_token() + { + return detail_token; + } +}; +#endif diff --git a/balloon/balloon_parse.h b/balloon/balloon_parse.h new file mode 100644 index 0000000..9b2b0fc --- /dev/null +++ b/balloon/balloon_parse.h @@ -0,0 +1,37 @@ +#ifndef __BALLOON_PARSE_H__ +#define __BALLOON_PARSE_H__ + +class balloon_parse +{ + private: + std::stack detail; + token this_token; + int error; + int warning; + public: + void get_token() + { + if(!detail.empty()) + { + this_token=detail.top(); + detail.pop(); + } + else + this_token.type=0; + return; + } + void get_detail_token_stream(std::list& tk_list) + { + std::stack temp; + for(std::list::iterator i=tk_list.begin();i!=tk_list.end();++i) + temp.push(*i); + while(!temp.empty()) + { + detail.push(temp.top()); + temp.pop(); + } + return; + } +}; + +#endif diff --git a/balloon/balloon_type.h b/balloon/balloon_type.h new file mode 100644 index 0000000..d95aece --- /dev/null +++ b/balloon/balloon_type.h @@ -0,0 +1,134 @@ +#ifndef __BALLOON_TYPE_H__ +#define __BALLOON_TYPE_H__ + + +enum token_type +{ + __token_number=1, + __token_string, + __reserve_word, + __token_identifier, + __token_operator +}; +void print_token(int type) +{ + std::string str; + switch(type) + { + case __token_number: str="number ";break; + case __token_string: str="string ";break; + case __reserve_word: str="reserve word ";break; + case __token_identifier:str="identifier ";break; + case __token_operator: str="operator ";break; + default: str="unknown ";break; + } + std::cout< >= + __and_operator,__or_operator,__nor_operator, // and or ! + __add_operator,__sub_operator, // + - + __mul_operator,__div_operator,__link_operator, // * / ~ + __add_equal,__sub_equal, // += -= + __mul_equal,__div_equal,__link_equal, // *= /= ~= + __left_brace,__right_brace, // {} + __left_bracket,__right_bracket, // [] + __left_curve,__right_curve, // () + __semi,__comma,__colon,__dot, // ; , : . + __var,__func,__return, + __if,__elsif,__else, + __continue,__break, + __for,__forindex,__foreach,__while, + __nil, + //operators & reserve words + __number,__string,__id,__dynamic_id, + //basic elements + + __null_node, + __root, + __loop, + __ifelse, + __function, + __definition, + __assignment, + __call_array, + __call_hash, + __call_function +}; +void print_detail_token(int type) +{ + std::string context=""; + switch(type) + { + case __equal: context="="; break; + case __cmp_equal: context="==";break; + case __cmp_not_equal: context="!=";break; + case __cmp_less: context="<"; break; + case __cmp_less_or_equal: context="<=";break; + case __cmp_more: context=">"; break; + case __cmp_more_or_equal: context=">=";break; + case __and_operator: context="and";break; + case __or_operator: context="or"; break; + case __nor_operator: context="!"; break; + case __add_operator: context="+"; break; + case __sub_operator: context="-"; break; + case __mul_operator: context="*"; break; + case __div_operator: context="/"; break; + case __link_operator: context="~"; break; + case __add_equal: context="+=";break; + case __sub_equal: context="-=";break; + case __mul_equal: context="*=";break; + case __div_equal: context="/=";break; + case __link_equal: context="~=";break; + case __left_brace: context="{"; break; + case __right_brace: context="}"; break; + case __left_bracket: context="["; break; + case __right_bracket: context="]"; break; + case __left_curve: context="("; break; + case __right_curve: context=")"; break; + case __semi: context=";"; break; + case __comma: context=","; break; + case __colon: context=":"; break; + case __dot: context="."; break; + case __var: context="var"; break; + case __func: context="func";break; + case __continue: context="continye"; break; + case __break: context="break"; break; + case __for: context="for"; break; + case __forindex: context="forindex";break; + case __foreach: context="foreach";break; + case __while: context="while";break; + case __if: context="if";break; + case __elsif: context="elsif";break; + case __else: context="else";break; + case __return: context="return";break; + case __nil: context="nil";break; + case __id: context="id";break; + case __dynamic_id: context="id...";break; + case __number: context="num";break; + case __string: context="str";break; + + case __null_node: context="null node";break; + case __root: context="root";break; + case __loop: context="loop";break; + case __ifelse: context="if-else";break; + case __function: context="function";break; + case __definition: context="definition";break; + case __assignment: context="assignment";break; + case __call_array: context="call array";break; + case __call_hash: context="call hash";break; + case __call_function: context="call func";break; + default: context="undefined token";break; + } + std::cout< balloon_array; + std::list balloon_hash; + public: + var() + { + number=0; + str=""; + name=""; + balloon_array.clear(); + balloon_hash.clear(); + return; + } + var(const var& p) + { + type=p.type; + number=p.number; + str=p.str; + name=p.name; + balloon_array=p.balloon_array; + balloon_hash=p.balloon_hash; + return; + } + var& operator=(const var p) + { + type=p.type; + number=p.number; + str=p.str; + name=p.name; + balloon_array.clear(); + balloon_hash.clear(); + balloon_array=p.balloon_array; + balloon_hash=p.balloon_hash; + return *this; + } + void set_type(int); + void set_name(std::string); + void set_number(double); + void set_string(std::string); + void append_array(var); + void append_hash(var); + std::string get_name(); + double get_number(); + std::string get_string(); + var& get_array_member(int); + var& get_hash_member(std::string); +}; + +var error_var; +void var::set_type(int _type) +{ + type=_type; + return; +} +void var::set_name(std::string _name) +{ + name=_name; + return; +} +void var::set_number(double _num) +{ + number=_num; + return; +} +void var::set_string(std::string _str) +{ + str=_str; + return; +} +void var::append_array(var _new_var) +{ + balloon_array.push_back(_new_var); + return; +} +void var::append_hash(var _new_var) +{ + balloon_hash.push_back(_new_var); + return; +} +std::string var::get_name() +{ + return name; +} +double var::get_number() +{ + return number; +} +std::string var::get_string() +{ + return str; +} +var& var::get_array_member(int _place) +{ + if(balloon_array.empty()) + { + std::cout<<">>[Runtime-error] overflow when searching member "<<_place<<" but the max size of array \'"<::iterator i=balloon_array.begin();i!=balloon_array.end();++i,++cnt) + if(cnt==_place) + return *i; + std::cout<<">>[Runtime-error] overflow when searching member "<<_place<<" but the max size of array \'"<::iterator i=balloon_hash.begin();i!=balloon_hash.end();++i) + if(i->name==_name) + return *i; + std::cout<<">>[Runtime-error] hash \'"<> Balloon interpreter by ValKmjolnir"<> Input [help] to find help."<> "; + std::getline(std::cin,command); + if(command=="help") + { + std::cout<<">> Balloon interpreter by ValKmjolnir"<> 1. [ ] |input file name to load the file."<> 2. [cls ] |clear the screen."<> 3. [exit ] |shut down the interpreter."<> 4. [lexer ] |run and show the lexer. (-lexer)"<> 5. [parser] |run parser and see parse stack & parse result(s). (-parser)"<> 6. [ast ] |print the abstract syntax tree."<> 7. [del ] |delete program in memory."<> 8. [run ] |run the programme in stack. (-lexer -parser)"<> 9. [rs ] |check the source program."<>[Delete] Complete."<