diff options
| Commit | 76b849fbaa276566fa8838d745c0e5fbd2f138bc (patch) | |
|---|---|---|
| Author | 2018-11-07 16:01:18 +0200 | |
| Committer | 2018-11-07 16:01:18 +0200 | |
| Files | 903597ade32e9f2cce2a52b90aa70ff90668bbbe | |
| IPL-76b849fbaa276566fa8838d745c0e5fbd2f138bc.tar IPL-76b849fbaa276566fa8838d745c0e5fbd2f138bc.tar.gz IPL-76b849fbaa276566fa8838d745c0e5fbd2f138bc.zip | ||
| Parent | 97a58430a248b9ea89a7da0120cfceb0e6b11af5 (diff) | |
First homework - highlighter for python (#17)
* Initial commit
* Fix some typos
modified: README
* Delete index.html
6 files changed, 376 insertions, 0 deletions
| -rw-r--r-- | homework/81350/py2html/README | 12 | ||||
| -rw-r--r-- | homework/81350/py2html/Token.cpp | 39 | ||||
| -rw-r--r-- | homework/81350/py2html/Token.h | 52 | ||||
| -rwxr-xr-x | homework/81350/py2html/build_lexer.sh | 5 | ||||
| -rw-r--r-- | homework/81350/py2html/program.py | 10 | ||||
| -rw-r--r-- | homework/81350/py2html/py2html.cpp | 258 |
diff --git a/homework/81350/py2html/README b/homework/81350/py2html/README new file mode 100644 index 0000000..da727c2 --- /dev/null +++ b/homework/81350/py2html/README @@ -0,0 +1,12 @@ +To build the program run the bash script build_lexer.sh: +$ ./build_lexer.sh + +To run the highlighter on a given program: +$ ./py2html <program name> +When you run the highlighter, it will produce an html +file in the current directory named "index.html". + +There is a test program named program.py: +$ ./py2html program.py + + diff --git a/homework/81350/py2html/Token.cpp b/homework/81350/py2html/Token.cpp new file mode 100644 index 0000000..ea17db5 --- /dev/null +++ b/homework/81350/py2html/Token.cpp @@ -0,0 +1,39 @@ +#include "Token.h" +#include<unordered_map> + +std::unordered_map<std::string, TokenType> keywords = { + {"False", TokenType::False}, + {"True", TokenType::True}, + {"None", TokenType::None}, + {"and", TokenType::And}, + {"as", TokenType::As}, + {"assert", TokenType::Assert}, + {"break", TokenType::Break}, + {"class", TokenType::Class}, + {"continue", TokenType::Continue}, + {"def", TokenType::Def}, + {"del", TokenType::Del}, + {"elif", TokenType::Elif}, + {"else", TokenType::Else}, + {"except", TokenType::Except}, + {"finally", TokenType::Finally}, + {"for", TokenType::For}, + {"from", TokenType::From}, + {"global", TokenType::Global}, + {"if", TokenType::If}, + {"import", TokenType::Import}, + {"in", TokenType::In}, + {"is", TokenType::Is}, + {"lambda", TokenType::Lambda}, + {"nonlocal", TokenType::Nonlocal}, + {"not", TokenType::Not}, + {"or", TokenType::Or}, + {"pass", TokenType::Pass}, + {"print", TokenType::Print}, + {"raise", TokenType::Raise}, + {"return", TokenType::Return}, + {"try", TokenType::Try}, + {"while", TokenType::While}, + {"with", TokenType::With}, + {"yield", TokenType::Yield} +}; diff --git a/homework/81350/py2html/Token.h b/homework/81350/py2html/Token.h new file mode 100644 index 0000000..97dda8d --- /dev/null +++ b/homework/81350/py2html/Token.h @@ -0,0 +1,52 @@ +#pragma once +#include<string> +#include<unordered_map> + +typedef std::string IPLString ; + + enum TokenType{ + False, + None, + True, + And, + As, + Assert, + Break, + Class, + Continue, + Def, + Del, + Elif, + Else, + Except, + Finally, + For, + From, + Global, + If, + Import, + In, + Is, + Lambda, + Nonlocal, + Not, + Or, + Pass, + Print, + Raise, + Return, + Try, + While, + With, + Yield + }; + +struct Token +{ + TokenType Type; + unsigned Line; + IPLString Lexeme; + double Number = 0.0; +}; + +extern std::unordered_map<std::string, TokenType> keywords; diff --git a/homework/81350/py2html/build_lexer.sh b/homework/81350/py2html/build_lexer.sh new file mode 100755 index 0000000..95492e0 --- /dev/null +++ b/homework/81350/py2html/build_lexer.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +g++ -Wall -O2 -std=c++11 -c py2html.cpp -o py2html.o +g++ -Wall -O2 -std=c++11 -c Token.cpp -o Token.o +g++ -o py2html py2html.o Token.o -s diff --git a/homework/81350/py2html/program.py b/homework/81350/py2html/program.py new file mode 100644 index 0000000..8343c02 --- /dev/null +++ b/homework/81350/py2html/program.py @@ -0,0 +1,10 @@ +num1 = 1.5 +num2 = 6.3 + +sum = float(num1) + float(num2) + +print('The sum of {0} and {1} is {2}'.format(num1, num2, sum)) + +table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678} +for name, phone in table.items(): + print(f'{name:10} ==> {phone:10d}') diff --git a/homework/81350/py2html/py2html.cpp b/homework/81350/py2html/py2html.cpp new file mode 100644 index 0000000..65d28da --- /dev/null +++ b/homework/81350/py2html/py2html.cpp @@ -0,0 +1,258 @@ +#include <iostream> +#include <string> +#include <cctype> +#include <unistd.h> +#include <sys/types.h> +#include <unordered_map> +#include <set> +#include "Token.h" + +std::string operatorChars = "+-*/%=<>&|^~"; +std::string parenthesisChars = "[]{}(),"; +std::set<std::string> operators = { + "+", + "-", + "*", + "/", + "//", + "%", + "**", + ">", + "<", + ">=", + "<=", + "==", + "!=", + "&", + "|", + "~", + "^", + ">>", + "<<", + "=", + "+=", + "-=", + "*=", + "/=", + "%=", + "**=", + "//=", + "^=", + "&=", + "|=", + ">>=", + "<<=" +}; + +using namespace std; +FILE* in; +FILE* out; + +bool isNumber(char c){ + return c >= '0' && c <= '9'; +} + +bool notValidNumber(char c){ + return !(isNumber(c) || c == '.'); +} + +bool isQuote(char c){ + return c == '\'' || c == '"'; +} + +bool isLastQuote(char firstQuote, char previousChar, char currentChar){ + return firstQuote == currentChar && previousChar != '\\'; +} + +bool isOperator(char c){ + return operatorChars.find(c) != std::string::npos; +} + +bool isParenthesis(char c){ + return parenthesisChars.find(c) != std::string::npos; +} + +bool isValidIdentifierChar(char c){ + return !(isOperator(c) || isParenthesis(c) || isQuote(c) || c == '\n' || isblank(c) || c == ','); +} + +bool isValidOperator(std::string word){ + std::set<std::string>::iterator iter; + iter = operators.find(word); + return iter != operators.end(); +} + +std::string readFormat(){ + std::string word = "{"; + char c; + + while((c = fgetc(in)) != EOF && c != '}'){ + word += c; + } + word += '}'; + return word; +} + +std::string readNumber(){ + fseek(in, -1, SEEK_CUR); + std::string word; + char c; + int dotCount = 0; + + while((c = fgetc(in)) != EOF && !notValidNumber(c)){ + //printf("%c", c); + if(notValidNumber(c)){ + return ""; + } else if(c == '.'){ + dotCount++; + if(dotCount >= 2){ + return ""; + } + } + word += c; + } + if(notValidNumber(c)){ + fseek(in, -1, SEEK_CUR); + } + return word; +} + +std::string readString(char firstQuote){ + std::string word = ""; + word += firstQuote; + char c; + char previousChar = ' '; + + while((c = fgetc(in)) != EOF && !isLastQuote(firstQuote, previousChar, c)){ + if( c == '{'){ + fprintf(out, "<span class=\"string\">%s</span>", word.c_str()); + word = readFormat(); + fprintf(out, "<span class=\"formatString\">%s</span>", word.c_str()); + word = ""; + } else { + word += c; + } + previousChar = c; + } + word += firstQuote; + fprintf(out, "<span class=\"string\">%s</span>", word.c_str()); + return word; +} + +std::string readOperator(){ + fseek(in, -1, SEEK_CUR); + std::string word; + char c; + while((c = fgetc(in)) != EOF && isOperator(c)){ + word += c; + } + if(!isOperator(c)){ + fseek(in, -1, SEEK_CUR); + } + return word; +} + +std::string readWord(){ + fseek(in, -1, SEEK_CUR); + std::string word; + char c; + while((c = fgetc(in)) != EOF && isValidIdentifierChar(c)){ + word += c; + } + + if(!isValidIdentifierChar(c)){ + fseek(in, -1, SEEK_CUR); + } + return word; +} + +void lexer(){ + char c; + bool validSyntaxis = 1; + std::string word; + std::unordered_map<std::string, TokenType>::const_iterator iter; + + while((c = fgetc(in)) != EOF){ + if(isQuote(c)){ + word = readString(c); + //fprintf(out, "<span class=\"string\">%s</span>", word.c_str()); + continue; + } + if(isNumber(c)){ + word = readNumber(); + fprintf(out, "<span class=\"number\">%s</span>", word.c_str()); + continue; + } + if(isOperator(c)){ + word = readOperator(); + if(isValidOperator(word)){ + validSyntaxis = 0; + } + fprintf(out, "<span class=\"operator\">%s</span>", word.c_str()); + // trqbwa da se proweti dali e korektno + // t.e. da e w nqkyw set ili hash + continue; + } + if(isParenthesis(c)){ + fprintf(out, "%c", c); + continue; + } + if(isblank(c) || c == '\n'){ + fprintf(out, "%c", c); + continue; + } + + word = readWord(); + iter = keywords.find(word); + if(iter == keywords.end()){ + fprintf(out, "%s", word.c_str()); + } else { + fprintf(out, "<span class=\"keyword\">%s</span>", word.c_str()); + } + + } +} + +int main(int argc, const char* argv[]) +{ + ++argv, --argc; /* skip over program name */ + if ( argc > 0 ) + in = fopen( argv[0], "r" ); + else + in = stdin; + + out = fopen("index.html", "w"); + + fputs( + "<!doctype>" + "<html>" + "<head>" + " <title>program.py</title>" + " <style>" + " .keyword {" + " color: purple;" + " }" + " .number {" + " color: orange;" + " }" + " .string {" + " color: green;" + " }" + " .operator {" + " font-style: bold;" + " }" + " .formatString {" + " color: red;" + " }" + " </style>" + "</head>" + "<body>" + " <pre class=\"code\">", + out); + + lexer(); + fputs("</pre></body></html>", out); + fclose(in); + fclose(out); + return 0; +} |
