Files
ls2tp/tests/test_lexer_parser.py
Hermes 9e997327e9 Initial commit: lexer, parser, tp_dump tool
- LSLexer: tokenisation complete du format LS Fanuc
- LSParser: AST pour programmes LS (mouvements, CALL, JMP, WAIT, IF)
- tp_dump: analyseur hexa TP avec header parsing et comparaison
- tp_format: structures du format binaire TP (V9.30)
- CLI: interface en ligne de commande (lex, parse, compile)
- Tests unitaires pour lexer et parser
2026-07-01 17:41:28 +00:00

149 lines
4.1 KiB
Python

"""
Tests unitaires pour ls2tp.
"""
import pytest
from ls2tp.lexer import LSLexer
from ls2tp.tokens import Token, TokenType
class TestLexer:
"""Tests du lexer LS."""
def test_empty(self):
lexer = LSLexer("")
tokens = lexer.tokenize()
assert len(tokens) == 1 # EOF
def test_program_header(self):
lexer = LSLexer("/PROG TESTPROG")
tokens = [t for t in lexer.tokenize() if t.type != TokenType.NEWLINE]
assert tokens[0].type == TokenType.PROGRAM
assert tokens[1].value == "TESTPROG"
def test_comment(self):
lexer = LSLexer("! ceci est un commentaire\nJ P[1]")
tokens = lexer.tokenize()
# Le commentaire n'est pas tokenizé, mais J, P, etc. oui
types = [t.type for t in tokens if t.type != TokenType.NEWLINE]
assert TokenType.J in types
assert TokenType.P in types
def test_motion_instruction(self):
src = "J P[1] 100% FINE"
lexer = LSLexer(src)
tokens = [t for t in lexer.tokenize() if t.type != TokenType.NEWLINE]
types = [t.type for t in tokens]
assert types == [
TokenType.J,
TokenType.P,
TokenType.LBRACKET,
TokenType.INTEGER,
TokenType.RBRACKET,
TokenType.INTEGER,
TokenType.PERCENT,
TokenType.FINE,
TokenType.EOF,
]
def test_register(self):
src = "R[5] = 42"
lexer = LSLexer(src)
tokens = [t for t in lexer.tokenize() if t.type != TokenType.NEWLINE]
types = [t.type for t in tokens]
assert types == [
TokenType.R,
TokenType.LBRACKET,
TokenType.INTEGER,
TokenType.RBRACKET,
TokenType.EQUAL,
TokenType.INTEGER,
TokenType.EOF,
]
def test_position_register(self):
src = "PR[10]"
lexer = LSLexer(src)
tokens = [t for t in lexer.tokenize() if t.type != TokenType.NEWLINE]
assert tokens[0].type == TokenType.PR
assert tokens[1].type == TokenType.LBRACKET
assert tokens[2].value == "10"
def test_call(self):
src = "CALL MONPROG(1, 2)"
lexer = LSLexer(src)
tokens = [t for t in lexer.tokenize() if t.type != TokenType.NEWLINE]
types = [t.type for t in tokens]
assert types[:4] == [TokenType.CALL, TokenType.STRING,
TokenType.LPAREN, TokenType.INTEGER]
def test_string(self):
src = 'R[1] = "hello"'
lexer = LSLexer(src)
tokens = [t for t in lexer.tokenize() if t.type != TokenType.NEWLINE]
assert TokenType.STRING in [t.type for t in tokens]
def test_negative_number(self):
src = "R[1] = -5"
lexer = LSLexer(src)
tokens = [t for t in lexer.tokenize() if t.type != TokenType.NEWLINE]
values = [t.value for t in tokens if t.type == TokenType.INTEGER]
assert "-5" in values
class TestParser:
"""Tests du parser LS."""
def test_simple_program(self):
from ls2tp.parser import LSParser
src = """/PROG TEST
/MN
: J P[1] 100% FINE ;
: L P[2] 2000mm/sec CNT50 ;
: CALL INIT ;
END
"""
lexer = LSLexer(src)
tokens = lexer.tokenize()
parser = LSParser(tokens)
prog = parser.parse()
assert prog.name == "TEST"
assert len(prog.body) > 0
def test_program_with_comment(self):
from ls2tp.parser import LSParser
src = """/PROG TESTPROG
COMMENT = "test"
/MN
: ! mouvement rapide
: J P[1] 100% FINE ;
END
"""
lexer = LSLexer(src)
tokens = lexer.tokenize()
parser = LSParser(tokens)
prog = parser.parse()
assert prog.name == "TESTPROG"
assert len(prog.headers) > 0
def test_label_and_jump(self):
from ls2tp.parser import LSParser
src = """/PROG JUMPTEST
: LBL[1] ;
: J P[1] 50% FINE ;
: JMP LBL[1] ;
END
"""
lexer = LSLexer(src)
tokens = lexer.tokenize()
parser = LSParser(tokens)
prog = parser.parse()
assert prog.name == "JUMPTEST"
if __name__ == '__main__':
pytest.main([__file__, '-v'])