def test_conflict_first_follow(): """ Valid input example but produces a first/follow conflict. """ TestParser._run(**{ 'name': 'First/Follow Conflict', 'productions': { '<S>': [['<A>', 'a', 'b']], '<A>': [['a'], []] }, 'start': '<S>', 'terminals': set(['a', 'b']), 'nonterminals': set(['<S>', '<A>']), 'first': { 'a': set(['a']), 'b': set(['b']), '<S>': set(['a']), '<A>': set(['a', ContextFreeGrammar.epsilon()]) }, 'follow': { '<S>': set([ContextFreeGrammar.end_of_input()]), '<A>': set(['a']) }, 'rules': [ ('<S>', ['<A>', 'a', 'b']), ('<A>', ['a']), ('<A>', []) ], 'table': [ [' ', 'a', ContextFreeGrammar.end_of_input(), 'b'], ['<S>', set([0]), set([]), set([])], ['<A>', set([1, 2]), set([]), set([])] ] })
def test_epsilon_absent(): """ Ensure the creation of a simple grammar goes as expected. """ TestParser._run(**{ 'name': 'No Epsilon', 'productions': { '<S>': [['<A>', 'a', '<A>', 'b'], ['<B>', 'b', '<B>', 'a']], '<A>': [[]], '<B>': [[]] }, 'start': '<S>', 'terminals': set(['a', 'b']), 'nonterminals': set(['<S>', '<A>', '<B>']), 'first': { 'a': set(['a']), 'b': set(['b']), '<S>': set(['a', 'b']), '<A>': set([ContextFreeGrammar.epsilon()]), '<B>': set([ContextFreeGrammar.epsilon()]) }, 'follow': { '<S>': set([ContextFreeGrammar.end_of_input()]), '<A>': set(['b', 'a']), '<B>': set(['a', 'b']) }, 'rules': [ ('<S>', ['<A>', 'a', '<A>', 'b']), ('<S>', ['<B>', 'b', '<B>', 'a']), ('<A>', []), ('<B>', []) ], 'table': [ [' ', ContextFreeGrammar.end_of_input(), 'a', 'b'], ['<S>', set([]), set([0]), set([1])], ['<A>', set([]), set([2]), set([2])], ['<B>', set([]), set([3]), set([3])] ] })
def test_ini(): """ Ensure the creation of the INI grammar goes as expected. """ TestParser._run(**{ 'name': 'INI', 'productions': { '<INI>': [['<SECTION>', '<INI>'], []], '<SECTION>': [['<HEADER>', '<SETTINGS>']], '<HEADER>': [['[', 'string', ']']], '<SETTINGS>': [['<KEY>', '<SEP>', '<VALUE>', '<SETTINGS>'], []], '<KEY>': [['string']], '<SEP>': [[':'], ['=']], '<VALUE>': [['string'], ['number'], ['bool']] }, 'start': '<INI>', 'terminals': set(['string', 'number', 'bool', ':', '=', '[', ']']), 'nonterminals': set(['<INI>', '<SECTION>', '<HEADER>', '<SETTINGS>', '<KEY>', '<SEP>', '<VALUE>']), 'first': { 'string': set(['string']), 'number': set(['number']), 'bool': set(['bool']), ':': set([':']), '=': set(['=']), '[': set(['[']), ']': set([']']), '<INI>': set([ContextFreeGrammar.epsilon(), '[']), '<SECTION>': set(['[']), '<HEADER>': set(['[']), '<SETTINGS>': set([ContextFreeGrammar.epsilon(), 'string']), '<KEY>': set(['string']), '<SEP>': set([':', '=']), '<VALUE>': set(['string', 'number', 'bool']) }, 'follow': { '<INI>': set([ContextFreeGrammar.end_of_input()]), '<SECTION>': set([ContextFreeGrammar.end_of_input(), '[']), '<HEADER>': set([ContextFreeGrammar.end_of_input(), '[', 'string']), '<SETTINGS>': set([ContextFreeGrammar.end_of_input(), '[']), '<KEY>': set([':', '=']), '<SEP>': set(['string', 'number', 'bool']), '<VALUE>': set([ContextFreeGrammar.end_of_input(), '[', 'string']) }, 'rules': [ ('<INI>', ['<SECTION>', '<INI>']), ('<INI>', []), ('<SECTION>', ['<HEADER>', '<SETTINGS>']), ('<HEADER>', ['[', 'string', ']']), ('<SETTINGS>', ['<KEY>', '<SEP>', '<VALUE>', '<SETTINGS>']), ('<SETTINGS>', []), ('<KEY>', ['string']), ('<SEP>', [':']), ('<SEP>', ['=']), ('<VALUE>', ['string']), ('<VALUE>', ['number']), ('<VALUE>', ['bool']) ], 'table': [[' ', ContextFreeGrammar.end_of_input(), 'bool', 'string', '=', '[', ':', ']', 'number'], ['<VALUE>', set([]), set([11]), set([9]), set([]), set([]), set([]), set([]), set([10])], ['<KEY>', set([]), set([]), set([6]), set([]), set([]), set([]), set([]), set([])], ['<SETTINGS>', set([5]), set([]), set([4]), set([]), set([5]), set([]), set([]), set([])], ['<SECTION>', set([]), set([]), set([]), set([]), set([2]), set([]), set([]), set([])], ['<HEADER>', set([]), set([]), set([]), set([]), set([3]), set([]), set([]), set([])], ['<SEP>', set([]), set([]), set([]), set([8]), set([]), set([7]), set([]), set([])], ['<INI>', set([1]), set([]), set([]), set([]), set([0]), set([]), set([]), set([])], ] })
def test_json(): """ Ensure the creation of the JSON grammar goes as expected. """ TestParser._run(**{ 'name': 'JSON', 'productions': { '<VALUE>': [ ['string'], ['number'], ['bool'], ['null'], ['<OBJECT>'], ['<ARRAY>'] ], '<OBJECT>': [['{', '<OBJECT\'>']], '<OBJECT\'>': [['}'], ['<MEMBERS>', '}']], '<MEMBERS>': [['<PAIR>', '<MEMBERS\'>']], '<PAIR>': [['string', ':', '<VALUE>']], '<MEMBERS\'>': [[',', '<MEMBERS>'], []], '<ARRAY>': [['[', '<ARRAY\'>']], '<ARRAY\'>': [[']'], ['<ELEMENTS>', ']']], '<ELEMENTS>': [['<VALUE>', '<ELEMENTS\'>']], '<ELEMENTS\'>': [[',', '<ELEMENTS>'], []] }, 'start': '<VALUE>', 'terminals': set(['{', '}', ',', '[', ']', ':', 'string', 'number', 'bool', 'null']), 'nonterminals': set(['<VALUE>', '<OBJECT>', '<OBJECT\'>', '<MEMBERS>', '<PAIR>', '<MEMBERS\'>', '<ARRAY>', '<ARRAY\'>', '<ELEMENTS>', '<ELEMENTS\'>']), 'first': { '{': set(['{']), '}': set(['}']), ',': set([',']), '[': set(['[']), ']': set([']']), ':': set([':']), 'string': set(['string']), 'number': set(['number']), 'bool': set(['bool']), 'null': set(['null']), '<VALUE>': set(['string', 'number', 'bool', 'null', '{', '[']), '<OBJECT>': set(['{']), '<OBJECT\'>': set(['}', 'string']), '<MEMBERS>': set(['string']), '<PAIR>': set(['string']), '<MEMBERS\'>': set([ContextFreeGrammar.epsilon(), ',']), '<ARRAY>': set(['[']), '<ARRAY\'>': set([']', 'string', 'number', 'bool', 'null', '{', '[']), '<ELEMENTS>': set(['string', 'number', 'bool', 'null', '{', '[']), '<ELEMENTS\'>': set([ContextFreeGrammar.epsilon(), ',']) }, 'follow': { '<VALUE>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']), '<OBJECT>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']), '<OBJECT\'>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']), '<MEMBERS>': set(['}']), '<PAIR>': set(['}', ',']), '<MEMBERS\'>': set(['}']), '<ARRAY>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']), '<ARRAY\'>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']), '<ELEMENTS>': set([']']), '<ELEMENTS\'>': set([']']) }, 'rules': [ ('<VALUE>', ['string']), ('<VALUE>', ['number']), ('<VALUE>', ['bool']), ('<VALUE>', ['null']), ('<VALUE>', ['<OBJECT>']), ('<VALUE>', ['<ARRAY>']), ('<OBJECT>', ['{', '<OBJECT\'>']), ('<OBJECT\'>', ['}']), ('<OBJECT\'>', ['<MEMBERS>', '}']), ('<MEMBERS>', ['<PAIR>', '<MEMBERS\'>']), ('<PAIR>', ['string', ':', '<VALUE>']), ('<MEMBERS\'>', [',', '<MEMBERS>']), ('<MEMBERS\'>', []), ('<ARRAY>', ['[', '<ARRAY\'>']), ('<ARRAY\'>', [']']), ('<ARRAY\'>', ['<ELEMENTS>', ']']), ('<ELEMENTS>', ['<VALUE>', '<ELEMENTS\'>']), ('<ELEMENTS\'>', [',', '<ELEMENTS>']), ('<ELEMENTS\'>', []) ], 'table': [[' ', ContextFreeGrammar.end_of_input(), ':', 'string', ']', 'number', ',', 'bool', '{', 'null', '}', '['], ['<PAIR>', set([]), set([]), set([10]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([])], ['<VALUE>', set([]), set([]), set([0]), set([]), set([1]), set([]), set([2]), set([4]), set([3]), set([]), set([5])], ['<OBJECT>', set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([6]), set([]), set([]), set([])], ['<ELEMENTS>', set([]), set([]), set([16]), set([]), set([16]), set([]), set([16]), set([16]), set([16]), set([]), set([16])], ['<OBJECT\'>', set([]), set([]), set([8]), set([]), set([]), set([]), set([]), set([]), set([]), set([7]), set([])], ['<MEMBERS\'>', set([]), set([]), set([]), set([]), set([]), set([11]), set([]), set([]), set([]), set([12]), set([])], ['<ARRAY>', set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([13])], ['<MEMBERS>', set([]), set([]), set([9]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([])], ['<ELEMENTS\'>', set([]), set([]), set([]), set([18]), set([]), set([17]), set([]), set([]), set([]), set([]), set([])], ["<ARRAY'>", set([]), set([]), set([15]), set([14]), set([15]), set([]), set([15]), set([15]), set([15]), set([]), set([15])] ] })
def test_simple_language(): """ Ensure the creation of a simple langugage grammar goes as expected. """ TestParser._run(**{ 'name': 'Simple language', 'productions': { '<STMT>': [ ['if', '<EXPR>', 'then', '<STMT>'], ['while', '<EXPR>', 'do', '<STMT>'], ['<EXPR>'] ], '<EXPR>': [ ['<TERM>', '->', 'id'], ['zero?', '<TERM>'], ['not', '<EXPR>'], ['++', 'id'], ['--', 'id'] ], '<TERM>': [['id'], ['constant']], '<BLOCK>': [['<STMT>'], ['{', '<STMTS>', '}']], '<STMTS>': [['<STMT>', '<STMTS>'], []] }, 'start': '<STMTS>', 'terminals': set(['if', 'then', 'while', 'do', '->', 'zero?', 'not', '++', '--', 'id', 'constant', '{', '}']), 'nonterminals': set(['<STMT>', '<STMTS>', '<BLOCK>', '<TERM>', '<EXPR>']), 'first': { 'if': set(['if']), 'then': set(['then']), 'while': set(['while']), 'do': set(['do']), '->': set(['->']), 'zero?': set(['zero?']), 'not': set(['not']), '++': set(['++']), '--': set(['--']), 'id': set(['id']), 'constant': set(['constant']), '{': set(['{']), '}': set(['}']), '<STMT>': set(['constant', '++', 'zero?', 'while', 'not', '--', 'id', 'if']), '<STMTS>': set([ContextFreeGrammar.epsilon(), 'constant', '++', 'zero?', 'while', 'not', '--', 'id', 'if']), '<BLOCK>': set(['constant', '++', 'zero?', 'while', 'not', '--', '{', 'id', 'if']), '<TERM>': set(['constant', 'id']), '<EXPR>': set(['++', 'not', 'constant', 'zero?', '--', 'id']) }, 'follow': { '<STMT>': set([ContextFreeGrammar.end_of_input(), 'constant', '++', 'not', 'while', 'zero?', '--', '}', 'id', 'if']), '<STMTS>': set([ContextFreeGrammar.end_of_input(), '}']), '<BLOCK>': set([]), '<TERM>': set([ContextFreeGrammar.end_of_input(), 'then', 'constant', 'do', 'not', 'id', 'if', '++', '--', 'while', 'zero?', '->', '}']), '<EXPR>': set([ContextFreeGrammar.end_of_input(), 'then', 'constant', 'do', '++', '--', 'while', 'not', 'zero?', '}', 'id', 'if']) }, 'rules': [ ('<STMT>', ['if', '<EXPR>', 'then', '<STMT>']), ('<STMT>', ['while', '<EXPR>', 'do', '<STMT>']), ('<STMT>', ['<EXPR>']), ('<EXPR>', ['<TERM>', '->', 'id']), ('<EXPR>', ['zero?', '<TERM>']), ('<EXPR>', ['not', '<EXPR>']), ('<EXPR>', ['++', 'id']), ('<EXPR>', ['--', 'id']), ('<TERM>', ['id']), ('<TERM>', ['constant']), ('<BLOCK>', ['<STMT>']), ('<BLOCK>', ['{', '<STMTS>', '}']), ('<STMTS>', ['<STMT>', '<STMTS>']), ('<STMTS>', []) ], 'table': [ [' ', ContextFreeGrammar.end_of_input(), 'then', 'constant', 'do', '++', 'zero?', 'while', 'not', '--', '{', '->', '}', 'id', 'if'], ['<STMT>', set([]), set([]), set([2]), set([]), set([2]), set([2]), set([1]), set([2]), set([2]), set([]), set([]), set([]), set([2]), set([0])], ['<EXPR>', set([]), set([]), set([3]), set([]), set([6]), set([4]), set([]), set([5]), set([7]), set([]), set([]), set([]), set([3]), set([])], ['<BLOCK>', set([]), set([]), set([10]), set([]), set([10]), set([10]), set([10]), set([10]), set([10]), set([11]), set([]), set([]), set([10]), set([10])], ['<STMTS>', set([13]), set([]), set([12]), set([]), set([12]), set([12]), set([12]), set([12]), set([12]), set([]), set([]), set([13]), set([12]), set([12])], ['<TERM>', set([]), set([]), set([9]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([8]), set([])] ] })
def test_epsilon_present(): """ Ensure the creation of a simple grammar containing an epsilon goes as expected. """ TestParser._run(**{ 'name': 'Epsilon', 'productions': { '<E>': [['<T>', '<E\'>']], '<E\'>': [['<A>', '<T>', '<E\'>'], []], '<A>': [['+'], ['-']], '<T>': [['<F>', '<T\'>']], '<T\'>': [['<M>', '<F>', '<T\'>'], []], '<M>': [['*']], '<F>': [['(', '<E>', ')'], ['id']] }, 'start': '<E>', 'terminals': set(['+', '-', '*', '(', ')', 'id']), 'nonterminals': set(['<E>', '<E\'>', '<A>', '<T>', '<T\'>', '<M>', '<F>']), 'first': { '+': set(['+']), '-': set(['-']), '*': set(['*']), '(': set(['(']), ')': set([')']), 'id': set(['id']), '<E>': set(['(', 'id']), '<E\'>': set(['+', '-', ContextFreeGrammar.epsilon()]), '<A>': set(['+', '-']), '<T>': set(['(', 'id']), '<T\'>': set([ContextFreeGrammar.epsilon(), '*']), '<M>': set(['*']), '<F>': set(['(', 'id']) }, 'follow': { '<E>': set([ContextFreeGrammar.end_of_input(), ')']), '<E\'>': set([ContextFreeGrammar.end_of_input(), ')']), '<A>': set(['(', 'id']), '<T>': set([')', '+', '-', ContextFreeGrammar.end_of_input()]), '<T\'>': set([')', '+', '-', ContextFreeGrammar.end_of_input()]), '<M>': set(['(', 'id']), '<F>': set([')', '+', '-', '*', ContextFreeGrammar.end_of_input()]) }, 'rules': [ ('<E>', ['<T>', '<E\'>']), ('<E\'>', ['<A>', '<T>', '<E\'>']), ('<E\'>', []), ('<A>', ['+']), ('<A>', ['-']), ('<T>', ['<F>', '<T\'>']), ('<T\'>', ['<M>', '<F>', '<T\'>']), ('<T\'>', []), ('<M>', ['*']), ('<F>', ['(', '<E>', ')']), ('<F>', ['id']) ], 'table': [ [' ', ContextFreeGrammar.end_of_input(), 'id', ')', '(', '+', '*', '-'], ['<E>', set([]), set([0]), set([]), set([0]), set([]), set([]), set([])], ['<E\'>', set([2]), set([]), set([2]), set([]), set([1]), set([]), set([1])], ['<A>', set([]), set([]), set([]), set([]), set([3]), set([]), set([4])], ['<T>', set([]), set([5]), set([]), set([5]), set([]), set([]), set([])], ['<T\'>', set([7]), set([]), set([7]), set([]), set([7]), set([6]), set([7])], ['<M>', set([]), set([]), set([]), set([]), set([]), set([8]), set([])], ['<F>', set([]), set([10]), set([]), set([9]), set([]), set([]), set([])] ] })
def test_conflict_left_recursion(): """ Valid input example but produces some conflicts due to the use of left recursion. """ TestParser._run(**{ 'name': 'Left Recursion', 'productions': { '<E>': [['<E>', '<A>', '<T>'], ['<T>']], '<A>': [['+'], ['-']], '<T>': [['<T>', '<M>', '<F>'], ['<F>']], '<M>': [['*']], '<F>': [['(', '<E>', ')'], ['id']] }, 'start': '<E>', 'terminals': set(['(', ')', '+', '*', '-', 'id']), 'nonterminals': set(['<E>', '<A>', '<T>', '<M>', '<F>']), 'first': { '(': set(['(']), ')': set([')']), '+': set(['+']), '-': set(['-']), '*': set(['*']), 'id': set(['id']), '<E>': set(['(', 'id']), '<A>': set(['+', '-']), '<T>': set(['(', 'id']), '<M>': set(['*']), '<F>': set(['(', 'id']) }, 'follow': { '<E>': set([ContextFreeGrammar.end_of_input(), '+', '-', ')']), '<A>': set(['(', 'id']), '<T>': set([ContextFreeGrammar.end_of_input(), '+', '-', '*', ')']), '<M>': set(['(', 'id']), '<F>': set([ContextFreeGrammar.end_of_input(), '+', '-', '*', ')']) }, 'rules': [ ('<E>', ['<E>', '<A>', '<T>']), ('<E>', ['<T>']), ('<A>', ['+']), ('<A>', ['-']), ('<T>', ['<T>', '<M>', '<F>']), ('<T>', ['<F>']), ('<M>', ['*']), ('<F>', ['(', '<E>', ')']), ('<F>', ['id']) ], 'table': [ [' ', ContextFreeGrammar.end_of_input(), 'id', ')', '(', '+', '*', '-'], ['<E>', set([]), set([0, 1]), set([]), set([0, 1]), set([]), set([]), set([])], ['<A>', set([]), set([]), set([]), set([]), set([2]), set([]), set([3])], ['<M>', set([]), set([]), set([]), set([]), set([]), set([6]), set([])], ['<T>', set([]), set([4, 5]), set([]), set([4, 5]), set([]), set([]), set([])], ['<F>', set([]), set([8]), set([]), set([7]), set([]), set([]), set([])] ] })
def test_lisp(): """ Ensure the creation of the Lisp grammar goes as expected. """ TestParser._run(**{ 'name': 'Lisp', 'productions': { '<expression>': [['<atom>'], ['<pair>']], '<pair>': [['(', '<expression>', '.', '<expression>', ')']], '<atom>': [ ['symbol'], ['character'], ['string'], ['boolean'], ['int'], ['float'], ['nil'] ] }, 'start': '<expression>', 'terminals': set(['(', '.', ')', 'symbol', 'character', 'string', 'boolean', 'int', 'float', 'nil']), 'nonterminals': set(['<atom>', '<pair>', '<expression>']), 'first': { '(': set(['(']), '.': set(['.']), ')': set([')']), 'symbol': set(['symbol']), 'character': set(['character']), 'string': set(['string']), 'boolean': set(['boolean']), 'int': set(['int']), 'float': set(['float']), 'nil': set(['nil']), '<atom>': set(['boolean', 'character', 'float', 'int', 'nil', 'string', 'symbol']), '<pair>': set(['(']), '<expression>': set(['(', 'boolean', 'character', 'float', 'int', 'nil', 'string', 'symbol']) }, 'follow': { '<atom>': set([ContextFreeGrammar.end_of_input(), ')', '.']), '<pair>': set([ContextFreeGrammar.end_of_input(), ')', '.']), '<expression>': set([ContextFreeGrammar.end_of_input(), ')', '.']) }, 'rules': [ ('<expression>', ['<atom>']), ('<expression>', ['<pair>']), ('<pair>', ['(', '<expression>', '.', '<expression>', ')']), ('<atom>', ['symbol']), ('<atom>', ['character']), ('<atom>', ['string']), ('<atom>', ['boolean']), ('<atom>', ['int']), ('<atom>', ['float']), ('<atom>', ['nil']) ], 'table': [ [' ', ContextFreeGrammar.end_of_input(), 'symbol', 'character', 'string', 'boolean', 'int', 'float', 'nil', '(', '.', ')'], ['<expression>', set([]), set([0]), set([0]), set([0]), set([0]), set([0]), set([0]), set([0]), set([1]), set([]), set([])], ['<atom>', set([]), set([3]), set([4]), set([5]), set([6]), set([7]), set([8]), set([9]), set([]), set([]), set([])], ['<pair>', set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([]), set([2]), set([]), set([])], ] })