Friday, September 16, 2016

UVa 134 - Loglan-A Logical Language

Accepted date: 2016-09-16
Run Time: 0.000
Ranking (as of 2016-09-16): 290 out of 808
Language: C++

Another simple implementation of recursive descent parser.


/*
  UVa 134 - Loglan-A Logical Language

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_134_Loglan-A_Logical_Language.cpp
*/

#include <algorithm>
#include <iostream>
#include <string>
#include <cctype>
using namespace std;

string sentence;
const char *ps, *pws, *pwe;

bool get_word_or_name(const char** s, const char** e)
{
  while (isspace(*ps))
    ps++;
  *s = ps;
  while (*ps && !isspace(*ps) && *ps != '.')
    ps++;
  *e = ps;
  return *s < *e;
}

bool is_vowel(char c)
{
  return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}

enum {A, MOD, BA, DA, LA, NAM, PREDA};

bool accept(int wn)
{
  if (pws == pwe) {
    if (!get_word_or_name(&pws, &pwe))
      return false;
  }
  bool result = false;
  switch (wn) {
  case A:
    result = pwe - pws == 1 && is_vowel(*pws);
    break;
  case MOD:
    result = pwe - pws == 2 && *pws == 'g' && is_vowel(*(pws + 1));
    break;
  case BA:
    result = pwe - pws == 2 && *pws == 'b' && is_vowel(*(pws + 1));
    break;
  case DA:
    result = pwe - pws == 2 && *pws == 'd' && is_vowel(*(pws + 1));
    break;
  case LA:
    result = pwe - pws == 2 && *pws == 'l' && is_vowel(*(pws + 1));
    break;
  case NAM:
    result = pwe > pws && !is_vowel(*(pwe - 1));
    break;
  case PREDA:
    result = pwe - pws == 5 && !is_vowel(*pws) && 
      (!is_vowel(*(pws + 1)) && is_vowel(*(pws + 2)) ||
        is_vowel(*(pws + 1)) && !is_vowel(*(pws + 2))) &&
      !is_vowel(*(pws + 3)) && is_vowel(*(pws + 4));
    break;
  }
  if (result)
    pws = pwe;
  return result;
}

void predclaim(), preds(), predname(), predstring(), statement(), verbpred();

void predclaim()
{
  if (accept(DA))
    preds();
  else {
    predname();
    if (accept(BA))
      preds();
    else
      throw -1;
  }
}

void preds()
{
  predstring();
  while (accept(A))
    predstring();
}

void predname()
{
  if (accept(LA))
    predstring();
  else if (accept(NAM))
    ;
  else
    throw -1;
}

void predstring()
{
  if (accept(PREDA)) {
    while (accept(PREDA))
    ;
  }
  else
    throw -1;
}

void statement()
{
  predname();
  verbpred();
  if (*ps && *ps != '.')
    predname();
}

void verbpred()
{
  if (accept(MOD))
    predstring();
  else
    throw -1;
}

int main()
{
  while (true) {
    string line;
    getline(cin, line);
    if (line[0] == '#')
      break;
    sentence.clear();
    while (true) {
      sentence += line;
      if (sentence.find_first_of('.') != string::npos)
        break;
      sentence += ' ';
      getline(cin, line);
    }
#ifdef DEBUG
    cout << sentence << endl;
#endif
//    transform(sentence.begin(), sentence.end(), sentence.begin(), (int(*)(int))tolower);
    bool good = false;
    try {
      ps = pws = pwe = sentence.c_str();
      statement();
      if (*ps == '.')
        good = true;
      else
        throw -1;
    }
    catch (int) {
      try {
        ps = pws = pwe = sentence.c_str();
        predclaim();
        if (*ps == '.')
          good = true;
      }
      catch (int) {
      }
    }
    cout << ((good) ? "Good\n" : "Bad!\n");
  }
  return 0;
}

No comments:

Post a Comment