Allow variables in input, such as "A(3,y)".

portnov [2008-12-14 08:56:30]
Allow variables in input, such as "A(3,y)".
Filename
data.py
lexer.py
parser.out
parsetab.py
syntax.py
diff --git a/data.py b/data.py
index a8b704f..5008fdd 100644
--- a/data.py
+++ b/data.py
@@ -71,28 +71,44 @@ class NothingClass(object):
 Nothing = NothingClass()

 class Unknown(object):
-    def __init__(self,name='',add=True):
+    def __init__(self,name='',add=True,value=None):
         self.name = name
         if add:
-            unknowns[name] = None
+            unknowns[name] = value

     def __repr__(self):
         return self.name

     def __add__(self,e):
+        if is_number(e) and e==0:
+            return self
         return Expr('+',self,e)

     def __sub__(self,e):
         return self + Expr('*',-1,e)

     def __mul__(self,e):
+        if is_number(e) and e==1:
+            return self
         return Expr('*',self,e)
+
+    def __pow__(self,e):
+        if is_number(e) and e==1.0:
+            return self
+        return Expr('^', self,e)
+
+    def __div__(self,e):
+        if is_number(e) and e==1:
+            return self
+        return Expr('/',self,e)

 class Const(float):
     def __init__(self,x):
         float.__init__(self,x)

     def __add__(self,e):
+        if self == 0:
+            return e
         if is_number(e):
             return float.__add__(self,e)
         if is_nothing(e):
@@ -112,6 +128,8 @@ class Const(float):
         return self + Expr('*',-1,e)

     def __mul__(self,e):
+        if self == 1.0:
+            return e
         if is_number(e):
             return float.__mul__(self,e)
         if is_nothing(e):
@@ -147,11 +165,11 @@ def line_by_two_points(A,B):

 class Point(object):
     def __init__(self,name,x,y):
-        if isinstance(x, Unknown):
+        if isinstance(x, Unknown) and not x.name:
             self.x = Unknown(name+'x')
         else:
             self.x = x
-        if isinstance(y, Unknown):
+        if isinstance(y, Unknown) and not y.name:
             self.y = Unknown(name+'y')
         else:
             self.y = y
@@ -321,7 +339,10 @@ class Expr(object):
         return Expr('+',self,e)

     def __sub__(self,e):
-        return self + Expr('*',-1,e)
+        return self + Expr('*',Const(-1),e)
+
+    def __neg__(self):
+        return Expr('*',Const(-1),self)

     def __mul__(self,e):
         if is_number(e):
diff --git a/lexer.py b/lexer.py
index a87aaf7..e5c0d02 100644
--- a/lexer.py
+++ b/lexer.py
@@ -1,13 +1,13 @@

 from ply import lex
-from data import Const
+from data import Const, Unknown

-tokens = ('POINT','SEGMENT', 'IN', 'PARAL', 'PERP', 'EQ', 'PARENL', 'PARENR', 'COMMA','NUMBER')
+tokens = ('POINT','SEGMENT', 'IN', 'PARAL', 'PERP', 'EQ', 'PARENL', 'PARENR', 'COMMA','NUMBER','VAR')

 t_POINT = '[A-Z]'
 t_SEGMENT = '[A-Z][A-Z]'

-t_IN = 'in'
+t_IN = '<-'
 t_PARAL = '\|\|'
 t_PERP = '_\|_'
 t_EQ = '='
@@ -24,4 +24,9 @@ def t_NUMBER(t):
     t.value = Const(t.value)
     return t

+def t_VAR(t):
+    "[a-z][0-9]?"
+    t.value = Unknown(t.value,value=Unknown(t.value))
+    return t
+
 lex.lex()
diff --git a/parser.out b/parser.out
index 3c78c00..9c8f278 100644
--- a/parser.out
+++ b/parser.out
@@ -10,27 +10,31 @@ Rule 2     statement -> SEGMENT PARAL SEGMENT
 Rule 3     statement -> SEGMENT PERP SEGMENT
 Rule 4     statement -> POINT IN SEGMENT
 Rule 5     statement -> SEGMENT EQ SEGMENT
-Rule 6     statement -> SEGMENT EQ NUMBER
-Rule 7     statement -> POINT PARENL NUMBER COMMA NUMBER PARENR
+Rule 6     statement -> SEGMENT EQ value
+Rule 7     statement -> POINT PARENL value COMMA value PARENR
+Rule 8     value -> NUMBER
+Rule 9     value -> VAR

 Terminals, with rules where they appear

 COMMA                : 7
 EQ                   : 5 6
 IN                   : 4
-NUMBER               : 6 7 7
+NUMBER               : 8
 PARAL                : 2
 PARENL               : 7
 PARENR               : 7
 PERP                 : 3
 POINT                : 4 7
 SEGMENT              : 2 2 3 3 4 5 5 6
+VAR                  : 9
 error                :

 Nonterminals, with rules where they appear

 generic              : 0
 statement            : 1
+value                : 6 7 7


 Parsing method: LALR
@@ -44,8 +48,8 @@ state 0
     (3) statement -> . SEGMENT PERP SEGMENT
     (4) statement -> . POINT IN SEGMENT
     (5) statement -> . SEGMENT EQ SEGMENT
-    (6) statement -> . SEGMENT EQ NUMBER
-    (7) statement -> . POINT PARENL NUMBER COMMA NUMBER PARENR
+    (6) statement -> . SEGMENT EQ value
+    (7) statement -> . POINT PARENL value COMMA value PARENR

     SEGMENT         shift and go to state 4
     POINT           shift and go to state 1
@@ -57,7 +61,7 @@ state 0
 state 1

     (4) statement -> POINT . IN SEGMENT
-    (7) statement -> POINT . PARENL NUMBER COMMA NUMBER PARENR
+    (7) statement -> POINT . PARENL value COMMA value PARENR

     IN              shift and go to state 5
     PARENL          shift and go to state 6
@@ -84,7 +88,7 @@ state 4
     (2) statement -> SEGMENT . PARAL SEGMENT
     (3) statement -> SEGMENT . PERP SEGMENT
     (5) statement -> SEGMENT . EQ SEGMENT
-    (6) statement -> SEGMENT . EQ NUMBER
+    (6) statement -> SEGMENT . EQ value

     PARAL           shift and go to state 9
     PERP            shift and go to state 8
@@ -102,27 +106,35 @@ state 5

 state 6

-    (7) statement -> POINT PARENL . NUMBER COMMA NUMBER PARENR
+    (7) statement -> POINT PARENL . value COMMA value PARENR
+    (8) value -> . NUMBER
+    (9) value -> . VAR

     NUMBER          shift and go to state 11
+    VAR             shift and go to state 13


+    value                          shift and go to state 12

 state 7

     (5) statement -> SEGMENT EQ . SEGMENT
-    (6) statement -> SEGMENT EQ . NUMBER
+    (6) statement -> SEGMENT EQ . value
+    (8) value -> . NUMBER
+    (9) value -> . VAR

-    SEGMENT         shift and go to state 12
-    NUMBER          shift and go to state 13
+    SEGMENT         shift and go to state 14
+    NUMBER          shift and go to state 11
+    VAR             shift and go to state 13


+    value                          shift and go to state 15

 state 8

     (3) statement -> SEGMENT PERP . SEGMENT

-    SEGMENT         shift and go to state 14
+    SEGMENT         shift and go to state 16



@@ -130,7 +142,7 @@ state 9

     (2) statement -> SEGMENT PARAL . SEGMENT

-    SEGMENT         shift and go to state 15
+    SEGMENT         shift and go to state 17



@@ -144,64 +156,88 @@ state 10

 state 11

-    (7) statement -> POINT PARENL NUMBER . COMMA NUMBER PARENR
+    (8) value -> NUMBER .

-    COMMA           shift and go to state 16
+    $end            reduce using rule 8 (value -> NUMBER .)
+    PARENR          reduce using rule 8 (value -> NUMBER .)
+    COMMA           reduce using rule 8 (value -> NUMBER .)



 state 12

-    (5) statement -> SEGMENT EQ SEGMENT .
+    (7) statement -> POINT PARENL value . COMMA value PARENR

-    $end            reduce using rule 5 (statement -> SEGMENT EQ SEGMENT .)
+    COMMA           shift and go to state 18



 state 13

-    (6) statement -> SEGMENT EQ NUMBER .
+    (9) value -> VAR .

-    $end            reduce using rule 6 (statement -> SEGMENT EQ NUMBER .)
+    $end            reduce using rule 9 (value -> VAR .)
+    PARENR          reduce using rule 9 (value -> VAR .)
+    COMMA           reduce using rule 9 (value -> VAR .)



 state 14

-    (3) statement -> SEGMENT PERP SEGMENT .
+    (5) statement -> SEGMENT EQ SEGMENT .

-    $end            reduce using rule 3 (statement -> SEGMENT PERP SEGMENT .)
+    $end            reduce using rule 5 (statement -> SEGMENT EQ SEGMENT .)



 state 15

-    (2) statement -> SEGMENT PARAL SEGMENT .
+    (6) statement -> SEGMENT EQ value .

-    $end            reduce using rule 2 (statement -> SEGMENT PARAL SEGMENT .)
+    $end            reduce using rule 6 (statement -> SEGMENT EQ value .)



 state 16

-    (7) statement -> POINT PARENL NUMBER COMMA . NUMBER PARENR
+    (3) statement -> SEGMENT PERP SEGMENT .

-    NUMBER          shift and go to state 17
+    $end            reduce using rule 3 (statement -> SEGMENT PERP SEGMENT .)



 state 17

-    (7) statement -> POINT PARENL NUMBER COMMA NUMBER . PARENR
+    (2) statement -> SEGMENT PARAL SEGMENT .

-    PARENR          shift and go to state 18
+    $end            reduce using rule 2 (statement -> SEGMENT PARAL SEGMENT .)



 state 18

-    (7) statement -> POINT PARENL NUMBER COMMA NUMBER PARENR .
+    (7) statement -> POINT PARENL value COMMA . value PARENR
+    (8) value -> . NUMBER
+    (9) value -> . VAR
+
+    NUMBER          shift and go to state 11
+    VAR             shift and go to state 13
+
+
+    value                          shift and go to state 19
+
+state 19
+
+    (7) statement -> POINT PARENL value COMMA value . PARENR
+
+    PARENR          shift and go to state 20
+
+
+
+state 20
+
+    (7) statement -> POINT PARENL value COMMA value PARENR .

-    $end            reduce using rule 7 (statement -> POINT PARENL NUMBER COMMA NUMBER PARENR .)
+    $end            reduce using rule 7 (statement -> POINT PARENL value COMMA value PARENR .)


diff --git a/parsetab.py b/parsetab.py
index 1b9b4ff..c5eca60 100644
--- a/parsetab.py
+++ b/parsetab.py
@@ -4,9 +4,9 @@

 _lr_method = 'LALR'

-_lr_signature = "'K\xe1\xf4\xb9.`<\x83\xcc:]\xa6\xcb\xff\xc5"
+_lr_signature = '\x92\x98\x85\xb9]z\xf7\x14\x8c\xbe\xd7pE\xaeh2'

-_lr_action_items = {'PARENR':([17,],[18,]),'POINT':([0,],[1,]),'EQ':([4,],[7,]),'NUMBER':([6,7,16,],[11,13,17,]),'PARAL':([4,],[9,]),'PERP':([4,],[8,]),'COMMA':([11,],[16,]),'IN':([1,],[5,]),'SEGMENT':([0,5,7,8,9,],[4,10,12,14,15,]),'PARENL':([1,],[6,]),'$end':([2,3,10,12,13,14,15,18,],[0,-1,-4,-5,-6,-3,-2,-7,]),}
+_lr_action_items = {'PARENR':([11,13,19,],[-8,-9,20,]),'POINT':([0,],[1,]),'EQ':([4,],[7,]),'NUMBER':([6,7,18,],[11,11,11,]),'PARAL':([4,],[9,]),'PERP':([4,],[8,]),'COMMA':([11,12,13,],[-8,18,-9,]),'IN':([1,],[5,]),'VAR':([6,7,18,],[13,13,13,]),'SEGMENT':([0,5,7,8,9,],[4,10,14,16,17,]),'PARENL':([1,],[6,]),'$end':([2,3,10,11,13,14,15,16,17,20,],[0,-1,-4,-8,-9,-5,-6,-3,-2,-7,]),}

 _lr_action = { }
 for _k, _v in _lr_action_items.items():
@@ -15,7 +15,7 @@ for _k, _v in _lr_action_items.items():
       _lr_action[_x][_k] = _y
 del _lr_action_items

-_lr_goto_items = {'generic':([0,],[2,]),'statement':([0,],[3,]),}
+_lr_goto_items = {'generic':([0,],[2,]),'value':([6,7,18,],[12,15,19,]),'statement':([0,],[3,]),}

 _lr_goto = { }
 for _k, _v in _lr_goto_items.items():
@@ -32,4 +32,6 @@ _lr_productions = [
   ('statement',3,'p_statement_eq_s','syntax.py',31),
   ('statement',3,'p_statement_eq_n','syntax.py',37),
   ('statement',6,'p_statement_point','syntax.py',43),
+  ('value',1,'p_value_number','syntax.py',48),
+  ('value',1,'p_value_var','syntax.py',52),
 ]
diff --git a/syntax.py b/syntax.py
index 8d113cd..66ea126 100644
--- a/syntax.py
+++ b/syntax.py
@@ -34,16 +34,23 @@ def p_statement_eq_s(t):
     t[0] = c

 def p_statement_eq_n(t):
-    "statement : SEGMENT EQ NUMBER"
+    "statement : SEGMENT EQ value"
     c = Condition(COND_EQ, segment(t[1]), t[3])
     conditions.append(c)
     t[0] = c

 def p_statement_point(t):
-    "statement : POINT PARENL NUMBER COMMA NUMBER PARENR"
+    "statement : POINT PARENL value COMMA value PARENR"
     p = Point(t[1],t[3],t[5])
     points[t[1]] = p
-    return p
+
+def p_value_number(t):
+    "value : NUMBER"
+    t[0] = t[1]
+
+def p_value_var(t):
+    "value : VAR"
+    t[0] = t[1]

 yacc.yacc()
ViewGit