/* * grammars.cpp * * Created on: 28.10.2014 г. * Author: trifon */ #include using namespace std; #include "stack_automaton.h" bool matchTerminal(char const*& word, char t) { if (*word == t) { word++; return true; } return false; } bool parseS(char const*&); bool parseT(char const*&); bool parseU(char const*&); int count = 0; bool parseU(char const*& word) { if (*word == '{') { return matchTerminal(word, '{') && parseS(word) && matchTerminal(word, '}'); } else return matchTerminal(word, 'a'); } bool parseT(char const*& word) { if (*word == '[') { count++; return matchTerminal(word, '[') && parseU(word) && matchTerminal(word, ']'); } else return matchTerminal(word, 'a'); } bool parseS(char const*& word) { if (*word == '(') { return matchTerminal(word, '(') && parseT(word) && matchTerminal(word, ')'); } else return matchTerminal(word, 'a'); } bool parseE(char const*& word) { if (*word >= '0' && *word <= '9') { //return matchTerminal(word, *word); word++; return true; } else { return (matchTerminal(word, '+') || matchTerminal(word, '-') || matchTerminal(word, '*') || matchTerminal(word, '/')) && parseE(word) && parseE(word); } } bool calculateE(char const*& word, double& result) { if (*word >= '0' && *word <= '9') { result = *word - '0'; word++; return true; } else { char op = *word; double l, r; bool success = (matchTerminal(word, '+') || matchTerminal(word, '-') || matchTerminal(word, '*') || matchTerminal(word, '/')) && calculateE(word, l) && calculateE(word, r); if (success) { switch(op) { case '+':result = l + r; break; case '-':result = l - r; break; case '*':result = l * r; break; case '/':result = l / r; break; } } return success; } } void testStackAutomaton() { StackAutomaton s; s.addDelta('a', '#', "a"); s.addDelta('b', 'a', "b"); s.addDelta('c', 'b', ""); cout << s.recognize("abc") << endl; cout << s.recognize("ab") << endl; cout << s.recognize("abcd") << endl; } void testGrammars() { char word[100]; cin.getline(word, 100); char const* p = word; bool recognizeS = parseS(p) && *p == '\0'; cout << recognizeS << endl; cout << "Брой на квадратните скоби: " << count << endl; p = word; bool recognizeE = parseE(p) && *p == '\0'; cout << recognizeE << endl; p = word; double result; recognizeE = calculateE(p, result) && *p == '\0'; if (recognizeE) { cout << result << endl; } else cout << "ERROR!" << endl; } struct Rule { char LHS; char const* RHS; }; StackAutomaton buildAutomaton(Rule grammar[], int n) { StackAutomaton sa(grammar[0].LHS); // (1) for(int i = 0; i < n; i++) sa.addDelta(EPS, grammar[i].LHS, grammar[i].RHS); // (2) for(unsigned char c = 1; c < TABLE_SIZE; c++) sa.addDelta(c, c, ""); return sa; } void testParentheses() { Rule grammar[] = { { 'S', "(T)" }, { 'T', "[U]" }, { 'U', "{S}" }, { 'S', "a" }, { 'T', "a" }, { 'U', "a" } }; StackAutomaton sa = buildAutomaton(grammar, 6); cout << sa.recognize("a") << endl; sa.reset(); cout << sa.recognize("(a)") << endl; sa.reset(); cout << sa.recognize("([{(a)}])") << endl; sa.reset(); cout << sa.recognize("([a)]") << endl; } void testPN() { Rule grammar[] = { { 'E', "+EE" }, { 'E', "-EE" }, { 'E', "*EE" }, { 'E', "/EE" }, { 'E', "0" }, { 'E', "1" }, { 'E', "2" }, { 'E', "3" }, { 'E', "4" }, { 'E', "5" }, { 'E', "6" }, { 'E', "7" }, { 'E', "8" }, { 'E', "9" } }; StackAutomaton sa = buildAutomaton(grammar, 14); cout << sa.recognize("*+12-3/45") << endl; } void testArithmetic() { Rule grammar[] = { { 'S', "S+T" }, { 'S', "S-T" }, { 'S', "T" }, { 'T', "T*F" }, { 'T', "T/F" }, { 'T', "F" }, { 'F', "(S)" }, { 'F', "0" }, { 'F', "1" }, { 'F', "2" }, { 'F', "3" }, { 'F', "4" }, { 'F', "5" }, { 'F', "6" }, { 'F', "7" }, { 'F', "8" }, { 'F', "9" } }; StackAutomaton sa = buildAutomaton(grammar, 17); cout << sa.recognize("(1+2)*(3-4/5)") << endl; } void testArithmeticLL1() { Rule grammar[] = { { 'S', "TA" }, { 'A', "+S" }, { 'A', "-S" }, { 'A', "" }, { 'T', "FB" }, { 'B', "*T" }, { 'B', "/T" }, { 'B', "" }, { 'F', "(S)" }, { 'F', "0" }, { 'F', "1" }, { 'F', "2" }, { 'F', "3" }, { 'F', "4" }, { 'F', "5" }, { 'F', "6" }, { 'F', "7" }, { 'F', "8" }, { 'F', "9" } }; StackAutomaton sa = buildAutomaton(grammar, 19); cout << sa.recognize("1") << endl; sa.reset(); cout << sa.recognize("(1+2)*(3-4/5)") << endl; } int main() { // testGrammars(); // testStackAutomaton(); // testParentheses(); // testPN(); // testArithmetic(); testArithmeticLL1(); return 0; }